OpenCV 2d line intersection helper function
There's one cool trick in 2D geometry which I find to be very useful to calculate lines intersection. In order to use this trick we represent each 2D point and each 2D line in homogeneous 3D coordinates.
At first let's talk about 2D points:
- Each 2D point
(x, y)
corresponds to a 3D line that passes through points(0, 0, 0)
and(x, y, 1)
. - So
(x, y, 1)
and(α•x, α•y, α)
and(β•x, β•y, β)
correspond to the same point(x, y)
in 2D space. - Here's formula to convert 2D point into homogeneous coordinates:
(x, y) -> (x, y, 1)
- Here's formula to convert homogeneous coordinates into 2D point:
(x, y, ω) -> (x / ω, y / ω)
. If ω is zero that means "point at infinity". It doesn't correspond to any point in 2D space. - In OpenCV you may use
convertPointsToHomogeneous()
andconvertPointsFromHomogeneous()
Now let's talk about 2D lines:
- Each 2D line can be represented with three coordinates
(a, b, c)
which corresponds to 2D line equation:a•x + b•y + c = 0
- So
(a, b, c)
and(ω•a, ω•b, ω•c)
correspond to the same 2D line. - Also,
(a, b, c)
corresponds to(nx, ny, d)
where(nx, ny)
is unit length normal vector and d is distance from the line to(0, 0)
- Also,
(nx, ny, d)
is(cos φ, sin φ, ρ)
where(φ, ρ)
are polar coordinates of the line.
There're two interesting formulas that link together points and lines:
- Cross product of two distinct points in homogeneous coordinates gives homogeneous line coordinates:
(α•x₁, α•y₁, α) ✕ (β•x₂, β•y₂, β) = (a, b, c)
- Cross product of two distinct lines in homogeneous coordinates gives homogeneous coordinate of their intersection point:
(a₁, b₁, c₁) ✕ (a₂, b₂, c₂) = (x, y, ω)
. If ω is zero that means lines are parallel (have no single intersection point in Euclidean geometry). - In OpenCV you may use either
Mat::cross()
ornumpy.cross()
to get cross product
If you're still here, you've got all you need to find lines given two points and intersection point given two lines.
An algorithm for finding line intersection is described very well in the post How do you detect where two line segments intersect?
The following is my openCV c++ implementation. It uses the same notation as in above post
bool getIntersectionPoint(Point a1, Point a2, Point b1, Point b2, Point & intPnt){
Point p = a1;
Point q = b1;
Point r(a2-a1);
Point s(b2-b1);
if(cross(r,s) == 0) {return false;}
double t = cross(q-p,s)/cross(r,s);
intPnt = p + t*r;
return true;
}
double cross(Point v1,Point v2){
return v1.x*v2.y - v1.y*v2.x;
}
There are no function in OpenCV API to calculate lines intersection, but distance is:
cv::Point2f start, end;
double length = cv::norm(end - start);
If you need a piece of code to calculate line intersections then here it is:
// Finds the intersection of two lines, or returns false.
// The lines are defined by (o1, p1) and (o2, p2).
bool intersection(Point2f o1, Point2f p1, Point2f o2, Point2f p2,
Point2f &r)
{
Point2f x = o2 - o1;
Point2f d1 = p1 - o1;
Point2f d2 = p2 - o2;
float cross = d1.x*d2.y - d1.y*d2.x;
if (abs(cross) < /*EPS*/1e-8)
return false;
double t1 = (x.x * d2.y - x.y * d2.x)/cross;
r = o1 + d1 * t1;
return true;
}