OpenCV: ошибка в использовании cvHoughCircles

Я использую 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);
} 

Редактировать:

Поскольку я не получаю удовлетворительных результатов с Hough Transform, я готов пойти другим путем. Я могу предположить, что все белые шарики на рисунке имеют одинаковый размер (размер известен), а также известно расстояние между шариками. Есть ли нетривиальный способ найти вертикальную линию (касательную), касающуюся левой стороны левого белого пятна? Как только я узнаю этот тангенс, я получу представление о местоположении границы, а затем нарисую круг в точке 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); 

Вот результат:

введите здесь описание изображения


person gpuguy    schedule 18.05.2012    source источник
comment
Возможно, я не знаком с OpenCv, но разве вы не должны использовать изображение края, а не пороговое значение в качестве входных данных для алгоритма Хафа?   -  person Andrey Rubshtein    schedule 21.05.2012
comment
с использованием обнаружения краев Canny, а затем Hough Transformed сработало! Но когда я беру другое изображение, больше нет. белых пятен тот же алгоритм не удался.   -  person gpuguy    schedule 22.05.2012
comment
@ Андрей, как вы думаете, для определения овальной формы следует использовать ту же процедуру? (Потому что в моем случае на самом деле формы овальные, а не круглые)   -  person gpuguy    schedule 22.05.2012
comment
На самом деле края отлично обнаруживаются, когда пороговое значение выполняется до хитрости. Но я предполагаю, что внутренне Canny также будет использовать пороговое значение. Так что могут быть некоторые проблемы с параметрами. В любом случае, ваш ответ сработал для меня и для некоторых других изображений. Спасибо   -  person gpuguy    schedule 22.05.2012


Ответы (2)


Вы должны использовать изображение с обнаруженным краем в качестве входных данных, а не с пороговым значением. Во-вторых, круги Хафа не будут работать для эллипсов, если только они не будут очень близки к кругам. Я рекомендую прочитать об обобщенном преобразовании Хафа и реализовать его для эллипсов.

person Andrey Rubshtein    schedule 22.05.2012
comment
Тершодинг должен быть сделан, а затем край, а затем hough Transforms. В моем случае для изображений почти круглой формы решения сработали, а овальные — нет. Поэтому я думаю, что обобщенное преобразование Хафа может быть лучшим решением. Приложение на самом деле намного проще, так как я знаю размер и многие другие параметры белых пятен, поэтому может быть какой-то тривиальный метод также работает в моем случае. - person gpuguy; 22.05.2012

Все дело в параметрах< /а>:

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

Если бы вы провели еще немного экспериментов, то в конечном итоге обнаружили бы, что с разными параметрами вы получаете разные результаты:

person karlphillip    schedule 18.05.2012
comment
Старался изо всех сил, использовал ваши, а также следующие параметры: CvSeq* results = cvHoughCircles( image, storage, CV_HOUGH_GRADIENT, 2,1 ); Но не сработало, круг не определяется, возврат ›0 - person gpuguy; 21.05.2012
comment
Приведенный выше код создал изображение, которым я поделился. Я использовал OpenCV 2.3.1. Я предлагаю вам проверить это на другой машине. - person karlphillip; 21.05.2012
comment
У меня есть такие библиотеки, как opencv_core240.lib, значит, у меня opencv 2.4. Ваши значения 4, ширина изображения/3 соответствуют dp = 1: обратное отношение разрешения и минимального расстояния между обнаруженными центрами. Я прав? - person gpuguy; 21.05.2012
comment
Я не знаю наизусть, но вы можете узнать это, просмотрев документацию OpenCV 2.3. Кстати, я только что протестировал свой код на Windows-боксе с OpenCV 2.3.1, и он тоже работал. - person karlphillip; 21.05.2012