happy
happy

Reputation: 21

OpenCV, C++, Line Detection with HoughLinesP

I want to crop the image between two lines, as shown in the image below. But the bottom line is not recognized well with HoughLinesP. The bottom line points are not really edged because of eroding, but is it important?

How can I detect the bottom line, and then crop the image according to these 2 lines?

Original image:

enter image description here

Processed image:

enter image description here

Canny edged:

enter image description here

Lines detected:

enter image description here

Code For Line Detection :

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 for displaying lines :

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

EDIT:

For line detection appliying adaptive tresholding to original image gives more reliable results.

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

I tested on 20 samples which has different number of rows , and thanks to Micka, with his modification, I got good results. To detect the right lines I put an if statement.

"ratio" variable is the y1 / row size of the image. And checking the line angle to prevent irrelevant lines.

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

Upvotes: 0

Views: 7976

Answers (2)

user1196549
user1196549

Reputation:

Here are the plots of the accumulated raw intensities along horizontals, in ROIs around the top and bottom line pairs.

enter image description here

enter image description here

Needless to say, detecting the peaks isn't a real problem.

If there can be limited skew, you can repeat the process with a little rotation.

Upvotes: 0

Micka
Micka

Reputation: 20160

using your image and this code (basically yours but reduced the maximum line gap and used some dilates to actually make connected straigt parts out of the non-straight bottom line:

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

getting this result:

enter image description here

For HoughLinesP is is important that the line is really straight, because the summed lines are expected to have thickness 1. So if the accumulator misses lines by just one pixel, it fails. Since the bottom lines aren't as straight as the first ones, this might be the problem.

Upvotes: 1

Related Questions