2

我正在使用 cvHoughCircles 在下图中找到两个白色椭圆:

在此处输入图像描述

我首先使用阈值来定位白色区域,然后使用霍夫变换。但是输出不正确,如下所示:

在此处输入图像描述

我无法理解发生了什么?为什么它检测到 3 个圆圈,为什么只有一个被正确检测到?有什么建议么?

下面是我的代码:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <math.h> 
#include <ctype.h>
#include <stdlib.h>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include<conio.h>
#include<malloc.h>



using namespace cv;
using namespace std;
int main( ) {
IplImage* image = cvLoadImage( 
"testing.bmp",
  CV_LOAD_IMAGE_GRAYSCALE
);

IplImage* src = cvLoadImage("testing.bmp");
CvMemStorage* storage = cvCreateMemStorage(0);


cvThreshold( src, src,  200, 255, CV_THRESH_BINARY );

CvSeq* results = cvHoughCircles( 
image, 
 storage, 
 CV_HOUGH_GRADIENT, 
 3, 
 image->width/10 
 ); 

 for( int i = 0; i < results->total; i++ ) 
 {
 float* p = (float*) cvGetSeqElem( results, i );
 CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] ) );
 cvCircle( 
  src,
  pt, 
  cvRound( p[2] ),
  CV_RGB(0xff,0,0) 
);
}
cvNamedWindow( "HoughCircles", 1 );
cvShowImage( "HoughCircles", src);
cvWaitKey(0);
} 

编辑:

由于我对霍夫变换没有得到满意的结果,我愿意采取其他方式。我可以假设图中每个白色斑点的大小相同(大小已知),并且斑点之间的距离也是已知的。有没有一种不平凡的方法可以找到一条垂直线(切线)接触左侧白色斑点的左侧?一旦我知道了这个切线,我就知道了边界位置,然后我将在 x=(这个位置 + 半径(已知))处画一个圆,y = 这个位置。我可以使用一些重要的方法找到这样的 x 和 y 坐标吗?

解决了,通过如下改变:

cvThreshold(image, image,  220, 255, CV_THRESH_BINARY );

cvCanny(image, image, 255, 255, 3);


cvNamedWindow( "edge", 1 );
cvShowImage( "edge", image);
cvWaitKey(0);

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* results = cvHoughCircles( 
             image, 
             storage, 
             CV_HOUGH_GRADIENT, 
             4, 
             image->width/4, 100,100,0,50); 

这是输出:

在此处输入图像描述

4

2 回答 2

3

这都是关于 参数的

IplImage* src = cvLoadImage(argv[1]);
if (!src)
{
    cout << "Failed: unable to load image " << argv[1] << endl;
    return -1;
}

//IplImage* image = cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
IplImage* image = cvCreateImage(cvSize(src->width, src->height), IPL_DEPTH_8U, 1);
cvCvtColor(src, image, CV_RGB2GRAY);

cvThreshold(image, image,  220, 255, CV_THRESH_BINARY );
//  cvNamedWindow( "thres", 1 );
//  cvShowImage( "thres", image);
//  cvWaitKey(0);

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* results = cvHoughCircles( 
                 image, 
                 storage, 
                 CV_HOUGH_GRADIENT, 
                 4, 
                 image->width/3); 

std::cout << "> " << results->total << std::endl;

for( int i = 0; i < results->total; i++ ) 
{
    float* p = (float*) cvGetSeqElem( results, i );
    CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] ) );
    cvCircle(src,
             pt, 
             cvRound( p[2] ),
             CV_RGB(0xff,0,0));
}

cvNamedWindow( "HoughCircles", 1 );
cvShowImage( "HoughCircles", src);
cvWaitKey(0);

如果您进行了更多实验,您最终会发现使用不同的参数会得到不同的结果

于 2012-05-18T13:48:46.807 回答
2

您应该使用边缘检测图像作为输入,而不是阈值。其次,霍夫圆不适用于椭圆,除非它们非常接近圆。我推荐阅读广义霍夫变换并为椭圆实现它。

于 2012-05-22T08:13:16.197 回答