Opencv学习笔记-----求取两条直线的交点坐标

求取二直线交点(基于OpenCv)

理论补充:

两直线是否有交点(或线段齐延长线是否相交)是一个Line-line intersection(Wikipedia)问题

在一个2维平面中有两直线L_{1}(点(x_1,y_1)到点(x_2,y_2)L_2(点(x_3,y_3)到点(x_4,y_4),这两条直线的交点P(P_x,P_y)用行列式表示如下:

Opencv学习笔记-----求取两条直线的交点坐标_第1张图片

行列式可变形写作:

(P_x,P_y)=(\frac{\left(x_{1} y_{2}-y_{1} x_{2}\right)\left(x_{3}-x_{4}\right)-\left(x_{1}-x_{2}\right)\left(x_{3} y_{4}-y_{3} x_{4}\right)}{\left(x_{1}-x_{2}\right)\left(y_{3}-y_{4}\right)-\left(y_{1}-y_{2}\right)\left(x_{3}-x_{4}\right)},\frac{\left(x_{1} y_{2}-y_{1} x_{2}\right)\left(y_{3}-y_{4}\right)-\left(y_{1}-y_{2}\right)\left(x_{3} y_{4}-y_{3} x_{4}\right)}{\left(x_{1}-x_{2}\right)\left(y_{3}-y_{4}\right)-\left(y_{1}-y_{2}\right)\left(x_{3}-x_{4}\right)})

该交点是由4个点、两两一组确定的线段所在位置的直线的交点

根据贝塞尔参数可以将两直线定义为:

L_{1}=\left(\begin{array}{l}{x_{1}} \\ {y_{1}}\end{array}\right)+t\left(\begin{array}{c}{x_{2}-x_{1}} \\ {y_{2}-y_{1}}\end{array}\right), \quad L_{2}=\left(\begin{array}{c}{x_{3}} \\ {y_{3}}\end{array}\right)+u\left(\begin{array}{c}{x_{4}-x_{3}} \\ {y_{4}-y_{3}}\end{array}\right)

其中ut均是实数、且ut分别为:

t=\frac{\left|\begin{array}{ll}{x_{1}-x_{3}} & {x_{3}-x_{4}} \\ {y_{1}-y_{3}} & {y_{3}-y_{4}}\end{array}\right|}{\left|\begin{array}{cc}{x_{1}-y_{2}} & {x_{3}-x_{4}} \\ {y_{1}-y_{2}} & {y_{3}-y_{4}}\end{array}\right|}=\frac{\left(x_{1}-x_{3}\right)\left(y_{3}-y_{4}\right)-\left(y_{1}-y_{3}\right)\left(x_{3}-x_{4}\right)}{\left(x_{1}-x_{2}\right)\left(y_{3}-y_{4}\right)-\left(y_{1}-y_{2}\right)\left(x_{3}-x_{4}\right)}

u=-\frac{\left|\begin{array}{ll}{x_{1}-x_{2}} & {x_{1}-x_{3}} \\ {y_{1}-y_{2}} & {y_{1}-y_{3}}\end{array}\right|}{\left|\begin{array}{ccc}{x_{1}-x_{2}} & {x_{3}-x_{4}} \\ {y_{1}-y_{2}} & {y_{3}-y_{4}}\end{array}\right|}=-\frac{\left(x_{1}-x_{2}\right)\left(y_{1}-y_{3}\right)-\left(y_{1}-y_{2}\right)\left(x_{1}-x_{3}\right)}{\left(x_{1}-x_{2}\right)\left(y_{3}-y_{4}\right)-\left(y_{1}-y_{2}\right)\left(x_{3}-x_{4}\right)}

0.0 \leqslant t \leqslant 1.00.0 \leqslant u \leqslant 1.0时、存在交点P。那么在满足交点P(P_x,P_y)存在的情况下,交点可以表示为:

\left(P_{x}, P_{y}\right)=\left(x_{1}+t\left(x_{2}-x_{1}\right), y_{1}+t\left(y_{2}-y_{1}\right)\right) \quad \text { or } \quad\left(P_{x}, P_{y}\right)=\left(x_{3}+u\left(x_{4}-x_{3}\right), y_{3}+u\left(y_{4}-y_{3}\right)\right)

当两直线平行或者重合的时候:t、u对应的表达式的分母为0:

(x_1-x_2)(y_3-y_4)-(y_1-y_2)(x_3-x_4)=0


理解了两条直线的叉乘之后用opencv学习了一个能求取两条直线交点的代码,而且发现很多人都遇到求直线交点的问题,然后就把我学习到的代码贴出来,希望能对你有所帮助

代码如下:

 

#include 
#include 
using namespace std;
using namespace cv;

//****************************************************************************************
//  求二条直线的交点的公式
//  有如下方程    a1*x+b1*y=c1
//                a2*x+b2*y=c2
//                x= | c1 b1|  / | a1 b1 |      y= | a1 c1| / | a1 b1 |
//                   | c2 b2|  / | a2 b2 |         | a2 c2| / | a2 b2 |
//
//   a1= (L1.pEnd.y-L1.pStart.y)   
//   b1= (L1.pEnd.x-L1.pStart.x)
//   c1= L1.pStart.x*(L1.pEnd.y-L1.pStart.y)-(L1.pEnd.x-L1.pStart.x)*L1.pStart.y
//   a2= (L2.pEnd.y-L2.pStart.y)   
//   b2= (L2.pEnd.x-L2.pStart.x)
//   c2= L2.pStart.x*(L2.pEnd.y-L2.pStart.y)-(L2.pEnd.x-L2.pStart.x)*L2.pStart.y  
//定义两个结构体方便理解
struct PT
{
	int x;
	int y;
};
struct LINE
{
	PT pStart;
	PT pEnd;
};
Point CrossPoint(const LINE *line1, const LINE *line2)
{
	//    if(!SegmentIntersect(line1->pStart, line1->pEnd, line2->pStart, line2->pEnd))
	//    {// segments not cross   
	//        return 0;
	//    }
	Point pt;
	// line1's cpmponent
	double X1 = line1->pEnd.x - line1->pStart.x;//b1
	double Y1 = line1->pEnd.y - line1->pStart.y;//a1
	// line2's cpmponent
	double X2 = line2->pEnd.x - line2->pStart.x;//b2
	double Y2 = line2->pEnd.y - line2->pStart.y;//a2
	// distance of 1,2
	double X21 = line2->pStart.x - line1->pStart.x;
	double Y21 = line2->pStart.y - line1->pStart.y;
	// determinant
	double D = Y1*X2 - Y2*X1;// a1b2-a2b1
	// 
	if (D == 0) return 0;
	// cross point
	pt.x = (X1*X2*Y21 + Y1*X2*line1->pStart.x - Y2*X1*line2->pStart.x) / D;
	// on screen y is down increased ! 
	pt.y = -(Y1*Y2*X21 + X1*Y2*line1->pStart.y - X2*Y1*line2->pStart.y) / D;
	// segments intersect.
	if ((abs(pt.x - line1->pStart.x - X1 / 2) <= abs(X1 / 2)) &&
		(abs(pt.y - line1->pStart.y - Y1 / 2) <= abs(Y1 / 2)) &&
		(abs(pt.x - line2->pStart.x - X2 / 2) <= abs(X2 / 2)) &&
		(abs(pt.y - line2->pStart.y - Y2 / 2) <= abs(Y2 / 2)))
	{
		return pt;
	}
	return 0;
}
int main()
{
	LINE line1, line2;
	line1.pStart.x = 0;
	line1.pStart.y = 0;
	line1.pEnd.x = 2;
	line1.pEnd.y = 2;

	line2.pStart.x = 0;
	line2.pStart.y = 2;
	line2.pEnd.x = 2;
	line2.pEnd.y = 0;

	Point cross = CrossPoint(&line1, &line2);
	cout << "CrossPoint: " << "(" << cross.x << "," << cross.y << ")" << endl;
	system("pause");
	return 0;
}

Line1、Line2和交点如图:
Opencv学习笔记-----求取两条直线的交点坐标_第2张图片

 

代码运行结果:

求出来预期的(1,1)交点。

 

 

鄙人刚入门Opencv才疏学浅,尚有不足还望不惜赐教。

 
 
 
 

你可能感兴趣的:(opencv,opencv,叉乘,两直线交点)