我正试图在斯诺克台球上检测到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;
}
答案 0 :(得分:2)
我怀疑你在参数太严格或松散时遇到问题。您需要使用参数,直到获得所需的圆圈数。此外,根据图像,高斯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是我得到的输出。
(P.S。考虑使用C ++接口,它远远优于C接口恕我直言:)
答案 1 :(得分:0)
如果您使用iOS,则需要包含ios.h,或者只需编写自己的类方法来处理从cvMat到UIImage的img proc,反之亦然。
请原谅这些评论,我将它们仅包括在那些可能发现与我一样的“乱语”研究中的人。每张图片都需要完全不同的设置。不要放弃。 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