added houghcircles sample, improved circle detection (ticket #951)
This commit is contained in:
parent
eaea6782d5
commit
7a62413c94
@ -802,7 +802,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
|
|||||||
int canny_threshold, int acc_threshold,
|
int canny_threshold, int acc_threshold,
|
||||||
CvSeq* circles, int circles_max )
|
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> dx, dy;
|
||||||
cv::Ptr<CvMat> edges, accum, dist_buf;
|
cv::Ptr<CvMat> edges, accum, dist_buf;
|
||||||
std::vector<int> sort_buf;
|
std::vector<int> sort_buf;
|
||||||
@ -842,7 +842,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
|
|||||||
acols = accum->cols - 2;
|
acols = accum->cols - 2;
|
||||||
adata = accum->data.i;
|
adata = accum->data.i;
|
||||||
astep = accum->step/sizeof(adata[0]);
|
astep = accum->step/sizeof(adata[0]);
|
||||||
|
// Accumulate circle evidence for each edge pixel
|
||||||
for( y = 0; y < rows; y++ )
|
for( y = 0; y < rows; y++ )
|
||||||
{
|
{
|
||||||
const uchar* edges_row = edges->data.ptr + y*edges->step;
|
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);
|
x0 = cvRound((x*idp)*ONE);
|
||||||
y0 = cvRound((y*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++ )
|
for( k = 0; k < 2; k++ )
|
||||||
{
|
{
|
||||||
x1 = x0 + min_radius * sx;
|
x1 = x0 + min_radius * sx;
|
||||||
@ -894,7 +894,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
|
|||||||
nz_count = nz->total;
|
nz_count = nz->total;
|
||||||
if( !nz_count )
|
if( !nz_count )
|
||||||
return;
|
return;
|
||||||
|
//Find possible circle centers
|
||||||
for( y = 1; y < arows - 1; y++ )
|
for( y = 1; y < arows - 1; y++ )
|
||||||
{
|
{
|
||||||
for( x = 1; x < acols - 1; x++ )
|
for( x = 1; x < acols - 1; x++ )
|
||||||
@ -924,17 +924,19 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
|
|||||||
dr = dp;
|
dr = dp;
|
||||||
min_dist = MAX( min_dist, dp );
|
min_dist = MAX( min_dist, dp );
|
||||||
min_dist *= min_dist;
|
min_dist *= min_dist;
|
||||||
|
// For each found possible center
|
||||||
|
// Estimate radius and check support
|
||||||
for( i = 0; i < centers->total; i++ )
|
for( i = 0; i < centers->total; i++ )
|
||||||
{
|
{
|
||||||
int ofs = *(int*)cvGetSeqElem( centers, i );
|
int ofs = *(int*)cvGetSeqElem( centers, i );
|
||||||
y = ofs/(acols+2) - 1;
|
y = ofs/(acols+2);
|
||||||
x = ofs - (y+1)*(acols+2) - 1;
|
x = ofs - (y)*(acols+2);
|
||||||
float cx = (float)(x*dp), cy = (float)(y*dp);
|
//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 start_dist, dist_sum;
|
||||||
float r_best = 0, c[3];
|
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++ )
|
for( j = 0; j < circles->total; j++ )
|
||||||
{
|
{
|
||||||
float* c = (float*)cvGetSeqElem( circles, j );
|
float* c = (float*)cvGetSeqElem( circles, j );
|
||||||
@ -944,7 +946,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
|
|||||||
|
|
||||||
if( j < circles->total )
|
if( j < circles->total )
|
||||||
continue;
|
continue;
|
||||||
|
// Estimate best radius
|
||||||
cvStartReadSeq( nz, &reader );
|
cvStartReadSeq( nz, &reader );
|
||||||
for( j = k = 0; j < nz_count; j++ )
|
for( j = k = 0; j < nz_count; j++ )
|
||||||
{
|
{
|
||||||
@ -991,8 +993,8 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
|
|||||||
}
|
}
|
||||||
dist_sum += d;
|
dist_sum += d;
|
||||||
}
|
}
|
||||||
|
// Check if the circle has enough support
|
||||||
if( max_count > R_THRESH )
|
if( max_count > acc_threshold )
|
||||||
{
|
{
|
||||||
c[0] = cx;
|
c[0] = cx;
|
||||||
c[1] = cy;
|
c[1] = cy;
|
||||||
|
BIN
samples/cpp/board.jpg
Normal file
BIN
samples/cpp/board.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 KiB |
48
samples/cpp/houghcircles.cpp
Normal file
48
samples/cpp/houghcircles.cpp
Normal file
@ -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…
x
Reference in New Issue
Block a user