Ask Your Question

Detect/Fitting Circles

asked 2012-12-14 11:02:20 -0600

KC gravatar image

updated 2016-01-21 09:57:20 -0600


If you look at this image:

image description

It's easy to find by human eyes that there are 3 circles which share the same center.

How could I detect/fit these 3 circles ? I try cvFindContours() but the middle and inner circles are detected as a single contours. I also try cvHoughCircles(), it give me a lot of circles ... but not the 3 circles I expected.

What should I do for this kind of situation ? I'm new in computer vision, is this an easy question ? Or this is a known difficult problem ?

Regards KC

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted

answered 2012-12-15 00:24:37 -0600

Haris gravatar image

updated 2012-12-15 00:26:32 -0600

Hough Circle Transform is the best option to detect circle in OpenCV. If you are getting expected circle with false circle using Hough Circle Transform you can easily filter out the true circle. For this first manually find out the radius of three circle you are expecting. Then find out the ratios between the three circle and these ratios will be constant even if you re-size your image. Then using Hough Circle Transform and find out the circles in the image. Then filter out co-centred circle from detected circle. For each co-centred circle(with next) check whether it's radius ratio comes in the range of your predefined value, if it comes so store it as true circle.

Hope this is helpful.

edit flag offensive delete link more



I did try different parameters' setup for cvHoughCircles() ... a lot of circles will be detected, but no one will fit the inner/empty circle :-( I need to know the center and radius correctly (this is a measurement application), and I do know the approximate center and radius ... any suggestion to handle this kind of "tooth" like circle ? Thanks a lot.

KC gravatar imageKC ( 2012-12-15 10:24:00 -0600 )edit

answered 2012-12-17 01:34:08 -0600

Haris gravatar image

You can easily detect the outer circle using Hough transform, from there you will get the centre.

  1. Find the THRESH_BINARY_INV of the src image('thr') with a threshold say 100.
  2. Create Mat of same size and and set all element to zero say 'add'.
  3. In a loop start drawing circle on 'add' from centre towards outer with a value say 255.
  4. On each step add=add+thr 5 Scan through each pixel of 'add' and check whether it's value is 255(means it touches whiter boarder) 6.If 255 exit loop and that will be the intermediate circle. 7.Else increase radius until you met the condition.

For intermediate circle Same step as above but instead of adding image minus it. radius=radius found out using hough transform- a constant 1. add=add-thr;
2. check if pixel value of add=155 if yes exit
3. else radius--

I am not sure does it work or not for other images but it is working fine for the image you provided with your question. Below is the code I just made to test the above algorithm.

  #include "opencv2/highgui/highgui.hpp"
  #include "opencv2/imgproc/imgproc.hpp"
  #include <iostream>
  #include <stdio.h>

 using namespace cv;

       /** @function main */
    int main(int argc, char** argv)
      Mat src, src_gray,thr,edge,add;

      /// Read the image
        src = imread( argv[1], 1 );
        int t1=75;
       int t2=100;
       if( ! )
        { return -1; }

      /// Convert it to gray
         cvtColor( src, src_gray, CV_BGR2GRAY );
       /// Reduce the noise so we avoid false circle detection
        GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
        threshold( src_gray, thr, t1, t2, THRESH_BINARY_INV );
         threshold( src_gray, add, 0, 0, THRESH_BINARY_INV ); //Instaed of this step you can create an image of the same size and set all element to zero

       imshow( "thr", thr );

       Point cent; // centre for inner circle
       int rad=55; //radius for inner circle
       int radius; // centre for Hough circle
       vector<Vec3f> circles;

      /// Apply the Hough Transform to find the circles
      HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, t1, t2, 0, 0 );

       /// Draw the circles detected
          for( size_t i = 0; i < circles.size(); i++ )
            Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
           radius = cvRound(circles[i][2]);

          // circle center
          circle( src, center, 3, Scalar(0,255,0), 5, 8, 0 );
         // circle outline
         circle( src, center, radius, Scalar(0,255,0), 1, 8, 0 );

      /************ This block will findout the inner circle******************/

        int flag=0;


        threshold( src_gray, add, 0, 0, THRESH_BINARY_INV ); // instead of this can you can set all elemet to zero
       circle( add, cent, rad, Scalar(155), 1, 8, 0 );
      imshow( "add", add );


      //Scan whole mat and check whether the circle hit the white pixel
      for(int i = 0; i < add.rows; i++)
        for(int j = 0; j < add.cols; j++)
          Vec3b bgrPixel =<Vec3b>(i, j);
          int p=bgrPixel.val[0];

            if(p==255){ //Check whether the radius reaches white region from centre.
        flag=1 ...
edit flag offensive delete link more


Cool, this is what I expected !! I think I got the point, thanks a lot :-)

KC gravatar imageKC ( 2012-12-17 02:40:03 -0600 )edit

Just another question. The HoughCircles() usually does not return a single circle. It usually return a lot of circle; sometime no circle at all ... what's the trick to turn the image or parameters to let HoughCircles() to return single circle ? Is the general rules existed ?

KC gravatar imageKC ( 2012-12-17 03:20:21 -0600 )edit

I think the two parameters -upper and lower threshold values- control the number of circles returns. If you include more edges in your image it will return maximum number of circles and it depends on the high and low threshold values, also blur operation before the Hough transform reduces false circle return. Selecting the thresholds can be considered as the key point in Houch circle tranform and that can be varied according to your image brightness

Haris gravatar imageHaris ( 2012-12-17 03:46:14 -0600 )edit

Hi, I was very excited when I see your code running without second thought. In fact, this is not what I wanted. Your approach assume the outer and inner circle share the same centre. But what I really need is find the outer/inner circle independently and check if they have the same centre.

Thanks anyway, your example is helpful.


KC gravatar imageKC ( 2012-12-17 10:04:13 -0600 )edit

Question Tools


Asked: 2012-12-14 11:02:20 -0600

Seen: 11,224 times

Last updated: Dec 17 '12