图形学概念:矩、中心矩、质心、patch方向

1、几何矩理论

1.1 矩与数学期望

  • 数学期望

定义(一维离散):设X[a,b],密度为f(x),数学期望为:

E(X)=i=1xiP(xi)



定义(一维连续):设X为连续型随机变量,其概率密度为f(x),则X的数学期望为:

E(X)=+xf(x)dx


注:假定广义积分绝对收敛,即+|x|f(x)dx存在


定义(二维离散):对于离散变量(X,Y)P(xi,yi)PX(xi)=jP(xi,yj)期望为:

E(X)=ixiPX(xi)=jixiP(xi,yj)



E(Y)=jyjPY(yj)=jiyjP(xi,yj)



定义(二维连续):连续变量(X,Y)f(x,y):

fX(x)=+f(x,y)dy



E(X)=+xfX(x)dx=+x(+f(x,y)dy)dx=++xf(x,y)dxdy



E(Y)=+yfY(y)dy=++yf(x,y)dxdy


  • 原点矩

定义1:设X是随机变量,则称νk(X)=E(Xk)Xk原点矩

X是离散型随机变量,则:

νk(X)=ixikp(xi)


X是连续型随机变量,则:

νk(X)=+xkf(x)dx


  • 中心距

定义2:设X是随机变量,则称

μk(X)=E(XE(X))k
为 X的 k中心距


X是离散型随机变量,则:

μk(X)=i(xiE(X))kp(xi)


X是连续型随机变量,则:

μk(X)=+(xE(X))kf(x)dx


  • 原点矩与中心距

当中心距中的E(X)为0时,此时为k阶原点矩,即原点矩是中心距的特殊情况。

一阶原点矩就是数学期望,二阶中心距就是方差,在实际中常用低阶矩,高于四阶矩极少使用。

原点矩与中心距的关系式:

μ2=ν2ν12



μ3=ν33ν2ν1+2ν13



μ4=ν44ν3ν1+6ν2ν123ν14


以上可对μr用组合数拆开得到。

1.2 图像的矩

把图像的像素看做密度函数f(x,y),对该像素点求期望E,即是图像的矩(原点矩)。具体的求解过程参看下面第2节。

一般来说,一阶矩零阶矩可以计算某个形状的重心,二阶矩可以计算形状的方向。

