Search code examples
pythonopencvscipycomputer-visionflood-fill

Expanding background color to connected components(Flood fill) - Image Processing


kinda stuck trying to figure out how I can expand the background color inwards. I have this image that has been generated through a mask after noisy background subtraction.

enter image description here

I am trying to make it into this:

enter image description here

So far I have tried to this, but to no avail:

import cv2
from PIL import Image
import numpy as np

Image.open("example_of_misaligned_frame.png") # open poor frame

img_copy = np.asanyarray(img).copy()

contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX) # find contours 

# create bounding box around blob and figure out the row.cols to iterate over
x,y,w,h = cv2.boundingRect(max(contours, key = cv2.contourArea)) 

# flood fill the entire region with back, hoping that off-white region gets filled due to connected components.
for row in range(y, y+h):
    for col in range(x, x+w):
        cv2.floodFill(img_copy, None, seedPoint=(col,row), newVal=0)

This results in a completely black image :(

Any help, pointing me in the right direction, is greatly appreciated.


Solution

  • You can solve it by using floodFill twice:

    • First time - fill the black pixels with Off-White color.
    • Second time - fill the Off-White pixels with black color.

    There is still an issue for finding the RGB values of the Off-White color.
    I found an improvised solution for finding the Off-White color (I don't know the exact rules for what color is considered to be background).

    Here is a working code sample:

    import cv2
    import numpy as np
    
    #Image.open("example_of_misaligned_frame.png") # open poor frame
    img = cv2.imread("example_of_misaligned_frame.png")
    
    #img_copy = np.asanyarray(img).copy()
    img_copy = img.copy()
    
    #Improvised way to find the Off White color (it's working because the Off White has the maximum color components values).
    tmp = cv2.dilate(img, np.ones((50,50), np.uint8), iterations=10)
    
    # Color of Off-White pixel
    offwhite = tmp[0, 0, :]
    
    # Convert to tuple
    offwhite = tuple((int(offwhite[0]), int(offwhite[1]), int(offwhite[2])))
    
    # Fill black pixels with off-white color
    cv2.floodFill(img_copy, None, seedPoint=(0,0), newVal=offwhite)
    
    # Fill off-white pixels with black color
    cv2.floodFill(img_copy, None, seedPoint=(0,0), newVal=0, loDiff=(2, 2, 2, 2), upDiff=(2, 2, 2, 2))
    
    cv2.imshow("img_copy", img_copy)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    Result of cv2.dilate:
    enter image description here

    Result of first cv2.floodFill:
    enter image description here

    Result of second cv2.floodFill:
    enter image description here