我有一个图像,我想找到轮廓,但我的图像中的“轮廓”没有角。我是否可以使用一些技巧来帮助找到此图像中线条所暗示的矩形?我想扩展所有线条以形成角落,但我担心与其他轮廓相交的线条以及如何确定我感兴趣的交叉点。我对opencv很新,我对图像处理知之甚少。感谢您提供任何帮助。
答案 0 :(得分:4)
使用Hough transform在二进制图像中拟合线条,并将矩形拟合到正交相交的线条。
答案 1 :(得分:4)
我最终实现了自己的解决方案。它不是很优雅,但它完成了工作。我很想听听有关改进的消息。 HoughLines2并不总能给我找到线段的好结果,而且我不得不在不同情况下对阈值进行大量处理。相反,我选择了FindCountours,其中我采用了两个元素的轮廓,我应该保证1像素宽的线条。找到线后,我遍历它们并追踪它们以找到矩形。
其中points是行端点的* 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;
}
答案 2 :(得分:1)
您也可以尝试将其视为优化问题。如果包括旋转(x,y,宽度,高度,旋转),则矩形被定义为4D状态向量(x,w,宽度,高度)或5D向量。对于您当前的状态,您可以对Hough线的结果进行梯度下降以收敛到最佳状态。其他选项是使用线性最小二乘:http://people.inf.ethz.ch/arbenz/MatlabKurs/node88.html
答案 3 :(得分:0)
使用hough transform,您将能够提取线条。然后,您可以计算这些线的交点以估计矩形的位置。