Search code examples
image-processingopencvjavacv

Filling holes inside a binary object


I have a problem with filling white holes inside a black coin so that I can have only 0-255 binary images with filled black coins. I have used a Median filter to accomplish it but in that case connection bridge between coins grows and it goes impossible to recognize them after several times of erosion... So I need a simple floodFill like method in opencv

Here is my image with holes:

enter image description here

EDIT: floodfill like function must fill holes in big components without prompting X, Y coordinates as a seed...

EDIT: I tried to use the cvDrawContours function but it doesn't fill contours inside bigger ones.

Here is my code:

        CvMemStorage mem = cvCreateMemStorage(0);
        CvSeq contours = new CvSeq();
        CvSeq ptr = new CvSeq();
        int sizeofCvContour = Loader.sizeof(CvContour.class);
        
        cvThreshold(gray, gray, 150, 255, CV_THRESH_BINARY_INV);
        
        int numOfContours = cvFindContours(gray, mem, contours, sizeofCvContour, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
        System.out.println("The num of contours: "+numOfContours); //prints 87, ok
        
        Random rand = new Random();
        for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
            Color randomColor = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat());
            CvScalar color = CV_RGB( randomColor.getRed(), randomColor.getGreen(), randomColor.getBlue());
            cvDrawContours(gray, ptr, color, color, -1, CV_FILLED, 8);
        }
        CanvasFrame canvas6  = new CanvasFrame("drawContours");
        canvas6.showImage(gray);

Result: (you can see black holes inside each coin)

enter image description here


Solution

  • There are two methods to do this:

    1) Contour Filling:

    First, invert the image, find contours in the image, fill it with black and invert back.

    des = cv2.bitwise_not(gray)
    contour,hier = cv2.findContours(des,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
    
    for cnt in contour:
        cv2.drawContours(des,[cnt],0,255,-1)
    
    gray = cv2.bitwise_not(des)
    

    Resulting image:

    enter image description here

    2) Image Opening:

    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
    res = cv2.morphologyEx(gray,cv2.MORPH_OPEN,kernel)
    

    The resulting image is as follows:

    enter image description here

    You can see, there is not much difference in both cases.

    NB: gray - grayscale image, All codes are in OpenCV-Python


    Reference. OpenCV Morphological Transformations