Anubhav Rohatgi
Anubhav Rohatgi

Reputation: 458

Convert cv::Vec4f line to cv::Vec2f

I have a pair of Cartesian coordinates that represent a line in an image. I would like to convert this line to polar form and draw it over the image.

e.g

  cv::Vec4f line {10,20,60,70};
    float x1 = line[0];
    float y1 = line[1];
    float x2 = line[2];
    float y2 = line[3];

I want this line to be represented in cv::Vec2f form(rho,theta).

Taking care of rho & theta with all possible slopes.

Given are the image dimensions :: w and h;

w = image.cols h = image.rows

How can I achieve this.

N.B: We can also assume that the line can be an extended one running across the image.

for (size_t i = 0; i < lines.size(); i++)
        {
            int x1 = lines[i][0];
            int y1 = lines[i][1];
            int x2 = lines[i][2];
            int y2 = lines[i][3];


            float d = sqrt(((y1-y2)*(y1-y2)) + ((x2-x1)*(x2-x1)) );
            float rho = (y1*x2 - y2*x1)/d;
            float theta = atan2(x2 - x1,y1-y2) ;

            if(rho < 0){
                theta *= -1;
                rho *= -1;
            }

             linv2f.push_back(cv::Vec2f(rho,theta));
         }

The above approach doesnt give me results when I plot the lines I dont get the lines that are overlapping their original vec4f form.

I use this to convert vec2f to vec4f for testing :

cv::Vec4f cvtVec2fLine(const cv::Vec2f& data, const cv::Mat& img)
{
    float const rho = data[0];
    float const theta = data[1];

    cv::Point pt1,pt2;

    if((theta < CV_PI/4. || theta > 3. * CV_PI/4.)){
        pt1 = cv::Point(rho / std::cos(theta), 0);
        pt2 = cv::Point( (rho - img.rows * std::sin(theta))/std::cos(theta), img.rows);
    }else {
        pt1 = cv::Point(0, rho / std::sin(theta));
        pt2 = cv::Point(img.cols, (rho - img.cols * std::cos(theta))/std::sin(theta));
    }

    cv::Vec4f l;
    l[0] = pt1.x;
    l[1] = pt1.y;
    l[2] = pt2.x;
    l[3] = pt2.y;
    return l;
}

Upvotes: 0

Views: 2394

Answers (1)

MBo
MBo

Reputation: 80187

rho-theta equation has form

x * Cos(Theta) + y * Sin(Theta) - Rho = 0

We want to represent equation 'by two points' into rho-theta form (page 92 in pdf here). If we have

 x * A + y * B - C = 0

and need coefficients in trigonometric form, we can divide all equation by magnitude of (A,B) coefficient vector.

D = Length(A,B) = Math.Hypot(A,B)
x * A/D + y * B/D - C/D = 0

note that (A/D)^2 + (B/D)^2 = 1 - basic trigonometric equality, so we can consider A/D and B/D as cosine and sine of some angle theta.

Your line equation is

(y-y1) * (x2-x1) - (x-x1) * (y2-y1) = 0
or
x * (y1-y2) + y * (x2-x1) - (y1 * x2  - y2 * x1) = 0
let
D = Sqrt((y1-y2)^2 + (x2-x1)^2)
so
Theta = ArcTan2(x2-x1, y1-y2)
Rho = (y1 * x2  - y2 * x1) / D   

edited

If Rho is negative, change sign of Rho and shift Theta by Pi

Example:

 x1=1,y1=0, x2=0,y2=1
 Theta = atan2(-1,-1)=-3*Pi/4
 D=Sqrt(2)
 Rho=-Sqrt(2)/2  negative =>

 Rho = Sqrt(2)/2
 Theta = Pi/4

Back substitutuon - find points of intersection with axes

0 * Sqrt(2)/2 + y0 * Sqrt(2)/2 - Sqrt(2)/2 = 0
x=0 y=1

x0 * Sqrt(2)/2 + 0 * Sqrt(2)/2 - Sqrt(2)/2 = 0
x=1 y=0

Upvotes: 4

Related Questions