zoukankan      html  css  js  c++  java
  • 二值图像的几何性质

        二值图像 b(x,y) = 1 表示前景部分,b(x,y) = 0 表示背景部分。其基本几何特性包括:‘

        1 面积

         对整个图像区域进行积分,使用零阶矩表示为 

        2 位置

        将图像区域看作一种均匀物质构成得平面,物体得质心即为区域中心;使用一阶矩表示如下:

         ,进一步改写得:

        

        3 朝向

        假设物体沿某一方向比较长,其正交方向比较短,该方向定义为物体朝向。使用最小转动惯量来定义物体长轴,即寻找一条直线,使得物体上所有点到直线上距离平方和最小,定义如下:

        , r 表示物体上点到直线的最小距离。

        通过最小化 E,可以计算出物体朝向直线,具体如下:

        1)假设二值图像朝向直线已知,使用  定义为 ,如下图:

             

          如上图所示,由于 ,可以建立等式 

         ,化简得

        

        2)对直线 L 上任意点 ,以点  作为参考点,建立参数方程如下:

        ,s 表示点  距离参考点  的距离。

        3)由于 ,(x,y) 表示图像上的点, 表示直线上的点,将参数方程带入该等式,使得两个变量 简化为一个变量 s,如下:

       

       

        对 s 求导,当导数为零时表示(x,y)到直线 L 上距离最近  , 

        计算得 ,将 s 带入 

        

        ,最终推导出转动惯量方程为

        ,其中, 为待求解直线参数。

        4)令 

        将无关变量提出积分符号前

        同时除以 得 

        由于  为图像中心,则最小转动惯量对应得轴过图像中心。

        5)通过 4)结论,直线 L 的确定可转换为对选择角度的求解,具体如下:

        令 ,将图像上点绝对坐标转换为相对于图像中心的相对坐标,带入直线 L 方程得:

        ,重新改写 

        当前 E 仅包含未知量 ,再次改写 ,其中 

        

        

        

        使用倍角公式 

        

       通过以上分析,二值图像朝向直线为经过中心点,且满足  的 直线,其中,a, b, c 为图像二阶矩。

       4 形状

        在分析二值图像朝向时,,该方程是关于  的二次方程,

        其系数 a, b, c 为可构成一个 2*2 矩阵,通过分析该矩阵的特征值与特征向量可以估计出二值图像的形状,具体如下:

        ,通过分析特征值与特征向量,可的如下结论:

        1)较大特征值对应的特征向量方向即为二值图像朝向;

        2)两个特征值相差越小,二值图像越接近圆形。

       5 示例

         以下给出代码,使用二阶矩计算二值图像朝向及形状,使用直线拟合计算二值图像朝向。可以发现,两种求朝向方案都可得到基本一致的结果。

     1 cv::Mat img = cv::imread(str, IMREAD_GRAYSCALE);
     2 cv::Mat img_show;
     3 img.copyTo(img_show);
     4 
     5 // 提取二值图像轮廓
     6 std::vector<std::vector<cv::Point>> contours;
     7 cv::findContours(img, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
     8 if (contours.size() <= 0)
     9     return;
    10 
    11 // 只考虑每个图像上仅有一个二值图像
    12 cv::Moments moms = cv::moments(cv::Mat(contours[0]));
    13 double cx = moms.m10 / moms.m00;
    14 double cy = moms.m01 / moms.m00;
    15 double angle = atan2(moms.mu11 * 2., moms.mu20 - moms.mu02);
    16 double tan = tanf(angle * .5);
    17 double dx[2] = { -300., 300. };
    18 double dy[2] = { dx[0] * tan, dx[1] * tan };
    19 
    20 cv::Point pt1(cx + dx[0], cy + dy[0]);
    21 cv::Point pt2(cx + dx[1], cy + dy[1]);
    22 cv::circle(img_show, cv::Point(cx, cy), 10, cv::Scalar(125), 3);
    23 cv::line(img_show, pt1, pt2, cv::Scalar(125), 3);
    24 cv::imwrite("rst1.bmp", img_show);
    25 
    26 // 计算二值图像圆形度
    27 // 特征值比值(最大/最小)越接近1,圆形度越好
    28 cv::Mat sym = cv::Mat::zeros(2, 2, CV_32FC1);
    29 float *datasym = sym.ptr<float>(0);
    30 datasym[0] = moms.mu20;
    31 datasym[1] = moms.mu11;
    32 datasym = sym.ptr<float>(1);
    33 datasym[0] = moms.mu11;
    34 datasym[1] = moms.mu02;
    35 
    36 cv::Mat eg;
    37 cv::eigen(sym, eg);
    38 float e1 = eg.ptr<float>(0)[0];
    39 float e2 = eg.ptr<float>(1)[0];
    40 float circular = e1 / e2;
    41 
    42 // 直线拟合
    43 cv::Vec4f line_param;
    44 cv::fitLine(contours[0], line_param, CV_DIST_L2, 0, .001, .001);
    45 
    46 cv::Point pt0;
    47 pt0.x = line_param[2];
    48 pt0.y = line_param[3];
    49 
    50 double k = line_param[1] / line_param[0];
    51 pt1.x = 0;
    52 pt1.y = k * (0 - pt0.x) + pt0.y;
    53 pt2.x = 480;
    54 pt2.y = k * (480 - pt0.x) + pt0.y;
    55 
    56 cv::line(img_show, pt1, pt2, cv::Scalar(50), 3);
    57 cv::imwrite("rst2.bmp", img_show);

           

        参考资料 Robot Vision  Berthold Klaus Paul Horn

  • 相关阅读:
    利用BootStrap Table插件实现自己的弹出框分页。
    spring+redis的集成,使用spring-data-redis来集成
    Postgresql/Greenplum中将数字转换为字符串TO_CHAR函数前面会多出一个空格
    将根据时间戳增量数据方案修改为根据批次号增量数据方案
    Postgresql查询出换行符和回车符:
    增量数据,如果下次增量数据存在重复数据,如何解决。
    creating server tcp listening socket 127.0.0.1:6379: bind No error
    echarts的地图点击事件
    Postman 安装及使用入门教程(我主要使用接口测试)
    HTML5 canvas 捕鱼达人游戏
  • 原文地址:https://www.cnblogs.com/luofeiju/p/12992713.html
Copyright © 2011-2022 走看看