OpenCV,C ++,使用HoughLinesP进行线路检测

时间:2015-09-09 09:54:26

标签: c++ opencv image-processing line detection

我想在两行之间裁剪图像,如下图所示。但HoughLinesP并未充分认识到底线。 由于侵蚀,底线点并没有真正的边缘,但这很重要吗?

如何检测底线,然后根据这两行裁剪图像?

原始图片:

enter image description here

已处理的图片:

enter image description here

Canny edged:

enter image description here

检测到的行:

enter image description here

线路检测代码:

Mat dst, cdst,src2;
cv::blur( src, src2, cv::Size(5,5) );
Canny(src2, dst, 150, 300, 5);
cvtColor(dst, cdst, CV_GRAY2BGR);

//Mat original = imread("final_sample1.png",0);

vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, 2*CV_PI/180, 100,1000, 50 );

用于显示行:

   for( size_t i = 0; i < lines.size(); i++ )
{
    Vec4i l = lines[i];

   // oran = float(l[1] / col_size );
    double angle = atan2(l[3] - l[1], l[2] - l[0]) * 180.0 / CV_PI;

    if(angle  < 5  && angle >=-5   ){
    //if(1){
        cout << l[0] << "," << l[1] << "," << l[2] << "," << l[3] << endl;
        line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
    }
}

编辑:

对于线检测,应用自适应阈值处理原始图像可以得到更可靠的结果。

adaptiveThreshold(img,adaptiveTresholded,255,ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY,75,15);

我测试了20个行数不同的样本,感谢Micka的修改,我得到了很好的结果。为了检测正确的行,我放了一个if语句。

“ratio”变量是图像的y1 /行大小。并检查线角度以防止 无关紧要的。

for( size_t i = 0; i < lines.size(); i++ )
{
    Vec4i l = lines[i];

    raito = float(l[1] / row_size );
    double angle = atan2(l[3] - l[1], l[2] - l[0]) * 180.0 / CV_PI;

  if(angle  < 10 && angle >=- 10 && ratio > 0.15 && ratio< 0.8){
    //if(1){
        cout <<"Here: " <<  l[0] << "," << l[1] << "," << l[2] << "," << l[3] <<
        ", Oran: " << oran <<  endl;
        line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3);
    }
}

2 个答案:

答案 0 :(得分:1)

使用你的图像和这个代码(基本上你的,但减少了最大线间隙,并使用一些扩张实际上使连接的straigt部分从非直线底线:

int main()
{
    cv::Mat input = cv::imread("../inputData/LongLine.jpg");

    cv::Mat gray;
    cv::cvtColor(input,gray,CV_BGR2GRAY);

    // threshold because of loaded jpeg artifacts
    cv::Mat edges = gray > 100;

    cv::dilate(edges, edges, cv::Mat());
    cv::dilate(edges, edges, cv::Mat());
    cv::dilate(edges, edges, cv::Mat());

    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(edges, lines, 1, 2*CV_PI/180, 100,1000, 10 );

    for( size_t i = 0; i < lines.size(); i++ )
    {
        cv::Vec4i l = lines[i];

        cv::line( input, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(0,0,255), 3);

    }


    cv::imwrite("../outputData/LongLine.png", input);
    cv::resize(input, input, cv::Size(), 0.1, 0.1);
    cv::imshow("input",input);
    cv::waitKey(0);
    return 0;
}

得到这个结果:

enter image description here

对于HoughLinesP,重要的是线条非常直,因为求和线的厚度预计为1.因此,如果累加器仅缺少一个像素,则失败。由于底线与第一条底线不同,这可能是问题所在。

答案 1 :(得分:0)

以下是沿着水平线累积原始强度的图,在顶部和底部线对周围的ROI中。

enter image description here

enter image description here

毋庸置疑,检测峰值并不是一个真正的问题。

如果歪斜有限,您可以稍微旋转一下重复此过程。