二进制图像方向 [英] Binary Image Orientation

查看:238
本文介绍了二进制图像方向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到二进制图像的方向(其中方向被定义为最小惯性矩的轴,即面积的最小二次矩)。我使用霍恩博士的书(MIT)的机器人视觉在这里可以找到作为参考。



使用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; //中心是正确的
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 == c0:atan2(b,a-c)/2.0;

return Point3d(cen_x,cen_y,theta);
}

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

但是,当我尝试绘制具有最小惯性矩的轴时, 错误

(pz),100 * sin(pz))),(Point(px,py)+ Point(100 * cos(pz),100 * sin(pz)

以下是输入和输出的一些示例:






(我希望它是垂直的)






(我期望它是水平的)

解决方案

我使用的方向有时回来,并编码如下。它返回我的对象​​的确切方向。 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;

//匹配一个椭圆(并绘制)

if(largest_contour-> total> = 6)//只能做椭圆拟合
// if we have> 6 points
{
CvBox2D box = cvFitEllipse2(largest_contour);
if((box.size.width< imgYellowThresh-> width)&& amp;& amp;(box.size.height< imgYellowThresh-> height))
{

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


I'm trying to find the orientation of a binary image (where orientation is defined to be the axis of least moment of inertia, i.e. least second moment of area). I'm using Dr. Horn's book (MIT) on Robot Vision which can be found here as reference.

Using OpenCV, here is my function, where a, b, and c are the second moments of area as found on page 15 of the pdf above (page 60 of the text):

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 calculates the second moments around the origin (0,0) so I have to use the Parallel Axis Theorem to move the axis to the center of the shape, mr^2.

The center looks right when I call

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

But when I try to draw the axis with lowest moment of inertia, using this function, it looks completely wrong:

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

Here are some examples of input and output:

(I'd expect it to be vertical)

(I'd expect it to be horizontal)

解决方案

I worked with the orientation sometimes back and coded the following. It returns me the exact orientation of the object. largest_contour is the shape that is detected.

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

这篇关于二进制图像方向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