c++opencvlinedrawhoughlines

How to draw a desired line from HoughLines function output in OpenCV C++?


Context :

Page No 8 in this lecture says that the OpenCV HoughLines function returns an N x 2 array of line parameters rho and theta which is stored in the array called lines.

Then in order to actually create the lines from these angles, we have some formulae and later we use the line function. The formulae are explained below in the code.

Code :

    //Assuming we start our program with the Input Image as shown below.
    //This array will be used for storing rho and theta as N x 2 array

    vector<Vec2f> lines; 

    //The input bw_roi is a canny image with detected edges
    HoughLines(bw_roi, lines, 1, CV_PI/180, 70, 0, 0); '

    //These formulae below do the line estimation based on rho and theta

    for( size_t i = 0; i < lines.size(); i++ )
    {
        float rho = lines[i][0], theta = lines[i][1];
        Point2d pt1, pt2;
        double m;
        double a = cos(theta), b = sin(theta);
        double x0 = a*rho, y0 = b*rho;

        //When we use 1000 below we get Observation 1 output. 
        //But if we use 200, we get Observation 2 output.

        pt1.x = cvRound(x0 + 1000*(-b)); 
        pt1.y = cvRound(y0 + 1000*(a));
        pt2.x = cvRound(x0 - 1000*(-b));
        pt2.y = cvRound(y0 - 1000*(a));

        //This line function is independent of HoughLines function    
        //and is used for drawing any type of line in OpenCV

        line(frame, pt1, pt2, Scalar(0,0,255), 3, LINE_AA);
     }

Input Image:

enter image description here

Observation 1:

enter image description here

Observation 2:

enter image description here

Problem:

In the code shown above if we play around with the number we multiply with a, -a, b & -b we get lines of different lengths. The Observation 2 was obtained when I multiplied by 200 instead of 1000 (which lead to Observation 1).

For more information, please refer to comments in lines 18 and 19 of code shown above.

Question:

When we draw lines from HoughLines output, how can we have control of, from where our line begins and ends ?

For instance, I want the right lane (red line pointing towards right bottom from left top corner) in Observation 2 to begin from the right bottom of the screen and point towards the left top of the screen (like a mirror image of the left lane).


Solution

  • Given

    a = cos(theta)
    b = sin(theta)
    
    x0 = a * rho
    y0 = b * rho
    

    you can write the formula for all points lying on the line defined by (rho, theta) as

    x = x0 - c * b
    y = y0 + c * a
    

    where c is distance from the reference point (intersect with perpendicular line through origin).

    In your case, you've evaluated it with c = 1000 and c = -1000 to get two points to draw a line between.

    You can rewrite those as

    c = (x0 - x) / b
    c = (y - y0) / a
    

    And then use substitution to calculate horizontal and vertical intercepts:

    x = x0 - ((y - y0) / a) * b
    

    or

    y = y0 + ((x0 - x) / b) * a
    

    NB: Take care to correctly handle the cases when a or b are 0.


    Let's say you have an 800x600 image (to keep numbers simple). We can define the bottom edge of the image as the line y = 599. Calculate the value of x where your line intercepts it using the above formula.

    Then use similar technique to find the second point to be able to draw a line.