Search code examples
pythonopencvimage-preprocessing

How to fill contour of connected edge and crop the image out in python?


click to view the image

the left side is the original image and I've used canny edge detection method to only get the outer edge of the image as you can see from the right side image. Now is it possible to fill the connected edge with white color and crop the image? Sorry i'm quite new in image processing


Solution

  • Always best if you provide separate images.

    Here is one way to do that in Python/OpenCV.

    • Read the image as grayscale
    • Threshold
    • Apply morphology close
    • Get the one external contour
    • Get the bounding box coordinates of the contour
    • Draw the one white contour as filled on a black background
    • Crop the result
    • Save the results


    Input:

    enter image description here

    import cv2
    import numpy as np
    
    # load image
    img = cv2.imread("outline.png", cv2.IMREAD_GRAYSCALE)
    
    # threshold
    thresh = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY)[1]
    
    # apply close morphology
    #kernel = np.ones((5,5), np.uint8)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    
    # get bounding box coordinates from the one filled external contour
    filled = np.zeros_like(thresh)
    contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    the_contour = contours[0]
    x,y,w,h = cv2.boundingRect(the_contour)
    cv2.drawContours(filled, [the_contour], 0, 255, -1)
    
    # crop filled contour image
    result = filled.copy()
    result = result[y:y+h, x:x+w]
    
    # write result to disk
    cv2.imwrite("outline_thresh.png", thresh)
    cv2.imwrite("outline_filled.png", filled)
    cv2.imwrite("outline_cropped.png", result)
    
    # display results
    cv2.imshow("THRESH", thresh)
    cv2.imshow("FILLED", filled)
    cv2.imshow("CROPPED", result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    


    Threshold image:

    enter image description here

    Filled contour image:

    enter image description here

    Cropped image:

    enter image description here

    An alternate to using a filled contour would be to flood fill the interior.