使用opencv查找没有角落的矩形

时间:2010-10-18 01:31:58

标签: opencv

我有一个图像,我想找到轮廓,但我的图像中的“轮廓”没有角。我是否可以使用一些技巧来帮助找到此图像中线条所暗示的矩形?我想扩展所有线条以形成角落,但我担心与其他轮廓相交的线条以及如何确定我感兴趣的交叉点。我对opencv很新,我对图像处理知之甚少。感谢您提供任何帮助。 alt text

4 个答案:

答案 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,您将能够提取线条。然后,您可以计算这些线的交点以估计矩形的位置。