Recognize open and closed shapes opencv

前端 未结 4 929
终归单人心
终归单人心 2020-12-04 17:17

how to detect open and closed shapes in opencv.

\"enter

These are simple sampl

相关标签:
4条回答
  • 2020-12-04 17:31

    The answer depends on your image, more specifically, how many contours are preset, is there are other objects, noise, etc. In a simple case of a single contour flood fill started inside of the closed contour won’t spill over the whole image; if started outside it won’t get in the middle. So you would preserve some white area in both cases.

    0 讨论(0)
  • 2020-12-04 17:32

    Python implementation of the same as below.

    import cv2
    
    
    src = cv2.imread('test.png', cv2.IMREAD_COLOR)
    
    #Transform source image to gray if it is not already
    if len(src.shape) != 2:
        gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
    else:
        gray = src
    
    ret, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
    hierarchy = hierarchy[0]
    
    for i, c in enumerate(contours):
        if hierarchy[i][2] < 0 and hierarchy[i][3] < 0:
            cv2.drawContours(src, contours, i, (0, 0, 255), 2)
        else:
            cv2.drawContours(src, contours, i, (0, 255, 0), 2)
    #write to the same directory
    cv2.imwrite("result.png", src)
    
    0 讨论(0)
  • 2020-12-04 17:37

    While correct for the problem posed, @Haris helpful answer should not be taken as a general solution for identifying closed contours using findContours().

    One reason is that a filled object will have no internal contour and so would return hierarchy[i][2] = -1, meaning this test on its own would wrongly label such contours as 'open'.

    The contour of a filled object should have no child or parent in the contour hierarchy, i.e. be at top level. So to detect for closed contours of filled objects would at least require an additional test: if(hierarchy[i][2] < 0 && hierarchy[i][3] < 0).

    I think @Haris answer may have made this point obliquely but I thought it worth clarifying for people, like myself, who are learning how to use opencv.

    0 讨论(0)
  • 2020-12-04 17:40

    Just use findContours() in your image, then decide whether the contour is closed or not by examining the hierarchy passed to the findContours() function. From the second figure it is clearer that no contour has child contour as compared to the first image, you will get this data from hierarchy parameter which is optional output vector, containing information about the image topology. It has as many elements as the number of contours.

    Here we will use hierarchy as

    vector< Vec4i > hierarchy
    

    where for an i-th contour

    hierarchy[i][0] = next contour at the same hierarchical level
    hierarchy[i][1] = previous contour at the same hierarchical level
    hierarchy[i][2] = denotes its first child contour
    hierarchy[i][3] = denotes index of its parent contour
    

    If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative. See findContours() function for more details.

    So by checking the value hierarchy[i][2] you can decide the contour belongs to closed or not, that is for a contour if the hierarchy[i][2] = -1 then no child and it belongs to opened.

    And one more thing is that in findContours() function you should use CV_RETR_CCOMP which retrieves all of the contours and organizes them into a two-level hierarchy.

    Here is the C++ code how to implement this.

        Mat tmp,thr;
        Mat src=imread("1.png",1);
        cvtColor(src,tmp,CV_BGR2GRAY);
        threshold(tmp,thr,200,255,THRESH_BINARY_INV);
    
        vector< vector <Point> > contours; // Vector for storing contour
        vector< Vec4i > hierarchy;
        findContours( thr, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
    
        for( int i = 0; i< contours.size(); i=hierarchy[i][0] ) // iterate through each contour.
        {
            Rect r= boundingRect(contours[i]);
            if(hierarchy[i][2]<0) //Check if there is a child contour
              rectangle(src,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,0,255),2,8,0); //Opened contour
            else
              rectangle(src,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,255,0),2,8,0); //closed contour
        }
    

    Result:

    enter image description here

    0 讨论(0)
提交回复
热议问题