Выделите линии, найденные преобразованием Хафа - OPENCV

В Matlab, комбинируя преобразование hough, houghpeaks и houghlines, можно показать обнаруженные линии в исходном изображении.

Это можно показать на следующем изображении (созданном с использованием примера кода из справки Matlab для houghlines). Обнаружены зеленые линии. Синий - самый длинный:

вывод из примера кода от Mathoworks

Я запустил cv :: HoughLines на созданном мной простом синтетическом изображении (несколько квадратов и т. Д.). Изображение прикреплено сюда:

мой образец изображения

Соответствующая часть кода:

cv::vector<cv::Vec2f> lines;
cv::HoughLines(I_BW, lines, 1, CV_PI/180,200);
cv::Mat linesMat ( lines, true );

Просмотр матрицы linesMat (я преобразовал ее в эту форму, чтобы я мог использовать просмотр изображений для просмотра данных) при запуске цикла for для добавления красной линии поверх изображения края, я вижу, что rho и theta упорядочены по длине самого длинного линия на изображении.

Мой вывод:

Показаны 8 самых сильных линий

Линии составляют всю ширину (или высоту) изображения. Как я могу просто показать фактические строки, как в примере Matlab? Я могу вернуться от rho + theta к x и y, но тогда мне нужно как-то связать их с обнаруженными краями и т. Д. - может быть, есть простой способ сделать это, которого мне не хватает?

Спасибо!


person CV_User    schedule 10.05.2014    source источник


Ответы (2)


taoufik прав, и я поддержал его ответ. Я действительно нашел ответ в Поваренной книге по программированию приложений компьютерного зрения OpenCV 2, прежде чем прочитал его комментарий.

Я выбираю свой ответ в качестве ответа, потому что он является более полным для использования в будущем.

@taoufik - еще раз спасибо, чувак!

Я отправлю фрагмент кода, который может быть полезен другим людям (на основе решения, которое я нашел в книге рецептов. Я просто написал короткую версию, а не элегантную реализацию класса из книги рецептов).

Я также добавляю сюда небольшую функцию, которую я написал, которая вычисляет CDF, используемую для нахождения верхнего и нижнего порога для детектора ловких краев в реализации Canny в Matlab, что дает хорошие результаты. Обычно я также делаю размытие по Гауссу перед обнаружением края (как показано в canny.m в Matlab), но прикрепленное изображение синтетически идеально (без шума), поэтому здесь оно избыточно. Я выбрал высокое минимальное значение голоса («порог»), поэтому будут обнаружены только 4 длинные строки.

Начнем с кода в основной функции:

cv::Mat image = cv::imread("shapes.jpg");
int bins = 256;
cv::Mat cdf = getGrayCDF(image,bins);
cv::Mat diffy = cdf>0.7;
cv::Mat NonZero_Locations;   // output, locations of non-zero pixels 
cv::findNonZero(diffy, NonZero_Locations);
double highThreshold = double((NonZero_Locations.at<cv::Point>(0).y))/bins;
double lowThreshold = 0.4*highThreshold;
cv::Mat contours;
// cv::GaussianBlur( image, contours, cv::Size(7,7),2 ); // NOT REQUIRED HERE. Syhnthetic image
cv::Canny( image, contours, lowThreshold*bins, highThreshold*bins);
std::vector<cv::Vec4i> lines;
double rho = 1; // delta_rho resolution
double theta = CV_PI/180; // delta_theta resolution
int threshold = 300; // threshold number of votes , I SET A HIGH VALUE TO FIND ONLY THE LONG LINES
double minLineLength = 0; // min length for a line
double maxLineGap = 2; // max allowed gap along the line
cv::HoughLinesP(contours,lines, rho, theta, threshold, minLineLength, maxLineGap); // running probabilistic hough line
if (image.channels()!=3) {cv::cvtColor(image,image,CV_GRAY2BGR);} // so we can see the red lines
int line_thickness = 2;
cv::Scalar color=cv::Scalar(0,0,255);
std::vector<cv::Vec4i>::const_iterator iterator_lines = lines.begin();
while (iterator_lines!=lines.end()) {
    cv::Point pt1((*iterator_lines)[0],(*iterator_lines)[1]);
    cv::Point pt2((*iterator_lines)[2],(*iterator_lines)[3]);
    cv::line( image, pt1, pt2, color, line_thickness);
    ++iterator_lines;
}
cv::imshow("found lines", image); cvWaitKey(0); cv::destroyWindow("found lines");

И я закончу своей функцией для вычисления простой кумулятивной функции распределения оттенков серого:

cv::Mat getGrayCDF(cv::Mat Input, int histSize){
cv::Mat InputGray = Input.clone();
if (InputGray.channels()!=1) {cv::cvtColor(Input,InputGray,CV_BGR2GRAY);}
float range[] = { 0, histSize  } ;
const float* histRange = { range };
bool uniform = true; bool accumulate = false;
cv::Mat hist;
calcHist( &InputGray, 1, 0, cv::Mat(), hist, 1, &histSize , &histRange, uniform, accumulate );
for (int i = 1; i < hist.rows; i++) {
    float* data = hist.ptr<float>(0);
    data[i] += data[i-1];
}
return hist/(InputGray.total()); // WE NOW HAVE A *NORMALIZED* COMPUTED CDF!
}

Мое решение для приведенного выше фрагмента:

фигуры с 4 выделенными линиями

Надеюсь, вы найдете это полезным!

person CV_User    schedule 12.05.2014

То, что вы ищете, - это вероятностное преобразование Хафа. В OpenCV он доступен в разделе HoughLinesP().

person tofi9    schedule 12.05.2014