user2790954
user2790954

Reputation: 111

Search for contours within a contour / OpenCV c++

I am trying to track a custom circular marker in an image, and I need to check that a circle contains a minimum number of other circles/objects. My code for finding circles is below:

void findMarkerContours( int, void* )
{   
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
vector<Point> approx;

cv::Mat dst = src.clone();

cv::Mat src_gray;
cv::cvtColor(src, src_gray, CV_BGR2GRAY);
//Reduce noise with a 3x3 kernel
blur( src_gray, src_gray, Size(3,3));

//Convert to binary using canny
cv::Mat bw;
cv::Canny(src_gray, bw, thresh, 3*thresh, 3);

imshow("bw", bw);


findContours(bw.clone(), contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

Mat drawing = Mat::zeros( bw.size(), CV_8UC3 );

for (int i = 0; i < contours.size(); i++)
{
    Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
    // contour
    drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );

    //Approximate the contour with accuracy proportional to contour perimeter
    cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true) *0.02, true);

    //Skip small or non-convex objects
    if(fabs(cv::contourArea(contours[i])) < 100 || !cv::isContourConvex(approx))
        continue;
    if (approx.size() >= 8) //More than 6-8 vertices means its likely a circle
    {
            drawContours( dst, contours, i, Scalar(0,255,0), 2, 8);
    }


    imshow("Hopefully we should have circles! Yay!", dst);

}

namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow( "Contours", drawing );

}

As you can see the code to detect circles works quite well:

But now I need to filter out markers that I do not want. My marker is the bottom one. So once I have found a contour that is a circle, I want to check if there are other circular contours that exist within the region of the first circle and finally check the color of the smallest circle.

What method can I take to say if (circle contains 3+ smaller circles || smallest circle is [color] ) -> do stuff?

Upvotes: 0

Views: 3578

Answers (2)

Tomas Camin
Tomas Camin

Reputation: 10086

Take a look at the documentation for

findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())

You'll see that there's an optional hierarchy output vector which should be handy for your problem.

hierarchy – Optional output vector, containing information about the image topology. It has as many elements as the number of contours. For each i-th contour contours[i] , the elements hierarchy[i][0] , hiearchyi , hiearchyi , and hiearchyi are set to 0-based indices in contours of the next and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.

When calling findCountours using CV_RETR_TREE you'll be getting the full hierarchy of each contour that was found.

This doc explains the hierarchy format pretty well.

Upvotes: 3

GPPK
GPPK

Reputation: 6666

You are already searching for circles of a certain size

//Skip small or non-convex objects
if(fabs(cv::contourArea(contours[i])) < 100 || !cv::isContourConvex(approx))
    continue;

So you can use that to look for smaller circles than the one youve got, instead of looking for < 100 look for contours.size

I imagine there is the same for color also...

Upvotes: 0

Related Questions