1

Using OpenCV for Python, I am trying to get a mask of the noise elements in a image to be later used as input for the cv.inpaint() function.

I am given a greyscale image (2D matrix with values from 0 to 255) in the input_mtx_8u variable, with noise (isolated polygons of very low values).

So far what I did was:

  1. get the edges in which the gradient is above 25:
laplacian = cv2.Laplacian(input_mtx_8u, cv2.CV_8UC1)
lapl_bin, lapl_bin_val = cv2.threshold(laplacian, 25, 255, cv2.THRESH_BINARY)
  1. get the contours of the artifacts
contours, _ = cv2.findContours(lapl_bin_val, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
  1. fill the contours identified
filled_mtx = input_mtx_8u.copy()
cv2.fillPoly(filled_mtx, contours, (255, 255, 0), 4)

For some reason, my 'filled polygons' are not completely filled (see figure). What can I be doing wrong?

enter image description here

plr108
  • 1,201
  • 11
  • 16
adlzanchetta
  • 151
  • 1
  • 14
  • 1
    To fill polygons, use -1 for the line thickness – fmw42 Sep 09 '20 at 18:45
  • Thanks for the suggestion, fmw42. But it is not clear to me where I should set the line tickness to -1. Neither cv2.findContours() or cv2.fillPoly() seem to have this argument, only cv2.drawContours(). So cv2.fillPoly() would depend on the output of cv2.drawContours()? – adlzanchetta Sep 09 '20 at 19:13
  • 1
    My mistake. I was thinking of drawContours. Are your polygons closed? If you get contours from edges, then those contours define the edges, not the polygons. Try thresholding your image and then get the contours of the thresholded white objects. It would be best if you show your input image and more code so that we can try to reproduce and modify it. – fmw42 Sep 09 '20 at 19:56
  • Does this [answer](https://stackoverflow.com/questions/51121978/how-to-fill-a-polyline-in-opencv) your question? – Ahmet Sep 09 '20 at 19:58
  • The answer from @fmw42 helped me finding the answer, Ahmet. I used the drawContours() to modify my matrix and get the filled contours, which were later used as the masks I was looking for. Thanks guys! – adlzanchetta Sep 09 '20 at 20:43

1 Answers1

0

As pointed by @fmw42 , a solution to get the contours filled is using drawContours() instead of fillPoly().

The final working code I got is:

# input_mtx_8u = 2D matrix with uint8 values from 0 to 255

laplacian = cv2.Laplacian(input_mtx_8u, cv2.CV_8UC1)
lapl_bin, lapl_bin_val = cv2.threshold(laplacian, 25, 255, cv2.THRESH_BINARY)

contours, _ = cv2.findContours(lapl_bin_val, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

inpaint_mask = np.zeros(input_mtx_8u.shape, dtype=np.uint8)
for contour in contours:
    cv2.drawContours(inpaint_mask, [contour], -1, (255, 0, 0), thickness=-1)

# inpaint_mask = can be used as the mask for cv2.inpaint()

Note that for some reason:

cv2.drawContours(input_mtx_cont, contours, -1, (255, 0, 0), thickness=-1)

does not work. One must loop and draw contour by contour...

adlzanchetta
  • 151
  • 1
  • 14