Khizar
Khizar

Reputation: 45

OpenCv image inpaint left some marks of inpainted areas

I have an image with components, i have created a mask and extracted red colored regions out of it, then applied some inpainting on the components with some threshold size of component... but when i apply cv2.inpaint, it leaves some marks of red color behind.... i am not sure why... Here is the code.

lower_red = np.array([0,220,0]) #lower red color limit
upper_red = np.array([100,255,255]) # upper limit
mask = cv2.inRange(hsv,lower_red,upper_red) # masking red colored areas
nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(mask, 8) # finding components
sizes = stats[1:, -1]; nb_components = nb_components - 1 # getting areas of each component
min_size = 800  # threshold of component size 
inpaint_mask = np.zeros((output.shape))
for i in range(0, nb_components):
    if sizes[i] <= min_size:
        inpaint_mask[output == i + 1] = 255
inpaint_mask = inpaint_mask.astype('uint8')
dst = cv2.inpaint(src = rgb,inpaintMask=inpaint_mask,inpaintRadius=10, flags = cv2.INPAINT_TELEA)
plt.figure(figsize=(20,20),dpi=80)
plt.imshow(dst)

Here is the input image:

enter image description here

Output image:

enter image description here

Upvotes: 1

Views: 1276

Answers (1)

Rotem
Rotem

Reputation: 32114

The mask is too tight around the red regions, so inpaint takes the red-yellow color of the perimeter.

Zoom in to see that the perimeter is mixed with yellow color:

enter image description here

The range of lower_red and upper_red is too small, and you may also dilate inpaint_mask to include the surrounding area (include all the red-yellow perimeter in the mask).

You didn't post the first part of your code.
I assume hsv is the rgb image converted to HSV.

  • Increase the range to include all red pixels for including more of the red-yellow pixels:

     lower_red = np.array([0, 150, 0])  # lower red color limit
     upper_red = np.array([200, 255, 255])  # upper limit
    
  • Dilate inpaint_mask to include some of the surrounding area in the mask:

     inpaint_mask = cv2.dilate(inpaint_mask, np.ones((5, 5)))
    

Complete code sample:

import cv2
import numpy as np

bgr = cv2.imread('input.png')  # Use BGR instead of RGB for later using cv2.imshow instead of plt.imshow

hsv = cv2.cvtColor(bgr, cv2.COLOR_BGR2HSV)

#lower_red = np.array([0, 220, 0]) #lower red color limit
#upper_red = np.array([100, 255, 255]) # upper limit
lower_red = np.array([0, 150, 0]) #lower red color limit
upper_red = np.array([200, 255, 255]) # upper limit
mask = cv2.inRange(hsv, lower_red, upper_red) # masking red colored areas

nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(mask, 8) # finding components
sizes = stats[1:, -1]; nb_components = nb_components - 1 # getting areas of each component
min_size = 800  # threshold of component size 
inpaint_mask = np.zeros((output.shape))

for i in range(0, nb_components):
    if sizes[i] <= min_size:
        inpaint_mask[output == (i + 1)] = 255

inpaint_mask = inpaint_mask.astype('uint8')

# Dilate the mask
inpaint_mask = cv2.dilate(inpaint_mask, np.ones((5, 5)))

dst = cv2.inpaint(src=bgr, inpaintMask=inpaint_mask, inpaintRadius=10, flags=cv2.INPAINT_TELEA)

cv2.imshow("dst", dst)
cv2.waitKey()
cv2.destroyAllWindows()

Upvotes: 1

Related Questions