zoukankan      html  css  js  c++  java
  • 图像的矩 图像的轮廓面积和长度

    1. 矩的概念

    图像识别的一个核心问题是图像的特征提取,简单描述即为用一组简单的数据(图像描述量)来描述整个图像,这组数据越简单越有代表性越好。良好的特征不受光线、噪点、几何形变的干扰。图像识别发展几十年,不断有新的特征提出,而图像不变矩就是其中一个。

    矩是概率与统计中的一个概念,是随机变量的一种数字特征。设XX为随机变量,cc为常数,kk为正整数。则量E[(xc)k]E[(x−c)k]称为XX关于cc点的kk阶矩。

    比较重要的有两种情况:

    1. c=0c=0。这时ak=E(Xk)ak=E(Xk)称为XX的kk阶原点矩

    2. c=E(X)c=E(X)。这时μk=E[(XEX)k]μk=E[(X−EX)k]称为XX的kk阶中心矩。

    一阶原点矩就是期望。一阶中心矩μ1=0μ1=0,二阶中心矩μ2μ2就是XX的方差Var(X)Var(X)。在统计学上,高于4阶的矩极少使用。μ3μ3可以去衡量分布是否有偏。μ4μ4可以去衡量分布(密度)在均值附近的陡峭程度如何。

    针对于一幅图像,我们把像素的坐标看成是一个二维随机变量(X,Y)(X,Y),那么一幅灰度图像可以用二维灰度密度函数来表示,因此可以用矩来描述灰度图像的特征。

    不变矩(Invariant Moments)是一处高度浓缩的图像特征,具有平移、灰度、尺度、旋转不变性。M.K.Hu在1961年首先提出了不变矩的概念。1979年M.R.Teague根据正交多项式理论提出了Zernike矩。下面主要介绍这两种矩特征的算法原理与实现。

    2. Hu矩

    一幅M×NM×N的数字图像f(i,j)f(i,j),其p+qp+q阶几何矩mpqmpq和中心矩μpqμpq为:

    mpq=i=1Mj=1Nipjqf(i,j)mpq=∑i=1M∑j=1Nipjqf(i,j)
     
    μpq=i=1Mj=1N(ii¯)p(jj¯)qf(i,j)μpq=∑i=1M∑j=1N(i−i¯)p(j−j¯)qf(i,j)

    其中f(i,j)f(i,j)为图像在坐标点(i,j)(i,j)处的灰度值。i¯=m10/m00,j¯=m01/m00i¯=m10/m00,j¯=m01/m00

    若将m00m00看作是图像的灰度质量,则(i¯,j¯)(i¯,j¯)为图像的质心坐标,那么中心矩μpaμpa反映的是图像灰度相对于其灰度质心的分布情况。可以用几何矩来表示中心矩,0~3阶中心矩与几何矩的关系如下:

    μ00=Mi=1Nj=1(ii¯)0(jj¯)0f(i,j)=m00μ00=∑i=1M∑j=1N(i−i¯)0(j−j¯)0f(i,j)=m00

    μ10=Mi=1Nj=1(ii¯)1(jj¯)0f(i,j)=0μ10=∑i=1M∑j=1N(i−i¯)1(j−j¯)0f(i,j)=0

    μ01=Mi=1Nj=1(ii¯)0(jj¯)1f(i,j)=0μ01=∑i=1M∑j=1N(i−i¯)0(j−j¯)1f(i,j)=0

    μ11=Mi=1Nj=1(ii¯)1(jj¯)1f(i,j)=m11y¯m10μ11=∑i=1M∑j=1N(i−i¯)1(j−j¯)1f(i,j)=m11−y¯m10

    μ20=Mi=1Nj=1(ii¯)2(jj¯)0f(i,j)=m20y¯m01μ20=∑i=1M∑j=1N(i−i¯)2(j−j¯)0f(i,j)=m20−y¯m01

    μ02=Mi=1Nj=1(ii¯)0(jj¯)2f(i,j)=m02y¯m01μ02=∑i=1M∑j=1N(i−i¯)0(j−j¯)2f(i,j)=m02−y¯m01

    μ30=Mi=1Nj=1(ii¯)3(jj¯)0f(i,j)=m302x¯m20+2x¯2m10μ30=∑i=1M∑j=1N(i−i¯)3(j−j¯)0f(i,j)=m30−2x¯m20+2x¯2m10

    μ12=Mi=1Nj=1(ii¯)1(jj¯)2f(i,j)=m122y¯m11x¯m02+2y¯2m10μ12=∑i=1M∑j=1N(i−i¯)1(j−j¯)2f(i,j)=m12−2y¯m11−x¯m02+2y¯2m10

    μ21=Mi=1Nj=1(ii¯)2(jj¯)1f(i,j)=m212x¯m11y¯m20+2x¯2m01μ21=∑i=1M∑j=1N(i−i¯)2(j−j¯)1f(i,j)=m21−2x¯m11−y¯m20+2x¯2m01

    μ03=Mi=1Nj=1(ii¯)0(jj¯)3f(i,j)=m032y¯m02+2y¯2m01μ03=∑i=1M∑j=1N(i−i¯)0(j−j¯)3f(i,j)=m03−2y¯m02+2y¯2m01

    为了消除图像比例变化带来的影响,定义规格化中心矩如下:

    ηpq=μpaμγ00,(γ=p+q2,p+q=2,3,)ηpq=μpaμ00γ,(γ=p+q2,p+q=2,3,…)

    利用二阶和三阶规格中心矩可以导出下面7个不变矩组(Φ1 Φ7)(Φ1 Φ7),它们在图像平移、旋转和比例变化时保持不变。

    Φ1=η20+η02Φ1=η20+η02

    Φ2=(η20η02)2+4η211Φ2=(η20−η02)2+4η112

    Φ3=(η203η12)2+3(η21η03)2Φ3=(η20−3η12)2+3(η21−η03)2

    Φ4=(η30+η12)2+(η21+η03)2Φ4=(η30+η12)2+(η21+η03)2

    Φ5=(η30+3η12)(η30+η12)[(η30+η12)23(η21+η03)2]+(3η21η03)(η21+η03)[3(η30+η12)2(η21+η03)2]Φ5=(η30+3η12)(η30+η12)[(η30+η12)2−3(η21+η03)2]+(3η21−η03)(η21+η03)[3(η30+η12)2−(η21+η03)2]

    Φ6=(η20η02)[(η30+η12)2(η21+η03)2]+4η11(η30+η12)(η21+η03)Φ6=(η20−η02)[(η30+η12)2−(η21+η03)2]+4η11(η30+η12)(η21+η03)

    Φ7=(3η21η03)(η30+η12)[(η30+η12)23(η21+η03)2]+]+(3η12η30)(η21+η03)[3(η30+η12)2(η21+η03)2]

    3. 利用OpenCV计算Hu矩

    opencv里对Hu矩的计算有直接的API,它分为了两个函数:moments()函数用于计算中心矩,HuMoments函数用于由中心矩计算Hu矩。

    Moments moments(InputArray array, bool binaryImage=false )

    参数说明

    • 输入参数:array是一幅单通道,8-bits的图像,或一个二维浮点数组(Point of Point2f)。binaryImage用来指示输出图像是否为一幅二值图像,如果是二值图像,则图像中所有非0像素看作为1进行计算。
    • 输出参数:moments是一个类

    4.contourArea()

    contour:是一个向量,二维点,可以是vector或Mat类型

    oriented:有默认值false,面向区域标识符,如果为true,该函数返回一个带符号的面积,其正负取决于轮廓的方向(顺时针还是逆时针)。根据这个特性可以根据面积的符号来确定轮廓的位置。如果是默认值false,则面积以绝对值的形式返回.

    该函数使用Green formula计算轮廓面积,返回面积和非零像素数量如果使用drawContours或fillPoly绘制轮廓,可能导致不同。

    5. arcLength()

     用于计算封闭轮廓的周长或曲线的长度

    curve:输入二维点集,可以是vector或Mat类型 
    closed:曲线是否封闭的标志位,true则封闭否则不封闭

     1 #include<opencv2/imgproc/imgproc.hpp>
     2 #include<opencv2/highgui/highgui.hpp>
     3 #include<iostream>
     4 
     5 using namespace cv;
     6 using namespace std;
     7 
     8 Mat src, grayImage;
     9 int Thresh = 100;
    10 int MaxThresh = 255;
    11 RNG rng(12345);
    12 Mat canny_output;
    13 vector<vector<Point>>contours;
    14 vector<Vec4i>hierarchy;
    15 
    16 void on_threshChange(int, void *);
    17  
    18 int main()
    19 {
    20     src = imread("D:/meinv.jpg");
    21 
    22     cvtColor(src, grayImage, COLOR_BGR2GRAY);
    23     blur(grayImage, grayImage, Size(3, 3));
    24 
    25     namedWindow("原图", CV_WINDOW_AUTOSIZE);
    26     imshow("原图", src);
    27 
    28     //创建滚动条并进行初始化
    29     createTrackbar("阈值", "原图", &Thresh, MaxThresh, on_threshChange);
    30     on_threshChange(0, 0);
    31     waitKey(0);
    32     return(0);
    33 }
    34 
    35 void on_threshChange(int, void*)
    36 {   
    37     //使用Canny检测边缘
    38     Canny(grayImage, canny_output, Thresh, Thresh * 2, 3);
    39     //找到轮廓
    40     findContours(canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
    41     //计算矩
    42     vector<Moments>mu(contours.size());
    43     for (int i = 0; i < contours.size(); i++)
    44     {
    45         mu[i] = moments(contours[i], false);
    46     }
    47     //计算图像的质心
    48     vector<Point2f>mc(contours.size());
    49     for (int i = 0; i < contours.size(); i++)
    50     {
    51         mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
    52     }
    53     //绘制轮廓
    54     Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
    55     for (int i = 0; i < contours.size(); i++)
    56     {
    57         Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    58         drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
    59         circle(drawing, mc[i], 4, color, -1, 8, 0);
    60     }
    61     //显示到窗口中
    62     namedWindow("轮廓图", WINDOW_AUTOSIZE);
    63     imshow("轮廓图", drawing);
    64 
    65     //用moments矩集计算轮廓面积并与opencv函数计算结果进行比较
    66     printf("	 Info: Area and Contour Length 
    ");
    67     for (int i = 0; i < contours.size(); i++)
    68     {
    69         printf("* Contour[%d] - Area(M_00)=%.2f-Area OpenCV:%.2f - Length:%.2f
    ", i, mu[i].m00, contourArea(contours[i]), arcLength(contours[i], true));
    70         Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    71         drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
    72         circle(drawing, mc[i], 4, color, -1, 8, 0);
    73     }
    74 }

    效果图:

    本文参考自:https://blog.csdn.net/keith_bb/article/details/70197104

          http://www.cnblogs.com/ronny/p/3985810.html

  • 相关阅读:
    第18章 检测点模型
    第17章 发现过拟合和欠拟合
    第16章 学习速率调度器
    第15章 MiniVGGNet:更深的CNNs
    第14章 LeNet:识别手写数字
    第13章保存和加载你的模型
    第12章 训练你的第一个CNN
    Vue.js
    python3第一天
    R+JAVA 中文乱码问题
  • 原文地址:https://www.cnblogs.com/carlber/p/9726347.html
Copyright © 2011-2022 走看看