13
votes

Working with C++ and opencv

I am trying to calculate an angle between two points.....I have a 2D plane with a changing center point of a bounding box, Now if the center point in frame 1 has changed its location in frame 2 i need to find the angle of these two points.

Here is the example of what i am trying to do:

enter image description here

Can someone suggest a way of working this out.......? some kind of mathematical solution or perhaps a C++ function.

2
There is no angle between two points, just a line. You need two lines to define an angle. Where is the other line? - David Heffernan
Yep, where is the angle? That said, depending on where your angle is, the atan2() function might be useful, too, but you need to improve your question/diagram to get a definite answer. - Ulrich Eckhardt
In fact, it would be useful if you could draw the angle on the image. - Joseph Mansfield

2 Answers

19
votes

Use Dot product:

v1.v2 = v1.x * v2.x + v1.y * v2.y

v1.v2 = |v1| * |v2| * cos(theta)
---------------------------------+
                                 |
                                 +-->  theta = acos(v1.v2 / |v1|*|v2|)

A sample code is:

float angleBetween(const Point &v1, const Point &v2)
{
    float len1 = sqrt(v1.x * v1.x + v1.y * v1.y);
    float len2 = sqrt(v2.x * v2.x + v2.y * v2.y);

    float dot = v1.x * v2.x + v1.y * v2.y;

    float a = dot / (len1 * len2);

    if (a >= 1.0)
        return 0.0;
    else if (a <= -1.0)
        return PI;
    else
        return acos(a); // 0..PI
}

It calculates angle between v1 and v2 as below image

enter image description here

6
votes

Assuming you want to calculate the angle between the two points relative to the origin of the 2D plane, you can use the dot product to calculate the angle between the points (like how the other answer of this question described).

OpenCV has implementations of calculating the dot product and the length of points. The dot product of two points is:

v1.dot(v2) // v1.x * v2.x + v1.y * v2.y

Length of vector (commonly referred as the L2 Norm of vector) using cv::norm is:

cv::norm(v1) // sqrt(v1.x * v1.x + v1.y * v1.y)

Using OpenCV's implementations of dot product and the length of vector we have the following sample code

double angle(const Point& v1, const Point& v2)
{
    double cosAngle = v1.dot(v2) / (cv::norm(v1) * cv::norm(v2));
    if (cosAngle > 1.0)
        return 0.0;
    else if (cosAngle < -1.0)
        return CV_PI;
    return std::acos(cosAngle);
}

This solution isn't only limited to 2D points. It can be used for calculating the angle between 3D points as well.

Note that angle is in Radians.

If you want degrees, you should multiply it by 180 / Pi:

return std::acos(cosAngle) * 180 / CV_PI