天天看點

【opencv學習筆記】031 之 矩概念與圖像矩詳解

目錄

​​一、前言​​

​​二、矩概念詳解​​

​​1、離散情況​​

​​2、連續情況​​

​​三、圖像的幾何矩​​

​​1、幾何矩的概念​​

​​2、圖像的p+q階矩​​

​​3、HU矩​​

​​1.原點矩​​

​​2.中心矩​​

​​3.歸一化中心矩​​

​​4、相關API​​

​​1.Moments類​​

​​2.moments函數​​

​​3.contourArea函數​​

​​4.arcLength函數​​

​​5、代碼展示​​

​​6、執行結果​​

一、前言

圖像矩,opencv學習筆記的最後一個内容了。寫完這個,學習筆記也就寫完了,後續如果有精力,還會再寫一些代碼實戰的,感謝大家的支援。

如果想看其他有關于OpenCV學習方法介紹、學習教程、代碼實戰、常見報錯及解決方案等相關内容,可以直接看我的OpenCV分類:

如果你想了解更多有關于計算機視覺、OpenCV、機器學習、深度學習等相關技術的内容,想與更多大佬一起溝通,那就掃描下方二維碼加入我們吧!

二、矩概念詳解

矩這個東西,能組成的名詞太多了,矩形,就是長方形,矩陣,就是m行n列的二維數組,是以想了解矩,就要從其具體的場景中去了解。

今天我們要講的圖像矩,就是一個新的概念,圖像矩就是圖像的矩,這個概念來源于數學中的矩,是以我們要先來了解一下,數學中的矩。首先我們先來看一下它的定義和相關概念:

在數學和統計學中,矩(moment)是對變量分布和形态特點的一組度量。當所有的變量矩的定義是各點對某一固定點離差幂的平均值。n階矩被定義為一變量的n次方與其機率密度函數(Probability Density Function, PDF)之積的積分。在文獻中n階矩通常用符号μn表示。

直接使用變量計算的矩被稱為原始矩(raw moment),移除均值後計算的矩被稱為中心矩(central moment)。

講完了概念之後,我們從公式來直覺的看一下矩到底長啥樣。

1、離散情況

我們從矩的概念出發,我們先考慮離散情況:

假設有一個離散的随機變量X,用A表示一個常數,用k來表示幂(階數)。那麼我們有下面這個公式:
【opencv學習筆記】031 之 矩概念與圖像矩詳解

這個稱為X關于點A的k階矩。

如果這個常數A為0,我們把這個k階矩稱之為k階原點矩。

如果這個常數A為X的均值E(X),我們把這個k階矩稱之為k階中心矩。

變量的一階矩是數學期望(expectation),表示分布重心;

變量的二階矩是方差(variance),表示離散程度;

變量的三階矩是偏度(skewness),表示分布偏離對稱的程度;

變量的四階矩是峰度(kurtosis),描述分布的尖峰程度,例如正态分布峰态系數=0。

如果我們有兩個離散随機變量:X,Y。A1,A2分别代表對應于兩個随機變量的常數,用p,q表示幂(階數),那麼我們有下面的公式:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

這個稱為X,Y關于點A1,A2的p+q階矩。

如果兩個常數都是0,那麼我們稱之為p+q階混合原點矩。

如果兩個常數都是對應的均值,即A1=E(X),A2=E(Y),那麼我們稱之為p+q階混合中心矩。

2、連續情況

接下來我們考慮連續情況:

假設有一個連續的随機變量x,其單變量的機率密度函數為f(x),用A表示一個常數,用k來表示幂(階數)。那麼我們有下面這個公式:
【opencv學習筆記】031 之 矩概念與圖像矩詳解

這個稱為X關于點A的k階矩。

如果我們有兩個連續的随機變量:x,y,兩個變量的聯合機率密度為f(x,y)。A1,A2分别代表對應于兩個随機變量的常數,用p,q表示幂(階數),那麼我們有下面的公式:

【opencv學習筆記】031 之 矩概念與圖像矩詳解
這個稱為x,y關于點A1,A2的p+q階矩。

三、圖像的幾何矩

1、幾何矩的概念

了解了矩的概念,我們接下來說一下圖像的幾何矩。在圖像中,矩的概念如下:

矩是描述圖像特征的算子。

這裡的圖像是單通道,也就是灰階圖像,相當于一個矩陣,也就是上面提到的離散的情況。矩陣上每個位置的取值範圍是0-255的整數。

2、圖像的p+q階矩

圖像p+q階矩的定義公式如下:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

當p+q = 0時,為零階矩:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

當p+q = 1時,為一階矩:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

當p+q = 2時,為二階矩:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

通過上面的結果,我們也可以得到圖像的重心坐标和圖像的方向,這個時候的固定點為(0,0),是以:

圖像的重心坐标為:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

物體形狀方向為:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

3、HU矩

在圖像矩中有HU矩,這是Hu在1962年提出的,主要有:

(1)原點矩

(2)中心矩

(3)歸一化中心矩

1.原點矩

原點矩就是固定點的坐标為(0,0)。其公式如下:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

2.中心矩

中心矩就是以固定點(x0,y0)為中心:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

3.歸一化中心矩

歸一化中心矩就是對中心矩做歸一化處理:

【opencv學習筆記】031 之 矩概念與圖像矩詳解

4、相關API

1.Moments類

在講API之前,我們先說一下Moments類,它的定義如下:

class CV_EXPORTS_W_MAP Moments
{
public:
    //! the default constructor
    Moments();
    //! the full constructor
    Moments(double m00, double m10, double m01, double m20, double m11,
            double m02, double m30, double m21, double m12, double m03 );

    //! @name spatial moments
    CV_PROP_RW double  m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;

