突出显示由霍夫变换找到的线条 - OPENCV

时间:2014-05-10 20:20:39

标签: matlab opencv hough-transform

在Matlab中,通过组合霍夫变换,houghpeaks和houghlines,可以在原始图像中显示检测到的线条。

这可以在下图中显示(通过使用来自Matlab的houghlines帮助的示例代码生成)。检测到绿线。蓝色的是最长的一个:

output from example code by Mathoworks

我在我生成的简单合成图像上运行了cv :: HoughLines(几个正方形等)。图片附在此处:

my sample image

相关的代码部分是:

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

查看linesMat矩阵(我将其转换为此表单以便我可以使用image watch查看数据),同时运行for循环以在边缘图像上添加红线我看到rho和theta按长度排序图像中最长的一行。

我的输出是:

Showing the 8 strongest lines

线条是图像的整个宽度(或高度)。如何在Matlab示例中显示实际的行? 我可以从rho + theta回到x和y,然后我必须以某种方式将它们链接到检测到的边缘等等 - 也许有一种简单的方法可以做到这一点,我不知道了?

谢谢!

2 个答案:

答案 0 :(得分:6)

taoufik是正确的,我赞成他的回答。 在我阅读他的评论之前,我实际上在OpenCV 2计算机视觉应用程序设计手册中找到了答案。

我选择我的答案作为答案,因为它更完整,以备将来参考。

@taoufik - 再次感谢,伙计!

我会发布一个可能对其他人有用的代码片段(基于我在食谱中找到的解决方案。我只是编写了简短版本,而不是菜谱中优雅的类实现)。

我还在这里添加了一个我编写的小函数,用于计算用于在Canny的Matlab实现中找到canny边缘检测器的高阈值和低阈值的CDF,从而产生良好的结果。通常我也会在边缘检测之前进行高斯模糊(如Matlab中的canny.m中所示),但是附加的图像在综合上是完美的(没有噪声),所以在这里它是多余的。 我选择了一个较高的最低投票价值(&#39;阈值&#39;),因此只能找到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!
}

我对上面给出的代码段的解决方案是:

shapes with 4 highlighted lines

希望你觉得这很有用!

答案 1 :(得分:3)

你正在寻找的是概率霍夫变换。在OpenCV中,它可以在HoughLinesP()下找到。