简体   繁体   English

OpenCV 2d 线相交辅助函数

[英]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点:

  1. Each 2D point (x, y) corresponds to a 3D line that passes through points (0, 0, 0) and (x, y, 1) .每个 2D 点(x, y)对应于穿过点(0, 0, 0)(x, y, 1)的 3D 线。
  2. So (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)
  3. Here's formula to convert 2D point into homogeneous coordinates: (x, y) -> (x, y, 1)这是将 2D 点转换为齐次坐标的公式: (x, y) -> (x, y, 1)
  4. Here's formula to convert homogeneous coordinates into 2D point: (x, y, ω) -> (x / ω, y / ω) .这是将齐次坐标转换为二维点的公式: (x, y, ω) -> (x / ω, y / ω) If ω is zero that means "point at infinity".如果 ω 为零,则表示“指向无穷远”。 It doesn't correspond to any point in 2D space.它不对应于 2D 空间中的任何点。
  5. In OpenCV you may use convertPointsToHomogeneous() and convertPointsFromHomogeneous()在 OpenCV 中,您可以使用convertPointsToHomogeneous()convertPointsFromHomogeneous()

Now let's talk about 2D lines:现在让我们谈谈二维线:

  1. Each 2D line can be represented with three coordinates (a, b, c) which corresponds to 2D line equation: a•x + b•y + c = 0每条二维线可以用三个坐标(a, b, c) ,对应于二维线方程: a•x + b•y + c = 0
  2. So (a, b, c) and (ω•a, ω•b, ω•c) correspond to the same 2D line.所以(a, b, c)(ω•a, ω•b, ω•c)对应于同一条二维线。
  3. 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)此外, (a, b, c)对应于(nx, ny, d)其中(nx, ny)是单位长度法向量,d 是从线到(0, 0)距离
  4. Also, (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:有两个有趣的公式将点和线连接在一起:

  1. Cross product of two distinct points in homogeneous coordinates gives homogeneous line coordinates: (α•x₁, α•y₁, α) ✕ (β•x₂, β•y₂, β) = (a, b, c)齐次坐标中两个不同点的(α•x₁, α•y₁, α) ✕ (β•x₂, β•y₂, β) = (a, b, c)给出齐次线坐标: (α•x₁, α•y₁, α) ✕ (β•x₂, β•y₂, β) = (a, b, c)
  2. Cross product of two distinct lines in homogeneous coordinates gives homogeneous coordinate of their intersection point: (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).如果 ω 为零,则表示线是平行的(在欧几里得几何中没有单个交点)。
  3. In OpenCV you may use either Mat::cross() or numpy.cross() to get cross product在 OpenCV 中,您可以使用Mat::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM