2011-10-12 45 views
1

我想要检测斯诺克台上的22个球。我有一个图像可以测试,但程序操作系统检测到2个球,其他地方的随机圆。我的代码在下面的圆检测算法。有谁知道应该调整哪些参数以获得我需要的检测结果?谢谢CV Hough Circle参数来检测圈

#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

如果您分享了您在测试中使用的图像,它将帮助您很多。 – karlphillip

回答

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是输出我得到。

(PS考虑使用C++接口它远远优于C接口恕我直言:)

+0

非常感谢。很多你的代码和我的代码不一样,我真的不知道轨道条的用途是什么。所有的CvCanny在哪里? cvThreshold等去? – user966890

+0

我使用OpenCV 2.3.1的C++接口(尽管我不认为任何函数都比OpenCV 2.2更新,所以应该也可以)。轨道条只允许您调整Canny阈值,以查看它对图像所做的更改。作为练习,您可以为minDist参数添加另一个轨迹条。最后,HoughCircles实际上已经对图像执行Canny操作来查找圆圈。这就是hi和lo变量的用处。 – mevatron

0

如果您正在使用您需要包括ios.h,或简单地写自己的类的方法来处理IMG的iOS从cvMat处理到UIImage,反之亦然。

请原谅我的意见,我只将它们包括在那些可能已经发现一些与我一样的“胡言乱语”研究中。每张图片都需要完全不同的设置。不要放弃。 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