图像的矩主要表征了图像区域的几何特征,又称几何矩,由于具有旋转、平移、尺度等不变的特兴奋,所以又称为不变矩
利用不变矩可以计算出物体的圆形度(物体形状和园的接近程度)、物体的矩形度(物体形状和矩形的接近程度)、物体的水平和垂直对称性、物体的主轴方向、扁度等。

  • 原点矩:

    mpq=x1My1Nxpyqf(x,y)


    • moments of a patch(矩):

      (1)mpq=x=r,y=rrxpyqI(x,y)


    • 角点为中心:

      (1-1)m00=x=r,y=rrx0y0I(x,y)=x=r,y=rrI(x,y)


    • 一阶矩m01:

      (1-2)m01=x=r,y=rrx0y1I(x,y)=x=r,y=rryI(x,y)


    • 一阶矩m10:

      (1-3)m10=x=r,y=rrx1y0I(x,y)=x=r,y=rrxI(x,y)


    • centroid(质心,亦可称为重心):

      (2)C=(m10m00,m01m00)


      计算质心的优势:对噪声不敏感。当有外部噪声干扰时,计算出的质心不会偏离太大。从数学的角度来看,这种方法是计算一个连通域的质心(或一个团块儿blob的质心)。


    • 构造一个向量OC,从角点中心O到质心C

    • orientation of patch(方向):

      (3)θ=atan2(m01,m10)


      建立以角点为圆心的坐标系,如图这里写图片描述
      在图中,P为角点,园内为取点区域,每个方格代表一个像素。
      则质心Q可根据式(2)求得。


    • moments()

    • The function computes moments, up to the 3rd order, of a vector shape or a rasterized shape. The results are returned in the structure Moments defined as:

    • 1

    • 2

    • 3

    • 4

    • 5

    • 6

    • 7

    • 8

    • 9

    • 10

    • 11

    • 12

    • 13

    • 14

    • 15

    • 16

    • opencv2.4.13

    • 1

    • 2

    • 3

    • 4

    • 5

    • 6

    • 7

    • 8

    • 9

    • 10

    • 11

    • 12

    • 13

    • 14

    • 15

    • 16

    • 17

    • 18

    • 19

    • 20

    • 21

    • 22

    • 23

    • 24

    • 25

    • 26

    • 27

    • 28

    • 29

    • 30

    • 31

    • 32

    • 33

    • 34

    • 35

    • 36

    • 37

    • 38

    • 39

    • 40

    • 41

    • 42

    • 43

    • 44

    • 45

    • 46

    • 47

    • 48

    • 49

    • 50

    • 51

    • 52

    • 53

    • 54

    • 55

    • 56

    • 57

    • 58

    • 59

    • 60

    • 61

    • 62

    • 63

    • 64

    • 65

    • 66

    • 67

    • 68

    • 69

    • 70

    • 71

    • 72

    • 73

    • 74

    • 75

    • 76

    • 77

    • 78

    • 79

    • 80

    • 81

    • 82

    • 83

    • 84

    • 85

    • 86

    • 87

    • 88

    • 89

    • 90

    • 91

    • 92

    • 93

    • 94

    • 95

    • 96

    • 97

    • 98

    • 99

    • 100

    • 101

    • 102

    • 103

    • 1

    • 2

    • 3

    • 4

    • 5

    • 6

    • 7

    • 8

    • 9

    • 10

    • 11

    • 12

    • 13

    • 14

    • 15

    • 16

    • 17

    • 18

    • 19

    • 20

    • 21

    • 22

    • 23

    • 24

    • 25

    • 26

    • 27

    • 28

    • 29

    • 30

    • 31

    • 32

    • 33

    • 34

    • 35

    • 36

    • 37

    • 38

    • 39

    • 40

    • 41

    • 42

    • 43

    • 44

    • 45

    • 46

    • 47

    • 48

    • 49

    • 50

    • 51

    • 52

    • 53

    • 54

    • 55

    • 56

    • 57

    • 58

    • 59

    • 60

    • 61


    • 参考:

    • 中心距:

      μpq=x1My1N(xx0)p(yy0)qf(x,y)


    • 归一化中心距:

      ηpq=μpqμ00r


      其中r=p+q+22,p+q=2,3,...


    • 一阶矩:
      见下面第2节.

    • 二阶矩:


    • M20=xyx2·I(x,y)



      M02=xyy2·I(x,y)



      M11=xyx·y·I(x,y)


      M20M02分别表示图像围绕通过重心的垂直和水平轴线的惯性矩。
      M30M03可以度量图像对于垂直和水平轴线的对称性等。

      物体形状的方向:

      θ=arctan(b,(ac))2=arctan(b/(ac))2,θ[9090]


      其中:


      根据一阶矩的质心C=(M10M00,M01M00)


      a=M20M00C02



      b=2(M11M00C0C1)



      c=M02M00C12


      2、质心原理

      在图像处理中,一阶矩与形状有关,二阶矩显示曲线围绕直线平均值到扩展程度,三阶矩是关于平均值到对称性到测量.由二阶矩和三阶矩可以导出一组共7个不变矩.而不变矩是图像到统计特性,满足平移,伸缩,旋转均不变到不变性.


      3、中心距函数moments()

      Calculates all of the moments up to the third order of a polygon or rasterized shape.

      C++: Moments moments(InputArray array, bool binaryImage=false )

      Python: cv2.moments(array[, binaryImage]) → retval

      C: void cvMoments(const CvArr* arr, CvMoments* moments, int binary=0 )

      Python: cv.Moments(arr, binary=0) → moments

      Parameters:
      array – Raster image (single-channel, 8-bit or floating-point 2D array) or an array ( 1 \times N or N \times 1 ) of 2D points (Point or Point2f ).
      binaryImage – If it is true, all non-zero image pixels are treated as 1’s. The parameter is used for images only.
      moments – Output moments.

      class Moments
      {public:    Moments();
          Moments(double m00, double m10, double m01, double m20, double m11,            double m02, double m30, double m21, double m12, double m03 );
          Moments( const CvMoments& moments );    operator CvMoments() const;    // spatial moments
          double  m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;    // central moments
          double  mu20, mu11, mu02, mu30, mu21, mu12, mu03;    // central normalized moments
          double  nu20, nu11, nu02, nu30, nu21, nu12, nu03;
      }

      4、中心矩示例代码

      4.1 C++版代码

      #include <QCoreApplication>#include <opencv2/opencv.hpp>//  Qt Creator 4.2.0(Based on Qt 5.7.1)//  OpenCV 2.4.13using namespace cv;using namespace std;#define name1 "原图"#define name2 "效果图"cv::Mat img, gray;int nThresh = 100;int nMaxThresh = 255;
      cv::RNG rng(12345);  //产生一个随机数cv::Mat cannyImg;std::vector<std::vector<cv::Point>> contours;std::vector<cv::Vec4i> hierarchy;//void on_ThreshChange( int, void* ){//    //canny边缘检测//    cv::Canny( gray, cannyImg, nThresh, nThresh*2, 3 );//    //找轮廓//    cv::findContours( cannyImg, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point( 0, 0 ) );//    //计算矩//    std::vector<cv::Moments> mu( contours.size() );//    for(unsigned int i = 0; i < contours.size(); i++){//        mu[i] = cv::moments( contours[i], false);//    }//    //计算中心矩//    std::vector<cv::Point2f> mc( contours.size() );//    for( unsigned int i = 0; i < contours.size(); i++ ){//        mc[i] = cv::Point2f( static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));//    }//    //画轮廓//    cv::Mat drawing = cv::Mat::zeros( cannyImg.size(), CV_8UC3);//    for( unsigned int i = 0; i < contours.size(); i++ ){//        cv::Scalar color = cv::Scalar( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );//        cv::drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, cv::Point() );//        cv::circle( drawing, mc[i], 4, color, -1, 8, 0 );//    }//    cv::namedWindow( name2, cv::WINDOW_NORMAL);//    cv::imshow( name2, drawing );//    std::cout << "输出内容: 面积和轮廓长度 \n" << std::endl;//    for(unsigned int i = 0; i < contours.size(); i++ ){//        std::cout << ">通过m00计算出轮廓[" << i << "]的面积:(M_00) =" << mu[i].m00 << "\n OpenCV 函数计算出的面积 = " << cv::contourArea(contours[i]) << "长度:" << cv::arcLength( contours[i], true) <<  "\n\n" << std::endl;//        cv::Scalar color = cv::Scalar( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );//        cv::drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, cv::Point() );//        cv::circle( drawing, mc[i], 4, color, -1, 8, 0 );//     }//}int main(){
          img = cv::imread( "/home/jason/jason2/photo/1.jpg" );
          cv::cvtColor( img, gray, cv::COLOR_BGR2GRAY );
          cv::blur( gray, gray, cv::Size(3, 3) );
      
          cv::namedWindow( name1, cv::WINDOW_NORMAL );
          cv::imshow( name1, img );//    cv::createTrackbar( "阈值", name1, &nThresh, nMaxThresh, on_ThreshChange );//    on_ThreshChange( 0, 0 );
      
          //canny边缘检测
          cv::Canny( gray, cannyImg, nThresh, nThresh*2, 3 );    //找轮廓
          cv::findContours( cannyImg, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point( 0, 0 ) );    //计算矩
          std::vector<cv::Moments> mu( contours.size() );    for(unsigned int i = 0; i < contours.size(); i++){
              mu[i] = cv::moments( contours[i], false);
          }    //计算中心矩
          std::vector<cv::Point2f> mc( contours.size() );    for( unsigned int i = 0; i < contours.size(); i++ ){
              mc[i] = cv::Point2f( static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
          }    //画轮廓
          cv::Mat drawing = cv::Mat::zeros( cannyImg.size(), CV_8UC3);    for( unsigned int i = 0; i < contours.size(); i++ ){
              cv::Scalar color = cv::Scalar( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );
              cv::drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, cv::Point() );
              cv::circle( drawing, mc[i], 4, color, -1, 8, 0 );
          }
      
          cv::namedWindow( name2, cv::WINDOW_NORMAL);
          cv::imshow( name2, drawing );    std::cout << "输出内容: 面积和轮廓长度 \n" << std::endl;    for(unsigned int i = 0; i < contours.size(); i++ ){        std::cout << ">通过m00计算出轮廓[" << i << "]的面积:(M_00) =" << mu[i].m00 << "\n OpenCV 函数计算出的面积 = " << cv::contourArea(contours[i]) << "长度:" << cv::arcLength( contours[i], true) <<  "\n\n" << std::endl;
              cv::Scalar color = cv::Scalar( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );
              cv::drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, cv::Point() );
              cv::circle( drawing, mc[i], 4, color, -1, 8, 0 );
           }
          cv::waitKey(0);    return 0;
      }

      原图:
      这里写图片描述

      效果图:
      这里写图片描述

      部分打印结果:
      这里写图片描述


      4.2 Python版代码

      # -*- coding: utf-8 -*-"""
      Created on Sun Mar 26 18:36:19 2017
      
      @author: lql0716
      """import cv2import numpy as np
      
      nThresh = 100nMaxThresh = 255img = cv2.imread('D:/photo/04.jpg')
      gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
      gray = cv2.blur(gray, (3,3))
      cv2.namedWindow('img', cv2.WINDOW_NORMAL)
      cv2.imshow('img', img)
      
      cannyImg = cv2.Canny(gray, nThresh, nThresh*2, 3)
      contours, hierarchy = cv2.findContours(cannyImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
      
      mu = []
      mc = []
      retval = np.array([])for i in range(0, np.array(contours).shape[0]):
          retval = cv2.moments(contours[i], False)
          mu.append(retval)
      mu = np.array(mu)#print mu[0]['m10']thetas = []for i in range(0, np.array(contours).shape[0]):    if mu[i]['m00'] == 0.0:
              a=0
              b=0
          else:
              a = mu[i]['m10'] / mu[i]['m00']  #质心x坐标
              b = mu[i]['m01'] / mu[i]['m00']  #质心y坐标
      
              #根据二阶矩计算物体形状的方向
              r1 = mu[i]['m20'] / mu[i]['m00'] - a*a
              r2 = 2.0*(mu[i]['m11'] / mu[i]['m00'] - a*b)
              r3 = mu[i]['m02'] / mu[i]['m00'] - b*b#        print r1-r3
              if r1-r3==0:
                  theta = np.pi / 2
              else:
                  theta = np.arctan(r2/(r1-r3)) / 2
              thetas.append(theta)
          mc.append([a,b])
      mc = np.array(mc)
      drawing = np.zeros(img.shape, dtype = np.uint8)for i in range(0, mc.shape[0]):
          c1 = np.random.randint(0, 256)
          c2 = np.random.randint(0, 256)
          c3 = np.random.randint(0, 256)
          cv2.drawContours(drawing, contours, i, (c1, c2, c3), 2, 8)
          cv2.circle(drawing, (int(round(mc[i][0])), int(round(mc[i][1]))), 4, (c1, c2, c3), -1, 8, 0)
      cv2.namedWindow('img2', cv2.WINDOW_NORMAL)
      cv2.imshow('img2', drawing)   
      cv2.waitKey(0)

      原图:
      这里写图片描述

      效果图:
      这里写图片描述

      5、Hu矩HuMoments()

      原点矩:


      mpq=x1My1Nxpyqf(x,y)


      中心距:


      μpq=x1My1N(xx0)p(yy0)qf(x,y)


      归一化中心距:


      ηpq=μpqμ00r


      其中 r=p+q+22,p+q=2,3,...


      当图像变化时,mpq也变化,而μpq具有平移不变形,但对旋转依然敏感。如果用归一化中心距,则可以保持平移不变性、伸缩不变性。

      Hu矩利用二阶、三阶中心距构造了7个不变矩,它们在连续图像条件下可保持平移、旋转、伸缩不变,公式如下:
      M1=η20+η02
      M2=(η20η02)2+4η112
      M3=(η303η12)2+(3η21η03)2
      M4=(η30+η12)2+(η21+η03)2
      M5=(η303η12)(η30+η12)((η30+η12)23(η21+η03)2)+(3η21η03)(η21+η03)(3(η30+η12)2(η21+η03)2)
      M6=(η20η02)((η30+η12)2(η21+η03)2)+4η11(η30+η12)(η21+η03)
      M7=(3η21η03)(η30+η12)((η30+η12)23(η21+η03)2)(η303η12)(η21+η03)(3(η30+η12)2(η21+η03)2)

      以下公式为官方文档的公式:
      此处输入图片的描述

      在对图片识别过程中,只有M1M2不变性保持的比较好,其他几个不变矩带来的误差比较大,有学者认为只有基于二阶矩的不变矩对二维物体的描述才真正具有旋转,缩放,平移不变性(M1M2均为二阶矩构成).

      Hu矩的优势:速度快
      Hu矩的劣势:识别率低

      Hu矩一般用来识别图像中大的物体,对物体的形状描述得比较好,图像的纹理特征不能太复杂,如识别水果形状或车牌字符的效果较好.



      1、图像的几何矩浅析
      2、opencv官方文档-moments()
      3、形状描述与识别
      4、第三章 二值图像分析

本文转载自:https://blog.csdn.net/lql0716/article/details/68267829


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864