    //! @name central moments
    CV_PROP_RW double  mu20, mu11, mu02, mu30, mu21, mu12, mu03;

    //! @name central normalized moments
    CV_PROP_RW double  nu20, nu11, nu02, nu30, nu21, nu12, nu03;
};      

它有兩個預設構造函數和三組double類型的資料,

第一組資料:spatial moments(空間矩)對應的是我們前面講到的原點矩的零階矩、一階矩、二階矩和三階矩。

第二組資料:central moments(中心矩)對應的是我們前面講到的中心矩的二階矩和三階矩。

第三組資料:central normalized moments(歸一化中心矩)對應的是我們前面講到的歸一化中心矩的二階矩和三階矩。

2.moments函數

Moments moments( 
    InputArray array, 
    bool binaryImage = false 
);      

函數參數含義如下:

(1)InputArray類型的array,輸入的光栅圖像(單通道、8位或浮點二維數組)或二維點的數組。

(2)bool類型的binaryImage,如果為true,則所有非零圖像像素都被視為1。該參數僅用于圖像。

3.contourArea函數

double contourArea( 
    InputArray contour, 
    bool oriented = false 
);      

函數參數含義如下:

(1)InputArray類型的contour,二維點(輪廓頂點)的輸入向量,存儲在std::vector或Mat中。

(2)bool類型的oriented,面向區域标志。如果為真,則函數将根據輪廓方向(順時針或逆時針)傳回帶符号區域值。使用此功能,可以通過擷取區域的符号來确定輪廓的方向。預設情況下,參數為false,這意味着傳回絕對值。

4.arcLength函數

double arcLength( 
    InputArray curve, 
    bool closed 
);      

函數參數含義如下:

(1)InputArray類型的curve,二維點的輸入向量,存儲在std::vector或Mat中。

(2)bool類型的closed,訓示曲線是否閉合的标志。

5、代碼展示

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

Mat src, gray_src;
int threshold_value = 80;
int threshold_max = 255;
const char* input_win = "【輸入圖像】";
const char* output_win = "【輸出圖像】";
const char* trackbar_title = "Threshold:";
RNG rng(12345);

void Demo_Moments(int, void*);
int main() {
  src = imread("E:/image/moments.png");
  if (!src.data)
  {
    cout << "could not load image !";
    waitKey(0);
    return -1;
  }
  cvtColor(src, gray_src, CV_BGR2GRAY);
  GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);

  namedWindow(input_win, CV_WINDOW_AUTOSIZE);
  namedWindow(output_win, CV_WINDOW_AUTOSIZE);
  imshow(input_win, src);

  createTrackbar("Threshold", output_win, &threshold_value, threshold_max, Demo_Moments);
  Demo_Moments(0, 0);

  waitKey(0);
  return 0;
}

void Demo_Moments(int, void*) {
  Mat canny_output;
  vector<vector<Point>> contours;
  vector<Vec4i> hierachy;

  Canny(gray_src, canny_output, threshold_value, threshold_value * 2, 3, false);
  findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

  vector<Moments> contours_moments(contours.size());
  vector<Point2f> ccs(contours.size());
  for (size_t i = 0; i < contours.size(); i++) {
    contours_moments[i] = moments(contours[i]);
    ccs[i] = Point(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00), static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00));
  }

  Mat drawImg;// = Mat::zeros(src.size(), CV_8UC3);
  src.copyTo(drawImg);
  for (size_t i = 0; i < contours.size(); i++) {
    if (contours[i].size() < 100) {
      continue;
    }
    Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    printf("center point x : %.2f y : %.2f\n", ccs[i].x, ccs[i].y);
    printf("contours %d area : %.2f   arc length : %.2f\n", i, contourArea(contours[i]), arcLength(contours[i], true));
    drawContours(drawImg, contours, i, color, 1, 8, hierachy, 0, Point(0, 0));
    circle(drawImg, ccs[i], 1, color, 1, 8);
  }

  imshow(output_win, drawImg);
}      

6、執行結果

center point x : 451.00 y : 295.00
contours 2 area : 6493.00   arc length : 307.08
center point x : 451.00 y : 295.00
contours 3 area : 6451.00   arc length : 304.74
center point x : 296.00 y : 296.00
contours 4 area : 7234.00   arc length : 318.39
center point x : 296.00 y : 296.00
contours 5 area : 7188.00   arc length : 316.05
center point x : 296.00 y : 296.00
contours 6 area : 5812.00   arc length : 285.42
center point x : 296.00 y : 296.00
contours 7 area : 5770.00   arc length : 283.08
center point x : 495.00 y : 196.00
contours 8 area : 7537.00   arc length : 326.39
center point x : 495.00 y : 196.00
contours 9 area : 7496.00   arc length : 324.05
center point x : 495.00 y : 196.00
contours 10 area : 6079.00   arc length : 293.42
center point x : 495.00 y : 196.00
contours 11 area : 6045.00   arc length : 291.08
center point x : 140.00 y : 158.00
contours 12 area : 9359.00   arc length : 367.36
center point x : 140.00 y : 158.00
contours 13 area : 9313.00   arc length : 365.02
center point x : 344.00 y : 128.00
contours 14 area : 5525.00   arc length : 306.45
center point x : 344.00 y : 127.00
contours 15 area : 5493.00   arc length : 304.11
center point x : 247.00 y : 90.00
contours 16 area : 6527.00   arc length : 317.28
center point x : 247.00 y : 90.00
contours 17 area : 6525.00   arc length : 314.94
center point x : 247.00 y : 90.00
contours 18 area : 5125.00   arc length : 281.97
center point x : 247.00 y : 90.00
contours 19 area : 5119.00   arc length : 279.62