OpenCV fill missing pixels

Viewed 1037

Maybe someone has ideas how can we fill black pixels to white on the white digits and make that image more adopted to be recognizable

enter image description here

I was trying the Gaussian Blur with Kernel size (1,1), but it doesn't help effectively, sometimes digits on image become merged and this is much worst result

1 Answers

You may use the equivalent to MATLAB imfill, but the result is going to be binary image.

I found a Python implementation for imfill here (it uses Scikit-image).

Here is the code:

import cv2
import numpy as np
from skimage.morphology import reconstruction

def imfill(img):
    # https://stackoverflow.com/questions/36294025/python-equivalent-to-matlab-funciton-imfill-for-grayscale
    # Use the matlab reference Soille, P., Morphological Image Analysis: Principles and Applications, Springer-Verlag, 1999, pp. 208-209.
    #  6.3.7  Fillhole
    # The holes of a binary image correspond to the set of its regional minima which
    # are  not  connected  to  the image  border.  This  definition  holds  for  grey scale
    # images.  Hence,  filling  the holes of a  grey scale image comes down  to remove
    # all  minima  which  are  not  connected  to  the  image  border, or,  equivalently,
    # impose  the  set  of minima  which  are  connected  to  the  image  border.  The
    # marker image 1m  used  in  the morphological reconstruction by erosion is set
    # to the maximum image value except along its border where the values of the
    # original image are kept:

    seed = np.ones_like(img)*255
    img[ : ,0] = 0
    img[ : ,-1] = 0
    img[ 0 ,:] = 0
    img[ -1 ,:] = 0
    seed[ : ,0] = 0
    seed[ : ,-1] = 0
    seed[ 0 ,:] = 0
    seed[ -1 ,:] = 0

    fill_img = reconstruction(seed, img, method='erosion')

    return fill_img

img = cv2.imread('5375.jpg', cv2.IMREAD_GRAYSCALE)  # Read image as grayscale

img_thresh = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)[1]  # Convert to B/W

fill_img = imfill(img_thresh)

cv2.imshow('img', img)
cv2.imshow('fill_img', fill_img)
cv2.waitKey()
cv2.destroyAllWindows()

Result:

enter image description here

Note:
You may get the same result using cv2.findContours and drawContours, but you should apply findContours on img_thresh.


In case you want closer result to the original image, you may use closing morphological operation, and use 'fill_img' as a mask:

closed_img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, np.ones((35, 35)))
closed_img[fill_img == 0] = 0  # Set to zero where fill_img is zero.

Result:
enter image description here

Related