Using hierarchy in findContours () in OpenCV?
Asked Answered
C

2

35

When finding contours, I used the CV_RETR_CCOMP argument. This is supposed to create a two level hierarchy - the the first level are for outer contours, the second level are for boundaries of the holes. However, I have never used a hierarchy before so I am not familiar with this.

Could someone instruct my on how to access the boundaries of the holes only? I want to disregard the outer contours and only draw the hole boundaries. Code examples will be appreciated. I am using the C++ interface not the C, so please don't suggest C functions (i.e. use findContours () instead of cvFindContours ()).

Create answered 11/12, 2011 at 2:47 Comment(1)
Going between the C++ version and the C version is trivial. FYI.Emperor
P
49

The hierarchy returned by findContours has the following form: hierarchy[idx][{0,1,2,3}]={next contour (same level), previous contour (same level), child contour, parent contour}

CV_RETR_CCOMP, returns a hierarchy of outer contours and holes. This means elements 2 and 3 of hierarchy[idx] have at most one of these not equal to -1: that is, each element has either no parent or child, or a parent but no child, or a child but no parent.

An element with a parent but no child would be a boundary of a hole.

That means you basically go through hierarchy[idx] and draw anything with hierarchy[idx][3]>-1.

Something like (works in Python, but haven't tested the C++. Idea is fine though.):

findContours( image, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

if ( !contours.empty() && !hierarchy.empty() ) {

    // loop through the contours/hierarchy
    for ( int i=0; i<contours.size(); i++ ) {

        // look for hierarchy[i][3]!=-1, ie hole boundaries
        if ( hierarchy[i][3] != -1 ) {
            // random colour
            Scalar colour( (rand()&255), (rand()&255), (rand()&255) );
            drawContours( outImage, contours, i, colour );
        }
    }
}
Pinkston answered 12/12, 2011 at 0:59 Comment(3)
@Farhad make sure you do some testing. The hierarchy may not be what you expect. I tried this with your image from https://mcmap.net/q/450175/-finding-contours-in-opencv and the image frame was a parent, the outer contour was a child, and the inner contour was neither.Groovy
@Farhad Sorry, I meant the image frame was a child and the circle's outer contour was a parent.Groovy
Thanks, I guess I will have to find a way around it.Create
Y
4

AFAIK when using CV_RETR_CCOMP, all the holes are on the same level.

int firstHoleIndex = hierarchy[0][2];
for (int i = firstHoleIndex; i >= 0 ; i = hierarchy[i][0])
// contours.at(i) is a hole. Do something with it.
Yemen answered 11/9, 2013 at 12:6 Comment(1)
This won't work if the first contour has no holes in it.Lowgrade

© 2022 - 2024 — McMap. All rights reserved.