2016-09-22 130 views
0

由于现在是我的学校假期,我决定选择一些技巧,因此我试图学习如何在Visual Studio C++中使用OpenCV功能来检测许多罐在纸箱,并不得不将其分组4 4。 enter image description here使用Opencv和Hough变换圆圈来检测圆圈(下标错误)

我已经尝试了各种演示代码,如“opencv find:contour”,模板匹配(无法正常工作,因为它无法检测到旋转顶部盖子)

我发现的最佳方法是将Canny边缘检测和Hough变换圆组合起来,使得Canny边缘检测的输出结果可以是Hough变换圆的输入图像,结果如下。

enter image description here

不幸的是,当检测到不是所有的圈子,如果我改变

for (int i = 0; i < circles.size(); i++)

for (int i = 0; i < 24; i++) // 24 is the no. of cans 

我会得到一个表达:向量下标超出范围。我不知道为什么它是唯一能够检测21圈

来源如下代码: -

using namespace cv; 
using namespace std; 
Mat src, src_gray; 

int main() 
{ 
Mat src1; 

src1 = imread("cans.jpg", CV_LOAD_IMAGE_COLOR); 
namedWindow("Original image", CV_WINDOW_AUTOSIZE); 
imshow("Original image", src1); 


Mat gray, edge, draw; 
cvtColor(src1, gray, CV_BGR2GRAY); 

Canny(gray, edge,50, 150, 3); 
//50,150,3 

edge.convertTo(draw, CV_8U); 
namedWindow("Canny Edge", CV_WINDOW_AUTOSIZE); 
imshow("Canny Edge", draw); 
imwrite("output.jpg", draw); 


waitKey(500); 




/// Read the image 
src = imread("output.jpg", 1); 
Size size(932, 558);//the dst image size,e.g.100x100 
resize(src, src, size);//resize image 

/// Convert it to gray 
cvtColor(src, src_gray, CV_BGR2GRAY); 

/// Reduce the noise so we avoid false circle detection 
GaussianBlur(src_gray, src_gray, Size(9, 9), 2, 2); 

vector<Vec3f> circles; 

/// Apply the Hough Transform to find the circles 
HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8,200, 100, 0, 0); 

/// Draw the circles detected 
for (int i = 0; i < circles.size(); i++) 
{ 
    printf("are you um?\n"); 
    Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); 
    int radius = cvRound(circles[i][2]); 
    // circle center 
    circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0); 
    // circle outline 
    circle(src, center, radius, Scalar(255, 0, 255), 3, 8, 0); 
} 

// namedWindow("Hough Circle Transform Demo", CV_WINDOW_NORMAL); 
    imshow("Hough Circle Transform Demo", src); 
    line(src, Point(0, 288), Point(1024, 288), Scalar(225, 220, 225), 2, 8); 
    // middle line 
    line(src, Point(360, 0), Point(360, 576), Scalar(225, 220, 225), 2, 8); 
    //break cans into 4 by 4 
    line(src, Point(600, 0), Point(600, 576), Scalar(225, 220, 225), 2, 8); 
          //  x, y 
    imshow("Lines", src); 
    imwrite("lineoutput.jpg", src); 


    waitKey(0); 


    return 0; 
} 

我还手工打出来的坐标为线,以它们分成4×4 enter image description here 为了避免下标超出范围并且能够检测到所有圈子,我应该更改哪些内容?

+0

你不能访问超过你找到的东西。它创建了21个圆圈,所以矢量包含21个圆圈。如果将循环变量更改为24,则会得到下标错误,导致向量大小为21.您无法访问其大小。要找到缺少的圈子,您可以添加程序中的圈子。它不会总是有效,但在某种程度上它会起作用。它像一个6x4的网格。从中心的距离,你可以很容易地假设哪些圈丢失..... –

+0

我不认为我会手动添加圆圈,因为我有10多个不同的照明和位置的图像。 谢谢!修正了下标错误,我的6x4网格可能只是为了显示,因为它什么都不做:l – Lyber

回答

1

好吧解决了我自己的问题。将CV_BGR2GRAY更改为CV_RGB2GRAY,使文件比率更小,更改圆圈半径最小值并应用另一个阈值来获取圆圈。 enter image description here

+0

尝试不同的光线和其他条件......你不会总是有所有的圆圈。它可能会失败:) –

+0

是的..我试着用不同的照明,但不幸的是我不能在不改变代码的值的情况下得到所有的圆:c 有没有什么解决方案,我想知道? – Lyber

+0

功能匹配如Ransac和筛选? – Lyber