【发布时间】:2011-04-26 17:54:42
【问题描述】:
我有一张图像,我想在其中找到轮廓,但图像中的“轮廓”没有角。我可以使用一些技巧来帮助找到此图像中线条所隐含的矩形吗?我考虑过延伸所有线条以形成角落,但我担心线条与其他轮廓相交以及如何确定我感兴趣的交叉点。我对 opencv 很陌生,对图像处理知之甚少。感谢您提供的任何帮助。
【问题讨论】:
标签: opencv
我有一张图像,我想在其中找到轮廓,但图像中的“轮廓”没有角。我可以使用一些技巧来帮助找到此图像中线条所隐含的矩形吗?我考虑过延伸所有线条以形成角落,但我担心线条与其他轮廓相交以及如何确定我感兴趣的交叉点。我对 opencv 很陌生,对图像处理知之甚少。感谢您提供的任何帮助。
【问题讨论】:
标签: opencv
使用Hough transform 拟合二进制图像中的线条,并将矩形拟合到正交相交的线条。
【讨论】:
我最终实现了自己的解决方案。它不是很优雅,但它完成了工作。我有兴趣听到有关改进的信息。 HoughLines2 在寻找线段方面并不总是给我很好的结果,而且我不得不在不同的场景中大量使用阈值。相反,我选择了 FindCountours,我用两个元素获取轮廓,我应该保证 1 像素宽的线条。找到线条后,我遍历它们并追踪它们以找到矩形。
其中点是线端点的*CvSeq
while(points->total>0){
if(p1.x==-1&&p1.y==-1){
cvSeqPopFront(points,&p1);
cvSeqPopFront(points,&p2);
}
if((pos=findClosestPoint(&p1,&p2, points,maxDist))>=0){
p3 = (CvPoint*)cvGetSeqElem( points,pos );
pos2 = (pos%2==0)?pos+1:pos-1; //lines are in pairs of points
p4 = (CvPoint*)cvGetSeqElem( points,pos2 );
if(isVertical(&p1,&p2) && isHorizontal(p3,p4)){
printf("found Corner %d %d\n",p2.x,p3->y);
} else if(isHorizontal(&p1,&p2) && isVertical(p3,p4) ){
printf("found Corner %d %d\n",p3->x,p2.y);
}
memcpy(&p1,p3,sizeof(CvPoint));
memcpy(&p2,p4,sizeof(CvPoint));
cvSeqRemove(points, (pos>pos2)?pos:pos2);
cvSeqRemove(points, (pos>pos2)?pos2:pos);
} else {
p1.x=-1;
p1.y=-1;
}
}
int findClosestPoint (CvPoint *p1, CvPoint *p2, CvSeq *points, int maxDist) {
int ret = -1,i;
float dist, minDist = maxDist;
CvPoint* test;
int (*dirTest)(CvPoint *,CvPoint *);
if(isVertical(p1,p2)){ //vertical line
if(p2->y > p1->y) {//going down
dirTest = isBelow;
} else { // going up
dirTest = isAbove;
}
} else if (isHorizontal(p1,p2)){ //horizontal line
if(p2->x > p1->x) {//going right
dirTest = isRight;
} else { //going left
dirTest = isLeft;
}
}
for( i = 0; i < points->total; i++ )
{
test = (CvPoint*)cvGetSeqElem( points, i );
if(dirTest(p2,test)){ //only test points in the region we care about
dist = sqrt(pow(test->x - p2->x,2)+pow(test->y - p2->y,2));
if(dist<minDist){
minDist = dist;
ret = i;
}
}
}
return ret;
}
int isVertical(CvPoint *p1, CvPoint *p2){
return p1->x == p2->x;
}
int isHorizontal(CvPoint *p1, CvPoint *p2){
return p1->y == p2->y;
}
int isRight(CvPoint *pt1, CvPoint *pt2){
return pt2->x > pt1->x;
}
int isLeft(CvPoint *pt1, CvPoint *pt2){
return pt2->x < pt1->x;
}
int isBelow(CvPoint *pt1, CvPoint *pt2){
return pt2->y > pt1->y;
}
int isAbove(CvPoint *pt1, CvPoint *pt2){
return pt2->y < pt1->y;
}
【讨论】:
您也可以尝试将其视为优化问题。矩形定义为 4D 状态向量 (x,w,width,height) 或 5D 向量,如果包含旋转 (x,y,width,height,rotation)。对于您当前的状态,您可以对霍夫线的结果进行梯度下降以收敛到最佳状态。其他选项是使用线性最小二乘:http://people.inf.ethz.ch/arbenz/MatlabKurs/node88.html
【讨论】:
使用hough transform,您将能够提取行。然后你可以计算这些线的交点来估计矩形的位置。
【讨论】: