2

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

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Taras Vovkovych
  • 4,062
  • 2
  • 16
  • 21
  • @ChristophRackwitz After the pixels filled well the contours for this image will be found well, and then we can use matchtemplate function to recognise each digit. Hope it's clear – Taras Vovkovych Jun 19 '21 at 21:46
  • 2
    Try morphological closing... https://docs.opencv.org/master/d9/d61/tutorial_py_morphological_ops.html – Mark Setchell Jun 19 '21 at 21:48
  • @mark-setchell it may close the digits nearby and spoil the next contours search. But it is idea, thanks, will try – Taras Vovkovych Jun 19 '21 at 21:51

1 Answers1

5

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

Rotem
  • 30,366
  • 4
  • 32
  • 65