2013-02-06 56 views
8

我試圖找到二進制圖像的方向(其中方向定義爲最小慣性矩的軸,即最小面積的二次矩)。作爲參考,我正在使用Dr.Horn的書(MIT)作爲機器人視覺which can be found hereBinary Image Orientation

使用OpenCV的,這裏是我的功能,其中a,b,c爲區域的二階矩的PDF 15頁上找到上述(第60頁的文字):

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計算原點周圍的二次矩(0,0),因此我必須使用Parallel Axis Theorem將軸移動到形狀的中心mr^2。

中心期待權當我打電話

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

但是,當我嘗試繪製的慣性最低的時刻軸,使用此功能,它看起來完全錯誤

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); 

以下是一些輸入和輸出示例:

enter image description here enter image description here

(我希望它是垂直)

enter image description here enter image description here

(我希望它是水平)

+0

a,b和c以及θ的值是多少?你能打印出來並說服自己是對的嗎?當你將對象居中時會發生什麼?這有幫助嗎?這些將是兩個調試步驟開始...... – Floris

+1

對於一個起點,你應該像'm20/m00'一樣進行分割,而不是減去。 – mmgp

+0

a,b,c等m.m00部分正在使用平行軸定理將旋轉點從圖像原點移動到對象原點。 – Jason

回答

6

我與定向工作有時背部和編碼的以下。它返回對象的確切方向。 largest_contour是檢測到的形狀。

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

完美工作。只是將a,b和c改爲中央時刻。謝謝! – Jason

+0

那麼,爲什麼不直接使用'盒子'的中心點和角度呢?你所做的所有時刻計算都沒有使用......並且與「盒子」的中心點和角度相同(C++中的RotatedRectangle) – br1