Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

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( !src.data )
        { 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]);
           cent.x=center.x;
           cent.y=center.y;

          // 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;

       while(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 );
      add=thr+add;
      imshow( "add", add );
      waitKey(33);

      rad++;

      //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 = add.at<Vec3b>(i, j);
          int p=bgrPixel.val[0];

            if(p==255){ //Check whether the radius reaches white region from centre.
        flag=1;
       }

      }
     }
   }

         /*********************************This block will find the intermediate circle******************/
      radius=radius-15; // Decrease the radius some amount to avoid false dtection
       while(flag==1){

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

    radius--;

      for(int i = 0; i < add.rows; i++)  // Check whether the circle hits the black region.
       {
      for(int j = 0; j < add.cols; j++)
     {
          Vec3b bgrPixel = add.at<Vec3b>(i, j);
           int p=bgrPixel.val[0];

       if(p==155){//Check whether the radius reaches balck region from perimetre of the outer circle .
         flag=0;
      }

     }
    }
    }
    /***************************************************************************/

  circle( src, cent, radius, Scalar(0,255,0), 1, 8, 0 );
  circle( src, cent, rad, Scalar(0,255,0), 1, 8, 0 );

 /// Show your results
  namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
  imshow( "Hough Circle Transform Demo", src );

  waitKey(0);
  return 0;
 }