Search code examples
pythonopencv3.0contourflood-fill

How to enclose the irregular figure contour and fill it with with 5px dots in opencv using python?


This is my

Input Image

I want to get this

Output Image

but the problem is I am not able to enclose the contour and how should I add these dots? Does Open cv have any such function to handle this? So basically, The first problem is how to enclose this image Second, how to add Dots.

Thank you


Solution

  • Here is one way to do that in Python/OpenCV. However, I cannot close your dotted outline without connecting separate regions. But it will give you some idea how to proceed with most of what you want to do.

    If you manually add a few more dots to your input image where there are large gaps, then the morphology kernel can be made smaller such that it can connected the regions without merging separate parts that should remain isolated.

    • Read the input
    • Convert to grayscale
    • Threshold to binary
    • Apply morphology close to try to close the dotted outline. Unfortunately it connected separate regions.
    • Get the external contours
    • Draw white filled contours on a black background as a mask
    • Draw a single black circle on a white background
    • Tile out the circle image to the size of the input
    • Mask the tiled circle image with the filled contour image
    • Save results

    Input:

    enter image description here

    import cv2
    import numpy as np
    import math
    
    # read input image
    img = cv2.imread('island.png')
    hh, ww = img.shape[:2]
    
    # convert img to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # threshold 
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
    
    # use morphology to close figure
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (35,35))
    morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, )
    
    # find contours and bounding boxes
    mask = np.zeros_like(thresh)
    contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    for cntr in contours:
        cv2.drawContours(mask, [cntr], 0, 255, -1)
    
    # create a single tile as black circle on white background
    circle = np.full((11,11), 255, dtype=np.uint8)
    circle = cv2.circle(circle, (7,7), 3, 0, -1)
    
    # tile out the tile pattern to the size of the input
    numht = math.ceil(hh / 11)
    numwd = math.ceil(ww / 11)
    tiled_circle = np.tile(circle, (numht,numwd))
    tiled_circle = tiled_circle[0:hh, 0:ww]
    
    # composite tiled_circle with mask
    result = cv2.bitwise_and(tiled_circle, tiled_circle, mask=mask)
    
    # save result
    cv2.imwrite("island_morph.jpg", morph)
    cv2.imwrite("island_mask.jpg", mask)
    cv2.imwrite("tiled_circle.jpg", tiled_circle)
    cv2.imwrite("island_result.jpg", result)
    
    # show images
    cv2.imshow("morph", morph)
    cv2.imshow("mask", mask)
    cv2.imshow("tiled_circle", tiled_circle)
    cv2.imshow("result", result)
    cv2.waitKey(0)
    

    Morphology connected image:

    enter image description here

    Contour Mask image:

    enter image description here

    Tiled circles:

    enter image description here

    Result:

    enter image description here