opencv 线段相交怎么判断?用霍夫变换提取出的两条线段,怎么判断两条线段是否相交?应该用什么方法啊?求指导~

来源:学生作业帮助网 编辑:作业帮 时间:2024/05/06 20:23:05
opencv 线段相交怎么判断?用霍夫变换提取出的两条线段,怎么判断两条线段是否相交?应该用什么方法啊?求指导~

opencv 线段相交怎么判断?用霍夫变换提取出的两条线段,怎么判断两条线段是否相交?应该用什么方法啊?求指导~
opencv 线段相交怎么判断?
用霍夫变换提取出的两条线段,怎么判断两条线段是否相交?应该用什么方法啊?求指导~

opencv 线段相交怎么判断?用霍夫变换提取出的两条线段,怎么判断两条线段是否相交?应该用什么方法啊?求指导~
一.矢量基本知识
因为后面的计算需要一些矢量的基本知识,这里只是简单的列举如下,如果需要更加详细的信息,可以自行搜索wikipedia或google.
1.矢量的概念:如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段(directed segment).如果有向线段p1p2的起点p1在坐标原点,我们可以把它称为矢量(vector)p2.
2.矢量加减法:设二维矢量P = ( x1, y1 ),Q = ( x2 , y2 ),则矢量加法定义为: P + Q = ( x1 + x2 , y1 + y2 ),同样的,矢量减法定义为: P - Q = ( x1 - x2 , y1 - y2 ).显然有性质 P + Q = Q + P,P - Q = - ( Q - P ).
3.矢量的叉积:计算矢量叉积是与直线和线段相关算法的核心部分.设矢量P = ( x1, y1 ),Q = ( x2, y2 ),则矢量叉积定义为由(0,0)、p1、p2和p1+p2所组成的平行四边形的带符号的面积,即:P × Q = x1*y2 - x2*y1,其结果是一个标量.显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q ).一般在不加说明的情况下,本文下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积.
叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:
  若 P × Q > 0 , 则P在Q的顺时针方向.
  若 P × Q < 0 , 则P在Q的逆时针方向.
  若 P × Q = 0 , 则P与Q共线,但可能同向也可能反向.
4.折线段的拐向判断:折线段的拐向判断方法可以直接由矢量叉积的性质推出.对于有公共端点的线段p0p1和p1p2,通过计算(p2 - p0) × (p1 - p0)的符号便可以确定折线段的拐向:
  若(p2 - p0) × (p1 - p0) > 0,则p0p1在p1点拐向右侧后得到p1p2.
  若(p2 - p0) × (p1 - p0) < 0,则p0p1在p1点拐向左侧后得到p1p2.
  若(p2 - p0) × (p1 - p0) = 0,则p0、p1、p2三点共线.
这一条判断也可用来判断点在线段或直线的哪一测.
为了后文的叙述方便,先定义几个结构:
struct point{
int x;
int y;
};
struct v{
point start;
point end;
};
计算两条直线的叉积(cross production), 这里由于定义的都是二维的情况,本质上说,在平面上两个向量的叉积应该是垂直平面的,这里函数返回的整数值即为z轴上的值:
int crossProduct(v* v1, v* v2){
v vt1, vt2;
int result = 0;

vt1.start.x = 0;
vt1.start.y = 0;
vt1.end.x = v1->end.x - v1->start.x;
vt1.end.y = v1->end.y - v1->start.y;

vt2.start.x = 0;
vt2.start.y = 0;
vt2.end.x = v2->end.x - v2->start.x;
vt2.end.y = v2->end.y - v2->start.y;

result = vt1.end.x * vt2.end.y - vt2.end.x * vt1.end.y;
return result;
}
二.判断两条直线相交
先来看一个简单的情况,即判断两条直线是否相交.
第一个可能会想到的办法,就是判断斜率,这个在中学时代就学过了,不过斜率需要考虑垂直的特殊情况,比较麻烦.更好的办法或许是计算两个向量的叉积,如果为0,则是平行或者重合的,否则两直线相交.
代码就不贴了,直接调用上面的函数就ok了.
三.判断两线段相交
经典方法,就是跨立试验了,即如果一条线段跨过另一条线段,则线段的两个端点分别在另一条线段的两侧.但是,还需要检测边界情况,即两条线段中可能某条线段的某个端点正好落在另一条线段上.这也是算法导论中介绍的算法.
程序模拟如下:
int direction(point* pi, point* pj, point* pk){
point p1, p2;

p1.x = pk->x - pi->x;
p1.y = pk->y - pi->y;

p2.x = pj->x - pi->x;
p2.y = pj->y - pi->y;

return crossProduct(&p1, &p2);
}
int onSegment(point* pi, point* pj, point* pk){
int minx, miny, maxx, maxy;
if (pi->x > pj->x){
minx = pj->x;
maxx = pi->x;
}
else{
minx = pi->x;
maxx = pj->x;
}

if (pi->y > pj->y){
miny = pj->y;
maxy = pi->y;
}
else{
miny = pi->y;
maxy = pj->y;
}

if (minx x && pk->x y