added houghcircles sample, improved circle detection (ticket #951)

pull/13383/head
Vadim Pisarevsky 13 years ago
parent eaea6782d5
commit 7a62413c94
  1. 28
      modules/imgproc/src/hough.cpp
  2. BIN
      samples/cpp/board.jpg
  3. 48
      samples/cpp/houghcircles.cpp

@ -802,7 +802,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
int canny_threshold, int acc_threshold,
CvSeq* circles, int circles_max )
{
const int SHIFT = 10, ONE = 1 << SHIFT, R_THRESH = 30;
const int SHIFT = 10, ONE = 1 << SHIFT;
cv::Ptr<CvMat> dx, dy;
cv::Ptr<CvMat> edges, accum, dist_buf;
std::vector<int> sort_buf;
@ -842,7 +842,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
acols = accum->cols - 2;
adata = accum->data.i;
astep = accum->step/sizeof(adata[0]);
// Accumulate circle evidence for each edge pixel
for( y = 0; y < rows; y++ )
{
const uchar* edges_row = edges->data.ptr + y*edges->step;
@ -868,7 +868,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
x0 = cvRound((x*idp)*ONE);
y0 = cvRound((y*idp)*ONE);
// Step from min_radius to max_radius in both directions of the gradient
for( k = 0; k < 2; k++ )
{
x1 = x0 + min_radius * sx;
@ -894,7 +894,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
nz_count = nz->total;
if( !nz_count )
return;
//Find possible circle centers
for( y = 1; y < arows - 1; y++ )
{
for( x = 1; x < acols - 1; x++ )
@ -924,17 +924,19 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
dr = dp;
min_dist = MAX( min_dist, dp );
min_dist *= min_dist;
// For each found possible center
// Estimate radius and check support
for( i = 0; i < centers->total; i++ )
{
int ofs = *(int*)cvGetSeqElem( centers, i );
y = ofs/(acols+2) - 1;
x = ofs - (y+1)*(acols+2) - 1;
float cx = (float)(x*dp), cy = (float)(y*dp);
y = ofs/(acols+2);
x = ofs - (y)*(acols+2);
//Calculate circle's center in pixels
float cx = (float)((x + 0.5f)*dp), cy = (float)(( y + 0.5f )*dp);
float start_dist, dist_sum;
float r_best = 0, c[3];
int max_count = R_THRESH;
int max_count = 0;
// Check distance with previously detected circles
for( j = 0; j < circles->total; j++ )
{
float* c = (float*)cvGetSeqElem( circles, j );
@ -944,7 +946,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
if( j < circles->total )
continue;
// Estimate best radius
cvStartReadSeq( nz, &reader );
for( j = k = 0; j < nz_count; j++ )
{
@ -991,8 +993,8 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
}
dist_sum += d;
}
if( max_count > R_THRESH )
// Check if the circle has enough support
if( max_count > acc_threshold )
{
c[0] = cx;
c[1] = cy;

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

@ -0,0 +1,48 @@
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void help()
{
cout << "\nThis program demonstrates circle finding with the Hough transform.\n"
"Usage:\n"
"./houghcircles <image_name>, Default is pic1.png\n" << endl;
}
int main(int argc, char** argv)
{
const char* filename = argc >= 2 ? argv[1] : "board.jpg";
Mat img = imread(filename, 0);
if(img.empty())
{
help();
cout << "can not open " << filename << endl;
return -1;
}
Mat cimg;
medianBlur(img, img, 5);
cvtColor(img, cimg, CV_GRAY2BGR);
vector<Vec3f> circles;
HoughCircles(img, circles, CV_HOUGH_GRADIENT, 1, 10,
100, 30, 1, 30 // change the last two parameters
// (min_radius & max_radius) to detect larger circles
);
for( size_t i = 0; i < circles.size(); i++ )
{
Vec3i c = circles[i];
circle( cimg, Point(c[0], c[1]), c[2], Scalar(0,0,255), 3, CV_AA);
circle( cimg, Point(c[0], c[1]), 2, Scalar(0,255,0), 3, CV_AA);
}
imshow("detected circles", cimg);
waitKey();
return 0;
}
Loading…
Cancel
Save