在opencv中,对于跟踪的目标,通常用矩形进行圈定,但是Opencv的cvFindContours却不会那么精确,通常会将一个目标分成若干个相邻或相交或包含关系的矩形,此时需要判断这些矩的关系,以便进行融合,矩形之间的关系通常又很复杂,通常会有如下关系
在网上还确实不好找,有的是基于两条线是否相交,然后进行两两相交16次判断,但很多算法有bug,最典型是两条X一样的直线不相交会判断成相交,另外呢,由于矩形是平的或是垂直的,没必要复杂的数学运算。
做了两个函数,一个是判断线相交,一个是判断矩形相交,代码不用细看,直接用就行了
1、直线是否相交
BOOL IsLineSegmentCross(POINT pt1, POINT pt2, POINT pt3, POINT pt4,int iLinesRelation)
{
int iL1,iL2,iL3,iL4,iMax;
if(iLinesRelation==0) //平行关系
{
if(pt1.y==pt2.y)//横线
{
if(pt1.y!=pt3.y)
return FALSE;
else //两条线Y值相同
{
iL1=abs(pt1.x-pt2.x);
iL2=abs(pt3.x-pt4.x);
iL3=abs(pt3.x-pt2.x);
iL4=abs(pt4.x-pt1.x);
if(iL3>iL4)
iMax=iL3;
else
iMax=iL4;
if(iL1+iL2
return FALSE;
else
return TRUE;
}
}
else //坚线
{
if(pt1.x!=pt3.x)
return FALSE;
else
{
iL1=abs(pt1.y-pt2.y);
iL2=abs(pt3.y-pt4.y);
iL3=abs(pt2.y-pt3.y);
iL4=abs(pt1.y-pt4.y);
if(iL3>iL4)
iMax=iL3;
else
iMax=iL4;
if(iL1+iL2
return FALSE;
else
return TRUE;
}
}
}
else //垂直关系
{
if(pt1.y==pt2.y)//横线
{
if(pt3.xpt2.x)
return FALSE;
else
{
if(pt1.y>=pt3.y&&pt1.y<=pt4.y)
return TRUE;
else
return FALSE;
}
}
else //坚线
{
if(pt1.xpt4.x)
return FALSE;
else
{
if(pt3.y>=pt1.y&&pt3.y<=pt2.y)
return TRUE;
else
return FALSE;
}
}
}
return TRUE;
}
2、矩形是否相交
BOOL CNetXPlayerDlg::RectIsCross(RECT _Rect1,RECT _Rect2)
{
POINT pt1,pt2,pt3,pt4;
//
pt1.x=_Rect1.left;
pt1.y=_Rect1.top;
pt2.x=_Rect1.right;
pt2.y=_Rect1.top;
pt3.x=_Rect2.left;
pt3.y=_Rect2.top;
pt4.x=_Rect2.right;
pt4.y=_Rect2.top;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,0))
return TRUE;
pt3.x=_Rect2.right;
pt3.y=_Rect2.top;
pt4.x=_Rect2.right;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,1))
return TRUE;
pt3.x=_Rect2.left;
pt3.y=_Rect2.bottom;
pt4.x=_Rect2.right;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,0))
return TRUE;
pt3.x=_Rect2.left;
pt3.y=_Rect2.top;
pt4.x=_Rect2.left;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,1))
return TRUE;
//
pt1.x=_Rect1.right;
pt1.y=_Rect1.top;
pt2.x=_Rect1.right;
pt2.y=_Rect1.bottom;
pt3.x=_Rect2.left;
pt3.y=_Rect2.top;
pt4.x=_Rect2.right;
pt4.y=_Rect2.top;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,1))
return TRUE;
pt3.x=_Rect2.right;
pt3.y=_Rect2.top;
pt4.x=_Rect2.right;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,0))
return TRUE;
pt3.x=_Rect2.left;
pt3.y=_Rect2.bottom;
pt4.x=_Rect2.right;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,1))
return TRUE;
pt3.x=_Rect2.left;
pt3.y=_Rect2.top;
pt4.x=_Rect2.left;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,0))
return TRUE;
//
pt1.x=_Rect1.left;
pt1.y=_Rect1.bottom;
pt2.x=_Rect1.right;
pt2.y=_Rect1.bottom;
pt3.x=_Rect2.left;
pt3.y=_Rect2.top;
pt4.x=_Rect2.right;
pt4.y=_Rect2.top;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,0))
return TRUE;
pt3.x=_Rect2.right;
pt3.y=_Rect2.top;
pt4.x=_Rect2.right;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,1))
return TRUE;
pt3.x=_Rect2.left;
pt3.y=_Rect2.bottom;
pt4.x=_Rect2.right;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,0))
return TRUE;
pt3.x=_Rect2.left;
pt3.y=_Rect2.top;
pt4.x=_Rect2.left;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,1))
return TRUE;
//
pt1.x=_Rect1.left;
pt1.y=_Rect1.top;
pt2.x=_Rect1.left;
pt2.y=_Rect1.bottom;
pt3.x=_Rect2.left;
pt3.y=_Rect2.top;
pt4.x=_Rect2.right;
pt4.y=_Rect2.top;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,1))
return TRUE;
pt3.x=_Rect2.right;
pt3.y=_Rect2.top;
pt4.x=_Rect2.right;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,0))
return TRUE;
pt3.x=_Rect2.left;
pt3.y=_Rect2.bottom;
pt4.x=_Rect2.right;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,1))
return TRUE;
pt3.x=_Rect2.left;
pt3.y=_Rect2.top;
pt4.x=_Rect2.left;
pt4.y=_Rect2.bottom;
if(IsLineSegmentCross(pt1,pt2,pt3,pt4,0))
return TRUE;
return FALSE;
}
直接使用第二个函数就行了,代码略有点....,但绝对没有BUG,性能肯定是最棒的
原文地址:http://blog.sina.com.cn/s/blog_5375c7f90102vjes.html