Найти прямоугольники без углов, используя opencv - PullRequest
6 голосов
/ 18 октября 2010

У меня есть изображение, где я хочу найти контуры, но у «контуров» в моем изображении нет углов.Есть ли уловки, которые я могу использовать, чтобы помочь найти прямоугольники, которые подразумеваются линиями на этом изображении?Я думал о расширении всех линий, чтобы сформировать углы, но я беспокоюсь о линиях, пересекающихся с другими контурами, и о том, как определить, какие пересечения меня интересуют. Я очень плохо знаком с opencv и не очень разбираюсь в обработке изображений.Спасибо за любую помощь, которую вы можете оказать.alt text

Ответы [ 4 ]

4 голосов
/ 20 октября 2010

В итоге я реализовал собственное решение. Это не очень изящно, но это делает работу. Мне было бы интересно услышать об улучшениях. 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;
}
4 голосов
/ 18 октября 2010

Подгоните линии в вашем двоичном изображении с помощью преобразования Hough и подгоните прямоугольники к ортогонально пересекающимся линиям.

1 голос
/ 30 ноября 2014

Вы также можете попытаться представить это как проблему оптимизации.Прямоугольник определяется как вектор состояния 4D (x, w, ширина, высота) или вектор 5D, если вы включите вращение (x, y, ширина, высота, вращение).Для вашего текущего состояния вы можете сделать градиентный спуск к результату линий Хафа, чтобы приблизиться к оптимальному состоянию.Другой вариант - использование линейных наименьших квадратов: http://people.inf.ethz.ch/arbenz/MatlabKurs/node88.html

0 голосов
/ 19 октября 2010

Используя преобразование hough , вы сможете извлекать строки.Затем вы можете рассчитать пересечения этих линий, чтобы оценить положение прямоугольников.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...