1 | initial version |
You can easily detect the outer circle using Hough transform, from there you will get the centre.
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;
}