2012-05-18 121 views
2

我使用cvHoughCircles找到下圖中的兩個白色的橢圓形:用於定位的白色區域,然後OpenCV的:錯誤cvHoughCircles使用

enter image description here

我第一次使用閾值使用霍夫變換。

enter image description here

我無法理解發生了什麼:但如下面的輸出是不是來正確嗎?爲什麼它正在檢測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); 

這裏是輸出:

enter image description here

+1

也許我不熟悉OpenCv,但不應該使用邊緣圖像,而不是閾值作爲Hough算法的輸入? –

+0

使用Canny邊緣檢測,其次是Hough Transformed工作!但是當我拍攝更多沒有的圖像時。白色的斑點,同樣的算法失敗了。 – gpuguy

+0

@Andrey,你認爲對於橢圓形狀檢測應該使用相同的程序嗎? (因爲在我的情況下,實際上形狀是橢圓形的而不是圓形的) – gpuguy

回答

2

您應該使用邊緣檢測的圖像作爲輸入,而不是經過閾值。其次,霍夫圓圈不適用於elipses,除非它們非常接近圓圈。我建議閱讀關於Generalized Hough Transform併爲橢圓實現它。

+0

應該完成這個編碼,然後邊緣然後hough變換。在我的情況下,近似圓形的圖像解決方案的工作,但橢圓形沒有。所以我想Genralised Hough Transform可能是更好的解決方案。手中的應用程序實際上要簡單得多,因爲我知道白色斑點的大小和許多其他參數,所以可能是一些微不足道的方法也適用於我的情況。 – gpuguy

3

It's all aboutthe parameters

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); 

如果您已經做了一點點試驗,你會最終發現,with different parameters you get different results

+0

盡我所能,用你的以及這些參數:CvSeq * results = cvHoughCircles( image, storage, CV_HOUGH_GRADIENT,2,1);但沒有工作,沒有檢測到圓圈,返回> 0 – gpuguy

+0

上面的代碼產生了我共享的圖像。我使用OpenCV 2.3.1。我建議你在另一臺機器上測試它。 – karlphillip

+0

我有像opencv_core240.lib這樣的庫,所以這意味着我有opencv 2.4。您的值4,image-> width/3對應於「dp = 1:分辨率的反比例」和「檢測到的中心之間的最小距離」對嗎? – gpuguy