Opencv 二值图像定向

Opencv 二值图像定向,opencv,computer-vision,Opencv,Computer Vision,我试图找到一个二值图像的方向(其中方向被定义为最小惯性矩的轴,即最小面积秒矩)。我正在使用霍恩博士关于机器人视觉的书(麻省理工学院)作为参考 使用OpenCV,这里是我的函数,其中a、b和c是面积的二阶矩,见上述pdf第15页(文本第60页): OpenCV计算围绕原点(0,0)的二阶矩,因此我必须使用将轴移动到形状的中心,mr^2 我打电话的时候中心看起来很好 Point3d p = findCenterAndOrientation(src); rectangle(src, Point(p.x

我试图找到一个二值图像的方向(其中方向被定义为最小惯性矩的轴,即最小面积秒矩)。我正在使用霍恩博士关于机器人视觉的书(麻省理工学院)作为参考

使用OpenCV,这里是我的函数,其中a、b和c是面积的二阶矩,见上述pdf第15页(文本第60页):

OpenCV计算围绕原点(0,0)的二阶矩,因此我必须使用将轴移动到形状的中心,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); 
以下是一些输入和输出示例:

(我希望它是垂直的)


(我希望它是水平的)

我有时使用方向返回,并对以下内容进行编码。它返回对象的确切方向。最大轮廓是检测到的形状

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 );
                    }
                }
cvmoments1,centmoments1;
双M00、M01、M10;
Cv力矩(最大_轮廓和力矩1);
M00=cvGetSpatialMoment(&moments1,0,0);
M10=cvGetSpatialMoment(&moments1,1,0);
M01=cvGetSpatialMoment(&moments1,0,1);
posX_黄色=(内部)(M10/M00);
黄色=(内部)(M01/M00);
双θ=0.5*atan(
(2*cvGetCentralMoment(和moments1、1、1))/
(CVGetCentralMoments(&moments1,2,0)-CVGetCentralMoments(&moments1,0,2));
θ=(θ/PI)*180;
//拟合一个椭圆(并绘制它)
如果(最大轮廓->总计>=6)//只能进行椭圆拟合
//如果我们的分数超过6分
{
CvBox2D box=cvFitEllipse2(最大轮廓);
如果((box.size.widthwidth)和&(box.size.heightheight))
{
cvEllipseBox(imgYellowThresh,box,CV_RGB(255,255,255),3,8,0);
}
}

a、b、c和θ的值是多少?你能把这些打印出来,让自己相信它们是对的吗?将对象居中时会发生什么情况?这有用吗?这将是开始调试的两个步骤…对于一个起点,您应该像
m20/m00
那样除法,而不是减法。a,b上的m.m00部分,c等使用平行轴定理将旋转点从图像原点移动到对象原点。@Jason只计算/中心/力矩时考虑了质心,第二力矩
m20
等不是/中心/力矩,因此它们不是“围绕原点(0,0)”计算的(但是
mu20
和etc是)。这里没有应用平行轴定理。我认为这可以使用“使用opencv力矩的deskew”解决,而且效果非常好。只是将a、b和c更改为中心力矩。谢谢!那么为什么不使用
框中的中心点和角度呢?您所做的所有力矩计算都没有使用…与
框的中心点和角度(C++中的RotatedRectangle)
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 );
                    }
                }