二值图像方向

Posted

技术标签:

【中文标题】二值图像方向【英文标题】:Binary Image Orientation 【发布时间】:2013-02-06 02:42:08 【问题描述】:

我正在尝试查找二值图像的方向(其中方向定义为最小惯性矩的轴,即最小第二面积矩)。我正在使用霍恩博士 (MIT) 关于机器人视觉的书 which can be found here 作为参考。

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

下面是一些输入和输出的例子:

(我希望它是垂直的)

(我希望它是水平的)

【问题讨论】:

a、b 和 c - 和 theta 的值是多少?你能把这些打印出来并说服自己他们是对的吗?将对象居中时会发生什么?这有帮助吗?这将是开始的两个调试步骤...... 首先,您应该像m20/m00 一样进行除法,而不是减法。 a,b,c等上的m.m00部分是利用平行轴定理将旋转点从图像原点移动到物体原点。 @Jason 仅考虑质心计算 /central/ 矩,第二个矩 m20 等不是 /central/ 矩,因此它们不是围绕原点计算的(0 , 0)" (但mu20 等是)。这里没有平行轴定理。 我认为这可以使用 'deskew using opencv moment' 作为felix.abecassis.me/2011/09/opencv-detect-skew-angle 和felix.abecassis.me/2011/10/opencv-rotation-deskewing 来解决 【参考方案1】:

我有时会返回方向并编写以下代码。它返回我对象的确切方向。最大轮廓是检测到的形状。

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

【讨论】:

完美运行。只是将 a、b 和 c 更改为中心时刻。谢谢! 那么为什么不直接使用box 的中心点和角度呢?不使用您所做的所有矩计算...与box 的中心点和角度相同(C++ 中的RotatedRectangle)

以上是关于二值图像方向的主要内容,如果未能解决你的问题,请参考以下文章

求二值图像的最小外接矩形

二值化处理与边缘检测

在matlab中如何将灰度图像转化成二值图像??如何再转化回去?

如何用C语言实现对图像的二值化?

在matlab中如何将灰度图像转化成二值图像??如何再转化回去?

新手求助,二值化图像怎么去除面积较小的连通域