Ask Your Question
1

Help detecting/tracking circles with findContours

asked 2014-11-24 05:39:57 -0600

MohZ gravatar image

updated 2015-09-30 11:03:11 -0600

Hello everyone,

I am a beginner with OpenCV and need some help for my project. For my project I need to detect color based objects and track them.

The detection part is done, I am using cvtColor to convert a RGB image to an HSV, and use then the inRange function. Now, for the detections of balls, I first made use of houghCircles, but it seems to be unstable. The (x,y) coordinates of the balls were always updated, even when the ball wasn't moving. This is why the circle that I draw around the ball is always changing of place.

I decided to go for a second approach, with findContours. Here the code:

//these two vectors needed for output of findContours
vector< vector<Point> > contours;
vector<Vec4i> hierarchy;
//find contours of filtered image using openCV findContours function
findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );
double refArea = 0;
bool objectFound = false;
if (hierarchy.size() > 0) {
    int numObjects = hierarchy.size();
    //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter
    if(numObjects<MAX_NUM_OBJECTS){
        for (int index = 0; index >= 0; index = hierarchy[index][0]) {

            Moments moment = moments((cv::Mat)contours[index]);
            double area = moment.m00;

            //if the area is less than 20 px by 20px then it is probably just noise
            //if the area is the same as the 3/2 of the image size, probably just a bad filter
            //we only want the object with the largest area so we safe a reference area each
            //iteration and compare it to the area in the next iteration.
            if(area>MIN_OBJECT_AREA){

                Ball yellowBall;

                yellowBall.setXPos(moment.m10/area);
                yellowBall.setYPos(moment.m01/area);
                yellowBall.setType(yellowBall.getType());
                yellowBall.setColour(yellowBall.getColour());
                yBalls.push_back(yellowBall);

                objectFound = true;

            }else objectFound = false;


        }
        //let user know you found an object
        if(objectFound ==true){
            //draw object location on screen
            drawObject(yBalls,cameraFeed);}

    }else putText(cameraFeed,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2);
}

It works fine! Now my question is, is it possible to get the radius of the detected objects with this code ? If not, is it possible to get houghCircles more stable ?

Thanks!

edit retag flag offensive close merge delete

Comments

You will need to fit a houghCircle to your binary findContours output to get the radius of your blob. You can also retrieve the boundingbox directly from a contour and get parameters from that. This is not implemented for a circular ROI.

StevenPuttemans gravatar imageStevenPuttemans ( 2014-11-26 06:28:56 -0600 )edit
1

Thanks StevenPuttemans. I will try the 2 approaches to get the radius. But can you briefly explain how to do the first one with the HoughCircles and the findContours ? because in the vector Contours I only get points and not an image (so far i understood).

Is it normal that i can't see the others answers ? I see only my question and the comment of StevenPuttemans ...

MohZ gravatar imageMohZ ( 2014-11-26 07:26:45 -0600 )edit

Be patient, the Q&A forum has some bugs for the moment which are being solved as we speak. Someone needs to accept your answer as admin, but the page to do so is broken. Only admin messages (like mine) get displayed directly. As to the findContours operation, your image on which you create your findContours is binary right? That can also be used to create houghCircles.

StevenPuttemans gravatar imageStevenPuttemans ( 2014-11-26 07:29:54 -0600 )edit

Thanks for your reply! I tried the HoughCircle method but it seems to be very unstable. Example: in frame x the (x,y, radius) of the detect ball is (193, 202, 20). In the frame x+y: the (x,y, radius) of the detect ball is (195, 205, 23). In the frame x+y+z: it detects no balls at all.

This is what I mean by beeing unstable. I also make use of Morphological operations for the thresholded image but I didn't fixed it.

MohZ gravatar imageMohZ ( 2014-11-27 09:35:08 -0600 )edit

3 answers

Sort by ยป oldest newest most voted
1

answered 2014-11-26 05:51:11 -0600

tomasth gravatar image

Have you tried using minEnclosingCircle? Looks just right for the job

edit flag offensive delete link more
1

answered 2014-11-26 04:00:27 -0600

theodore gravatar image

Since you have the contours that you want, I think that the solution is pretty much simple. You need to call the minEnclosingCircle() function over the detected contours and then you have what you want. Have a look at this example, in order to see how to do it.

Cheers tt.

edit flag offensive delete link more
0

answered 2014-11-26 04:53:05 -0600

-Find width and height of the contour with a bounding box, like this link bounding_rects.

-Also find the area (A1) of the contour with this link contour_area

-Using either width, height or an average, assume that is the diameter of your circle (D) where the radius (r = D/2)

-Calculate the ideal area (A2) = Pi X r^2; this is the ideal area you are after.

-Compare A1 and A2 with something like: circular = 1 - (abs(A1-A2)/A2)

The circular value calculated should be a percentage how circular the contour is, if this number is high you can use width or height as the diameter, if not its not a circle.

edit flag offensive delete link more

Question Tools

Stats

Asked: 2014-11-24 05:39:57 -0600

Seen: 17,042 times

Last updated: Nov 26 '14