[英]OpenCV 2d line intersection helper function
I was looking for a helper function to calculate the intersection of two lines in OpenCV.我正在寻找一个辅助函数来计算 OpenCV 中两条线的交点。 I have searched the API Documentation, but couldn't find a useful resource.
我搜索了 API 文档,但找不到有用的资源。
Are there basic geometric helper functions for intersection/distance calculations on lines/line segments in OpenCV?是否有用于 OpenCV 中线/线段的交点/距离计算的基本几何辅助函数?
There are no function in OpenCV API to calculate lines intersection, but distance is: OpenCV API 中没有计算线交点的函数,但距离是:
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;
}
There's one cool trick in 2D geometry which I find to be very useful to calculate lines intersection. 2D 几何中有一个很酷的技巧,我发现它对于计算线交点非常有用。 In order to use this trick we represent each 2D point and each 2D line in homogeneous 3D coordinates.
为了使用这个技巧,我们用均匀的 3D 坐标表示每个 2D 点和每个 2D 线。
At first let's talk about 2D points:首先让我们谈谈2D点:
(x, y)
corresponds to a 3D line that passes through points (0, 0, 0)
and (x, y, 1)
.(x, y)
对应于穿过点(0, 0, 0)
和(x, y, 1)
的 3D 线。(x, y, 1)
and (α•x, α•y, α)
and (β•x, β•y, β)
correspond to the same point (x, y)
in 2D space.(x, y, 1)
和(α•x, α•y, α)
和(β•x, β•y, β)
对应于二维空间中的同一个点(x, y)
。(x, y) -> (x, y, 1)
(x, y) -> (x, y, 1)
(x, y, ω) -> (x / ω, y / ω)
.(x, y, ω) -> (x / ω, y / ω)
。 If ω is zero that means "point at infinity".convertPointsToHomogeneous()
and convertPointsFromHomogeneous()
convertPointsToHomogeneous()
和convertPointsFromHomogeneous()
Now let's talk about 2D lines:现在让我们谈谈二维线:
(a, b, c)
which corresponds to 2D line equation: a•x + b•y + c = 0
(a, b, c)
,对应于二维线方程: a•x + b•y + c = 0
(a, b, c)
and (ω•a, ω•b, ω•c)
correspond to the same 2D line.(a, b, c)
和(ω•a, ω•b, ω•c)
对应于同一条二维线。(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)
(a, b, c)
对应于(nx, ny, d)
其中(nx, ny)
是单位长度法向量,d 是从线到(0, 0)
距离(nx, ny, d)
is (cos φ, sin φ, ρ)
where (φ, ρ)
are polar coordinates of the line.(nx, ny, d)
是(cos φ, sin φ, ρ)
其中(φ, ρ)
是直线的极坐标。 There're two interesting formulas that link together points and lines:有两个有趣的公式将点和线连接在一起:
(α•x₁, α•y₁, α) ✕ (β•x₂, β•y₂, β) = (a, b, c)
(α•x₁, α•y₁, α) ✕ (β•x₂, β•y₂, β) = (a, b, c)
给出齐次线坐标: (α•x₁, α•y₁, α) ✕ (β•x₂, β•y₂, β) = (a, b, c)
(a₁, b₁, c₁) ✕ (a₂, b₂, c₂) = (x, y, ω)
.(a₁, b₁, c₁) ✕ (a₂, b₂, c₂) = (x, y, ω)
。 If ω is zero that means lines are parallel (have no single intersection point in Euclidean geometry).Mat::cross()
or numpy.cross()
to get cross productMat::cross()
或numpy.cross()
来获得交叉积If you're still here, you've got all you need to find lines given two points and intersection point given two lines.如果您还在这里,那么您已经拥有了找到给定两点的线和给定两条线的交点所需的一切。
Here is my implementation for EmguCV (C#).这是我对 EmguCV (C#) 的实现。
static PointF GetIntersection(LineSegment2D line1, LineSegment2D line2)
{
double a1 = (line1.P1.Y - line1.P2.Y) / (double)(line1.P1.X - line1.P2.X);
double b1 = line1.P1.Y - a1 * line1.P1.X;
double a2 = (line2.P1.Y - line2.P2.Y) / (double)(line2.P1.X - line2.P2.X);
double b2 = line2.P1.Y - a2 * line2.P1.X;
if (Math.Abs(a1 - a2) < double.Epsilon)
throw new InvalidOperationException();
double x = (b2 - b1) / (a1 - a2);
double y = a1 * x + b1;
return new PointF((float)x, (float)y);
}
Using homogeneous coordinates makes your life easier:使用齐次坐标使您的生活更轻松:
cv::Mat intersectionPoint(const cv::Mat& line1, const cv::Mat& line2)
{
// Assume we receive lines as l=(a,b,c)^T
assert(line1.rows == 3 && line1.cols = 1
&& line2.rows == 3 && line2.cols == 1);
// Point is p=(x,y,w)^T
cv::Mat point = line1.cross(line2);
// Normalize so it is p'=(x',y',1)^T
if( point.at<double>(2,0) != 0)
point = point * (1.0/point.at<double>(2,0));
}
Note that if the third coordinate is 0 the lines are parallel and there is not solution in R² but in P^2, and then the point means a direction in 2D.请注意,如果第三个坐标为 0,则这些线是平行的,并且在 R² 中没有解,而在 P^2 中没有解,那么该点表示 2D 中的一个方向。
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.以下是我的 openCV c++ 实现。 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;
}
my implementation in Python (using numpy array) with line1 = [[x1, y1],[x2, y2]] & line2 = [[x1, y1],[x2, y2]]我在 Python 中的实现(使用 numpy 数组),line1 = [[x1, y1],[x2, y2]] & line2 = [[x1, y1],[x2, y2]]
def getIntersection(line1, line2):
s1 = numpy.array(line1[0])
e1 = numpy.array(line1[1])
s2 = numpy.array(line2[0])
e2 = numpy.array(line2[1])
a1 = (s1[1] - e1[1]) / (s1[0] - e1[0])
b1 = s1[1] - (a1 * s1[0])
a2 = (s2[1] - e2[1]) / (s2[0] - e2[0])
b2 = s2[1] - (a2 * s2[0])
if abs(a1 - a2) < sys.float_info.epsilon:
return False
x = (b2 - b1) / (a1 - a2)
y = a1 * x + b1
return (x, y)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.