2013-02-06 9 views
8

Próbuję znaleźć orientację obrazu binarnego (gdzie orientacja jest zdefiniowana jako oś najmniejszego momentu bezwładności, tj. Najmniejszy drugi moment obszaru). Używam książki dr Horn'a (MIT) w Robot Vision which can be found here jako odnośniku.Orientacja obrazu binarnego

Używanie OpenCV, tu jest moja funkcja, gdzie a, b, c są drugie momenty obszarze, jak znaleźć na stronie 15 pdf powyżej (strona 60 tekstu):

Point3d findCenterAndOrientation(const Mat& src) 
{ 
    Moments m = cv::moments(src, true); 
    double cen_x = m.m10/m.m00; //Centers are right 
    double cen_y = m.m01/m.m00; 

    double a = m.m20-m.m00*cen_x*cen_x; 
    double b = 2*m.m11-m.m00*(cen_x*cen_x+cen_y*cen_y); 
    double c = m.m02-m.m00*cen_y*cen_y; 

    double theta = a==c?0:atan2(b, a-c)/2.0; 

    return Point3d(cen_x, cen_y, theta); 
} 

OpenCV oblicza sekundy wokół początku (0,0), więc muszę użyć Parallel Axis Theorem, aby przesunąć oś do środka kształtu, mr^2.

Centrum wygląda dobrze, gdy zadzwonię

Point3d p = findCenterAndOrientation(src); 
rectangle(src, Point(p.x-1,p.y-1), Point(p.x+1, p.y+1), Scalar(0.25), 1); 

Ale gdy próbuję narysować oś z najniższego momentu bezwładności, przy użyciu tej funkcji, wygląda zupełnie złym:

line(src, (Point(p.x,p.y)-Point(100*cos(p.z), 100*sin(p.z))), (Point(p.x, p.y)+Point(100*cos(p.z), 100*sin(p.z))), Scalar(0.5), 1); 

Oto kilka przykładów wejścia i wyjścia:

enter image description here enter image description here

(będę oczekiwać, że będzie w pionie)

enter image description here enter image description here

(będę oczekiwać, że będzie pozioma)

+0

Jakie są wartości a, b i c - oraz theta? Czy możesz je wydrukować i przekonać się, że mają rację? Co się dzieje, gdy wyśrodkujesz obiekt? To pomaga? Aby rozpocząć, byłyby to dwa etapy debugowania ... – Floris

+1

Aby zacząć, należy dzielić jak "m20/m00", a nie odejmować. – mmgp

+0

Część m.m00 na a, b, c itd. Używa twierdzenia o osi równoległej, aby przesunąć punkt obrotu od początku obrazu do początku obiektu. – Jason

Odpowiedz

6

Pracowałem z orientacją czasami z powrotem i kodowane następujący. Zwraca mi dokładną orientację obiektu. largest_contour to wykrywany kształt.

CvMoments moments1,cenmoments1; 
      double M00, M01, M10; 

      cvMoments(largest_contour,&moments1); 
      M00 = cvGetSpatialMoment(&moments1,0,0); 
      M10 = cvGetSpatialMoment(&moments1,1,0); 
      M01 = cvGetSpatialMoment(&moments1,0,1); 
      posX_Yellow = (int)(M10/M00); 
      posY_Yellow = (int)(M01/M00); 

      double theta = 0.5 * atan(
        (2 * cvGetCentralMoment(&moments1, 1, 1))/
        (cvGetCentralMoment(&moments1, 2, 0) - cvGetCentralMoment(&moments1, 0, 2))); 
       theta = (theta/PI) * 180; 

       // fit an ellipse (and draw it) 

       if (largest_contour->total >= 6) // can only do an ellipse fit 
               // if we have > 6 points 
       { 
        CvBox2D box = cvFitEllipse2(largest_contour); 
        if ((box.size.width < imgYellowThresh->width) && (box.size.height < imgYellowThresh->height)) 
        { 

         cvEllipseBox(imgYellowThresh, box, CV_RGB(255, 255 ,255), 3, 8, 0); 
        } 
       } 
+0

Działa idealnie. Po prostu zmieniłem a, b, i c na kluczowe momenty. Dzięki! – Jason

+0

Dlaczego więc po prostu nie użyjesz punktu środkowego i kąta z "pudełka"? Wszystkie wykonywane przez ciebie obliczenia nie są używane ... i tak samo jak punkt środkowy i kąt 'pola' (RotatedRectangle w C++) – br1