CV 霍夫圆参数检测圆
Posted
技术标签:
【中文标题】CV 霍夫圆参数检测圆【英文标题】:CV Hough Circle Parameters to detect Circles 【发布时间】:2011-10-12 01:38:29 【问题描述】:我正在尝试检测斯诺克台球桌上的 22 个球。我有一个图像要测试,但程序 os 检测到 2 个球和其他地方的随机圆圈。我的代码在下面带有圆形检测算法。有谁知道应该调整哪些参数以获得我需要的检测?谢谢
#include <cv.h>
#include <highgui.h>
#include <math.h>
int main(int argc, char** argv)
int edge_thresh = 1;
IplImage* img = cvLoadImage("C:\\Users\\Nathan\\Desktop\\SnookerPic.png", 1);;
IplImage* gray = cvCreateImage(cvGetSize(img), 8, 1);
IplImage *edge = cvCreateImage( cvSize(img->width,img->height), 8, 1);
CvMemStorage* storage = cvCreateMemStorage(0);
cvCvtColor(img, gray, CV_BGR2GRAY);
cvThreshold(gray,gray, CV_GAUSSIAN, 9, 9);
cvSmooth(gray, gray, CV_GAUSSIAN, 11, 11);
cvCanny(gray, edge, (float)edge_thresh, (float)edge_thresh*3, 5);
CvSeq* circles = cvHoughCircles(edge, storage,
CV_HOUGH_GRADIENT, 2, 20, 200, 50);
int i;
for (i = 0; i < circles->total; i++)
float* p = (float*)cvGetSeqElem( circles, i );
cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])),
3, CV_RGB(0,255,0), -1, 8, 0 );
cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])),
cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );
cvNamedWindow( "circles", 1 );
cvShowImage( "circles", img );
return 0;
【问题讨论】:
如果您分享您在测试中使用的图像,这将对您有很大帮助。 【参考方案1】:我怀疑您在参数过于严格或过于宽松时遇到了问题。您需要使用参数,直到获得所需的圈数。此外,高斯 11x11 模糊可能有点激进,具体取决于图像。对我的形象来说,弊大于利,但我的形象有点理想化了……
我修改了您正在使用的 OpenCV 示例,以包含允许您使用 Canny 参数的轨迹栏。这应该真的可以帮助您了解它是如何工作的。另外,请注意 minDist 参数。对于我的图像,圆心距离大约 32 像素。您需要将其调整为您的圈子大小。所以,这里是示例:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int hi = 1, lo = 1;
int main(int argc, char* argv[])
Mat orig = imread("Snooker_balls_triangled.png");
int key = 0;
namedWindow("circles", 1);
createTrackbar("hi", "circles", &hi, 255);
createTrackbar("lo", "circles", &lo, 255);
do
// update display and snooker, so we can play with them
Mat display = orig.clone();
Mat snooker;
cvtColor(orig, snooker, CV_RGB2GRAY);
vector<Vec3f> circles;
// also preventing crash with hi, lo threshold here...
HoughCircles(snooker, circles, CV_HOUGH_GRADIENT, 2, 32.0, hi > 0 ? hi : 1, lo > 0 ? lo : 1 );
for( size_t i = 0; i < circles.size(); i++ )
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the green circle center
circle( display, center, 3, Scalar(0,255,0), -1, 8, 0 );
// draw the blue circle outline
circle( display, center, radius, Scalar(255,0,0), 3, 8, 0 );
imshow( "circles", display );
imshow("snooker", snooker);
key = waitKey(33);
while((char)key != 27);
return 0;
我使用了这个snooker image,this 是我得到的输出。
(PS 考虑使用 C++ 接口,它远优于 C 接口恕我直言:)
【讨论】:
感谢一百万。你的很多代码与我的不同,我真的不明白轨迹栏的目的是什么。所有的 CvCanny 都在哪里。 cvThreshold 等去吗? 我正在使用 OpenCV 2.3.1 的 C++ 接口(尽管我认为没有任何功能比 OpenCV 2.2 更新,所以应该也可以)。轨迹栏只允许您调整 Canny 阈值以查看它对图像所做的更改。作为练习,您可以为 minDist 参数添加另一个轨迹栏。最后,HoughCircles 实际上已经对图像执行了 Canny 操作以找到圆圈。这就是 hi 和 lo 变量的用途。【参考方案2】:如果您使用的是 ios,则需要包含 ios.h,或者只需编写自己的类方法来处理从 cvMat 到 UIImage 的 img proc,反之亦然。
请原谅 cmets,我仅将它们包含在那些可能发现了与我相同的“胡言乱语”研究的人中。每个图像都需要完全不同的设置。不放弃。 houghcircles 是目前最好的检测算法。 我将把一些游戏代码与检测结合起来,让它变得更好、更简单、更快。
#import "JmBViewController.h"
@interface JmBViewController ()
@end
@implementation JmBViewController
- (void)viewDidLoad
[super viewDidLoad];
_imgtest = [UIImage imageNamed:@"IMG_0424.PNG"];
cv::Mat cvImage;
UIImageToMat(_imgtest, cvImage);
if (!cvImage.empty())
cv::Mat gray;
// cv::Mat filteredMat;
cv::cvtColor(cvImage, gray, CV_BGRA2GRAY);
// cv::GaussianBlur(gray, gray, cv::Size(5, 5), 1.2, 1.2);
cv::vector<cv::Vec3f> circles;
//cv::HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, 50);
/*
for(size_t i = 0; i < circles.size(); i++)
cv::Point center((cvRound(circles[i][0]), cvRound(circles[i][1])));
int radius = cvRound(circles[i][2]);
cv::circle(gray, center, 3, cv::Scalar(0,255,0));
cv::circle(gray, center, radius, cv::Scalar(0,0,255));
*/
// for ( int i = 1; i < 15; i = i + 2 )
cv::GaussianBlur(gray, gray, cv::Size(9, 9), 1.5, 1.5);
cv::Mat edges;
cv::Canny(gray, edges, 0, 50);
//gray.setTo(cv::Scalar::all(0));
//gray.setTo(cv::Scalar::all(255), edges);
cv::HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, gray.rows/30, 100, 50, 10, 30 );
for(size_t i = 0; i < circles.size(); i++)
cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
cv::circle(cvImage, center, 5, cv::Scalar::all(200), -1, 8, 0 );//center
cv::circle(cvImage, center, radius, cv::Scalar::all(255), 3, 8, 0 );//diamter
NSLog(@"Circles: %ld", i+1);
// cv::imshow(&"circles i " [ i], gray);
_imgView.image = MatToUIImage(cvImage);
/*
cv::Mat cvImage;
cv::Mat grey;
cv::Mat filteredMat;
cv::vector<cv::Vec3f> circles;
// cv::cvtColor(_imgtest, cvImage, CV_BGR2GRAY);
cv::threshold(grey, filteredMat, 100, 255, CV_THRESH_BINARY);
[UIImageCVMatConverter cvMatGrayFromUIImage:_imgtest];
// cv::cvtColor(cvImage, grey, CV_RGBA2GRAY);
// UIImageToMat(_imgtest, cvImage);
cv::HoughCircles(cvImage, circles, CV_HOUGH_GRADIENT, 1, 50);
// MatToUIImage(cvImage);
_imgView.image = [UIImageCVMatConverter UIImageFromCVMat:cvImage];
_imgView.image = MatToUIImage(cvImage);
*/
// Do any additional setup after loading the view, typically from a nib.
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
/*
UIImage* MatToUIImage(const cv::Mat& image)
NSData *data = [NSData dataWithBytes:image.data length:image.elemSize()*image.total()];
CGColorSpaceRef colorSpace;
if (image.elemSize() == 1)
colorSpace = CGColorSpaceCreateDeviceGray();
else colorSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
CGImageRef imageRef = CGImageCreate(image.cols, image.rows, 8, 8*image.elemSize(), image.step.p[0], colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault, provider, NULL, FALSE, kCGRenderingIntentDefault);
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
return finalImage;
*/
@end
【讨论】:
以上是关于CV 霍夫圆参数检测圆的主要内容,如果未能解决你的问题,请参考以下文章