'Improve contour detection

The bubbles are the target of contour detection

I would like to detect the contour of the bubble in the photo. However, no matter what kind of contour detection I used, my program would not detect the whole contour lines. I tried with erosion, blur and morphologyEx methods to make the contour continuous, but it seems the bubble shape has changed completely. May I ask is there other method that can help me correctly draw the bubble contour similar as original photo? My code is as following:

    cv2.imshow(self.window_name, clone)
    canvas = cv2.imshow('canvas', canvas)
    # waiting for the user to press any key
    imageThresh = cv2.adaptiveThreshold(cloneG, 200, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 3, 11)
    bubble_only = cv2.bitwise_and(imageThresh, imageThresh, mask = VA_mask)
    thresh = cv2.adaptiveThreshold(bubble_only, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 3, 9)
    kernel1 = np.ones((2,2), np.uint8)
    
    # Perform morphological hit-or-miss for
    erosion = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel1, iterations = 2)
    
    # Inverted this image and blurred it with a kernel size of 4
    ret, thresh1 = cv2.threshold(erosion, 127, 255, 1)
    blur = cv2.blur(thresh1, (4,4))
    
    # Again perform another threshold on this image to get the central portion of the edge
    ret, thresh2 = cv2.threshold(blur, 145, 255, 0)
    
    # Perform morphological dilation to thin the edge. Use an ellipse structuring element of kernel size of 2
    kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (1,1))
    final = cv2.morphologyEx(thresh2, cv2.MORPH_ERODE, kernel2, iterations = 2)
    
    # find the contour then fill the contour
    mask = np.zeros(clone.shape[:2], dtype = 'uint8')
    contours, hier = cv2.findContours(final, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    bubble_shade = cv2.drawContours(mask, contours, -1, color = (255,255,255), thickness=cv2.FILLED)
    area = []
    
    for contour in contours:
        cnt_Area = cv2.contourArea(contour)
        area.append(cnt_Area)
    print(sorted(area))
    
    cv2.imwrite('bubble_shade.jpg', bubble_shade)
    
    cv2.waitKey()
    cv2.destroyAllWindows()
    return clone

Detected bubble contour



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source