2013-02-06 52 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