矩(moment) 是概率与统计中的一个概念,是随机变量的一种数字特征,是对变量分布和形态特点的一组度量。
矩的定义如下:
<math xmlns="http://www.w3.org/1998/Math/MathML"> m n = ∫ − ∞ ∞ x n f ( x ) d x m_n = \textstyle \int_{-\infty}^{\infty} x^nf(x) dx </math>mn = ∫−∞∞xnf(x)dx
其中,f(x) 是随机变量的概率密度函数或概率质量函数,n 是正整数表示矩的阶数。
矩可以用来描述变量的均值、方差、偏度、峰度等特性。矩的性质如下:
- 零阶矩是变量的均值。
- 一阶矩是变量的均方根。
- 二阶矩是变量的方差。
- 三阶矩是变量的偏度。
- 四阶矩是变量的峰度。
在图像处理中,图像的矩是指图像的某些特定像素灰度的加权平均值,或者是图像具有类似功能或意义的属性。图像矩可以表示图像的一些特征,通过这些特征便于对图像进行识别。
1. 空间矩/几何矩
空间矩 是图像矩特征中最基本的一种,它只考虑图像的像素值。
<math xmlns="http://www.w3.org/1998/Math/MathML"> m p q = ∑ x , y f ( x , y ) ( x p + y q ) m_{pq} = \displaystyle \sum_{x,y} f(x,y)(x^p+y^q) </math>mpq = x,y∑ f(x,y)(xp+yq)
其中,f(x,y) 表示输入的图像,p、q 是正整数。
1.1 零阶矩
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 00 = ∑ x , y f ( x , y ) m_{00} = \displaystyle \sum_{x,y} f(x,y) </math>m00 = x,y∑ f(x,y)
零阶矩可以用来描述图像的面积。
1.2 一阶矩
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 10 = ∑ x , y x f ( x , y ) m_{10} = \displaystyle \sum_{x,y} xf(x,y) </math>m10 = x,y∑ xf(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 01 = ∑ x , y y f ( x , y ) m_{01} = \displaystyle \sum_{x,y} yf(x,y) </math>m01 = x,y∑ yf(x,y)
一阶矩可以用来描述图像的质心。
1.3 二阶矩
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 20 = ∑ x , y x 2 f ( x , y ) m_{20} = \displaystyle \sum_{x,y} x^2f(x,y) </math>m20 = x,y∑ x2f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 02 = ∑ x , y y 2 f ( x , y ) m_{02} = \displaystyle \sum_{x,y} y^2f(x,y) </math>m02 = x,y∑ y2f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 11 = ∑ x , y x y f ( x , y ) m_{11} = \displaystyle \sum_{x,y} xyf(x,y) </math>m11 = x,y∑ xyf(x,y)
二阶矩可以用来描述图像的周长、长轴、短轴、扭矩等信息。
1.4 三阶矩
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 30 = ∑ x , y x 3 f ( x , y ) m_{30} = \displaystyle \sum_{x,y}x^3f(x,y) </math>m30 = x,y∑x3f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 03 = ∑ x , y y 3 f ( x , y ) m_{03} = \displaystyle \sum_{x,y}y^3f(x,y) </math>m03 = x,y∑y3f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 21 = ∑ x , y x 2 y f ( x , y ) m_{21} = \displaystyle \sum_{x,y}x^2yf(x,y) </math>m21 = x,y∑x2yf(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> m 12 = ∑ x , y x y 2 f ( x , y ) m_{12} = \displaystyle \sum_{x,y}xy^2f(x,y) </math>m12 = x,y∑xy2f(x,y)
下面的代码找到图像中的有效轮廓后,通过 moments() 函数计算轮廓的空间矩。
cpp
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
bool ascendSort(vector<Point> a,vector<Point> b)
{
return contourArea(a) > contourArea(b);
}
int main(int argc, char **argv) {
Mat src = imread("/Users/Tony/OpenCV_Learning/2.11/test.jpg");
imshow("src", src);
Mat gray,thresh;
cvtColor(src, gray, cv::COLOR_BGR2GRAY);
threshold(gray,thresh,0,255,THRESH_BINARY_INV | THRESH_OTSU);
imshow("thresh", thresh);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(thresh, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
sort(contours.begin(), contours.end(), ascendSort);//ascending sort
for (size_t i = 0; i< contours.size(); i++) {
double area = contourArea(contours[i]);
if (area < 11000) {
continue;
}
RotatedRect rrt = minAreaRect(contours[i]);
Point2f pt[4];
rrt.points(pt);
line(src, pt[0], pt[1], Scalar(0, 0, 255), 8, 8);
line(src, pt[1], pt[2], Scalar(0, 0, 255), 8, 8);
line(src, pt[2], pt[3], Scalar(0, 0, 255), 8, 8);
line(src, pt[3], pt[0], Scalar(0, 0, 255), 8, 8);
Moments m = cv::moments(contours[i]);
printf("m.m00 = %f, m.m10 = %f, m.m01 = %f,m.m20 = %f, m.m11 = %f, m.m02 = %f,m.m30 = %f, m.m21 = %f, m.m12 = %f, m.m03 = %f \n", m.m00, m.m10, m.m01, m.m20, m.m11, m.m02,m.m30,m.m21,m.m12,m.m03);
}
imshow("result", src);
waitKey(0);
return 0;
}
调用 moments() 函数会返回 Moments 对象,包含了空间矩以及中心矩和归一化中心矩。
cpp
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 );
////! the conversion from CvMoments
//Moments( const CvMoments& moments );
////! the conversion to CvMoments
//operator CvMoments() const;
//! @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;
//! @}
};
空间矩的优点如下:
- 计算简单
- 易于实现。
- 能够描述图像的形状、大小、位置等信息。
空间矩的缺点,也很明显:
- 不具有尺度不变性和旋转不变性。
- 对噪声敏感。
尺度不变性 是指图像中的物体尺寸变化不应该影响计算机视觉算法的性能。旋转不变性是指图像中的物体旋转后,计算机视觉算法仍能正确识别或检测该物体。
2. 中心矩
中心矩考虑了图像的像素值和质心位置。
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ p q = ∑ x , y ( x − x ‾ ) p ( y − y ‾ ) q f ( x , y ) \mu_{pq} = \displaystyle \sum_{x,y}(x-\overline{x})^p(y-\overline{y})^qf(x,y) </math>μpq = x,y∑(x−x)p(y−y)qf(x,y)
其中,f(x,y) 表示输入的图像, <math xmlns="http://www.w3.org/1998/Math/MathML"> x ‾ \overline{x} </math>x 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> y ‾ \overline{y} </math>y 是图像的质心,p、q 是正整数。
质心可以通过下面的公式进行计算: <math xmlns="http://www.w3.org/1998/Math/MathML"> x ‾ = m 10 m 00 \overline{x} = \frac{m_{10}}{m_{00}} </math>x = m00m10, <math xmlns="http://www.w3.org/1998/Math/MathML"> y ‾ = m 01 m 00 \overline{y} = \frac{m_{01}}{m_{00}} </math>y = m00m01
2.1 零阶矩
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 00 = ∑ x , y f ( x , y ) \mu_{00} = \displaystyle \sum_{x,y}f(x,y) </math>μ00 = x,y∑f(x,y)
中心矩的零阶矩与空间矩的零阶矩相同,可以用来描述图像的面积。
2.2 一阶矩
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 10 = ∑ x , y ( x − x ‾ ) f ( x , y ) \mu_{10} = \displaystyle \sum_{x,y}(x-\overline{x})f(x,y) </math>μ10 = x,y∑(x−x)f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 01 = ∑ x , y ( y − y ‾ ) f ( x , y ) \mu_{01} = \displaystyle \sum_{x,y}(y-\overline{y})f(x,y) </math>μ01 = x,y∑(y−y)f(x,y)
中心矩的一阶矩可以用来描述图像的质心位置的偏移。 <math xmlns="http://www.w3.org/1998/Math/MathML"> μ 10 \mu_{10} </math>μ10 表示图像质心在 x 方向的偏移量, <math xmlns="http://www.w3.org/1998/Math/MathML"> μ 01 \mu_{01} </math>μ01 表示图像质心在 y 方向的偏移量。
2.3 二阶矩
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 20 = ∑ x , y ( x − x ‾ ) 2 f ( x , y ) \mu_{20} = \displaystyle \sum_{x,y}(x-\overline{x})^2f(x,y) </math>μ20 = x,y∑(x−x)2f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 02 = ∑ x , y ( y − y ‾ ) 2 f ( x , y ) \mu_{02} = \displaystyle \sum_{x,y}(y-\overline{y})^2f(x,y) </math>μ02 = x,y∑(y−y)2f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 11 = ∑ x , y ( x − x ‾ ) ( y − y ‾ ) f ( x , y ) \mu_{11} = \displaystyle \sum_{x,y}(x -\overline{x})(y-\overline{y})f(x,y) </math>μ11 = x,y∑(x−x)(y−y)f(x,y)
中心矩的二阶矩表示图像的形状和大小。
二阶矩的物理意义如下:
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 20 \mu_{20} </math>μ20 表示图像的长轴方向的方差。
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 02 \mu_{02} </math>μ02 表示图像的短轴方向的方差。
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 11 \mu_{11} </math>μ11 表示图像的主轴方向的偏心度。
2.4 三阶矩
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 30 = ∑ x , y ( x − x ‾ ) 3 f ( x , y ) \mu_{30} = \displaystyle \sum_{x,y}(x-\overline{x})^3f(x,y) </math>μ30 = x,y∑(x−x)3f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 03 = ∑ x , y ( y − y ‾ ) 3 f ( x , y ) \mu_{03} = \displaystyle \sum_{x,y}(y-\overline{y})^3f(x,y) </math>μ03 = x,y∑(y−y)3f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 21 = ∑ x , y ( x − x ‾ ) 2 ( y − y ‾ ) f ( x , y ) \mu_{21} = \displaystyle \sum_{x,y}(x-\overline{x})^2(y-\overline{y})f(x,y) </math>μ21 = x,y∑(x−x)2(y−y)f(x,y)
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 12 = ∑ x , y ( x − x ‾ ) ( y − y ‾ ) 2 f ( x , y ) \mu_{12} = \displaystyle \sum_{x,y}(x-\overline{x})(y-\overline{y})^2f(x,y) </math>μ12 = x,y∑(x−x)(y−y)2f(x,y)
三阶矩的物理意义如下:
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 30 \mu_{30} </math>μ30 表示图像的偏度,反映了图像的对称性。
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 03 \mu_{03} </math>μ03 表示图像的峰度,反映了图像的尖锐程度。
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 21 \mu_{21} </math>μ21 表示图像的矩形程度,反映了图像的旋转不变性。
<math xmlns="http://www.w3.org/1998/Math/MathML"> μ 12 \mu_{12} </math>μ12 表示图像的椭圆程度,反映了图像的旋转不变性。
2.5 归一化中心矩
中心矩实现了平移不变性,但是仍然不具有尺度不变性和旋转不变性。
为了使目标区域不受缩放造成的尺度变化带来的影响也就是实现**尺度不变性,**使用 <math xmlns="http://www.w3.org/1998/Math/MathML"> μ 00 \mu_{00} </math>μ00对各阶中心距进行归一化处理:
<math xmlns="http://www.w3.org/1998/Math/MathML"> η p q = μ p q μ 00 p + q + 2 2 \eta_{pq} = \frac{\mu_{pq}}{\mu_{00}^{\frac{p+q+2}{2}}} </math>ηpq = μ002p+q+2μpq,其中 p+q = 2,3,4,...
可得归一化中心距。
3. Hu 矩
Hu 矩是从中心矩推导出来的,图像在旋转、缩放、平移等操作后,Hu 矩仍能保持矩的不变性,实现了平移不变性、尺度不变性 和旋转不变性。
<math xmlns="http://www.w3.org/1998/Math/MathML"> h u [ 0 ] = η 20 + η 02 hu[0]= \eta_{20} + \eta_{02} </math>hu[0]= η20 + η02
<math xmlns="http://www.w3.org/1998/Math/MathML"> h u [ 1 ] = ( η 20 − η 02 ) 2 + 4 η 11 2 hu[1] =(\eta_{20} - \eta_{02})^2+4\eta_{11}^2 </math>hu[1]=(η20 − η02)2+4η112
<math xmlns="http://www.w3.org/1998/Math/MathML"> h u [ 2 ] = ( η 30 − 3 η 12 ) 2 + ( 3 η 21 − η 03 ) 2 hu[2] = (\eta_{30} - 3\eta_{12})^2 +( 3\eta_{21}-\eta_{03})^2 </math>hu[2]=(η30−3η12)2+(3η21−η03)2
<math xmlns="http://www.w3.org/1998/Math/MathML"> h u [ 3 ] = ( η 30 + η 12 ) 2 + ( η 21 + η 03 ) 2 hu[3] = (\eta_{30} + \eta_{12})^2 + ( \eta_{21}+\eta_{03})^2 </math>hu[3]=(η30+ η12)2+(η21+η03)2
<math xmlns="http://www.w3.org/1998/Math/MathML"> h u [ 4 ] = ( η 30 − 3 η 12 ) ( η 30 + η 12 ) [ ( η 30 + η 12 ) 2 − 3 ( η 21 + η 03 ) 2 ] + ( 3 η 21 − η 03 ) [ 3 ( η 30 + η 12 ) 2 − ( η 21 + η 03 ) 2 ] hu[4] = (\eta_{30} - 3\eta_{12}) (\eta_{30}+\eta_{12})[(\eta_{30}+\eta_{12})^2-3(\eta_{21}+\eta_{03})^2]+(3\eta_{21}-\eta_{03})[3(\eta_{30}+\eta_{12})^2-(\eta_{21}+\eta_{03})^2] </math>hu[4]=(η30− 3η12)(η30+η12)[(η30+η12)2−3(η21+η03)2]+(3η21−η03)[3(η30+η12)2−(η21+η03)2]
<math xmlns="http://www.w3.org/1998/Math/MathML"> h u [ 5 ] = ( η 20 − η 02 ) [ ( η 30 + η 12 ) 2 − ( η 21 + η 03 ) 2 + 4 η 11 ( η 30 + η 12 ) ( η 21 + η 03 ) ] hu[5] = (\eta_{20} - \eta_{02}) [(\eta_{30}+\eta_{12})^2-(\eta_{21}+\eta_{03})^2+4\eta_{11}(\eta_{30}+\eta_{12})(\eta_{21}+\eta_{03})] </math>hu[5]=(η20−η02)[(η30+η12)2−(η21+η03)2+4η11(η30+η12)(η21+η03)]
<math xmlns="http://www.w3.org/1998/Math/MathML"> h u [ 6 ] = ( 3 η 21 − η 03 ) ( η 30 + η 12 ) [ 3 ( η 30 + η 12 ) 2 − ( η 21 + η 03 ) 2 ] + ( η 30 − 3 η 12 ) ( η 21 + η 03 ) [ 3 ( η 30 + η 12 ) 2 − ( η 21 + η 03 ) 2 ] hu[6] = (3\eta_{21}-\eta_{03})(\eta_{30}+\eta_{12})[3(\eta_{30}+\eta_{12})^2-(\eta_{21}+\eta_{03})^2]+(\eta_{30} - 3\eta_{12}) (\eta_{21}+\eta_{03})[3(\eta_{30}+\eta_{12})^2-(\eta_{21}+\eta_{03})^2] </math>hu[6]=(3η21−η03)(η30+η12)[3(η30+η12)2−(η21+η03)2]+(η30− 3η12)(η21+η03)[3(η30+η12)2−(η21+η03)2]
Hu矩的特性如下:
- 具有尺度不变性和旋转不变性。
- 对噪声鲁棒性较好。
- 可以描述图像的形状、大小、位置等信息。
OpenCV 提供了 HuMoments() 函数计算 Hu 矩。
下面的代码,通过 sample 图匹配原图中的物体。
cpp
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
bool ascendSort(vector<Point> a,vector<Point> b)
{
return contourArea(a) > contourArea(b);
}
int main(int argc, char **argv) {
Mat src = imread("/Users/Tony/OpenCV_Learning/2.11/test.jpg");
imshow("src", src);
Mat gray,thresh;
cvtColor(src, gray, cv::COLOR_BGR2GRAY);
threshold(gray,thresh,0,255,THRESH_BINARY_INV | THRESH_OTSU);
imshow("thresh", thresh);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(thresh, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
sort(contours.begin(), contours.end(), ascendSort);//ascending sort
Mat sample = imread("/Users/Tony/OpenCV_Learning/2.11/sample.jpg");
imshow("sample", sample);
Mat gray2,thresh2;
cvtColor(sample, gray2, cv::COLOR_BGR2GRAY);
threshold(gray2,thresh2,0,255,THRESH_BINARY_INV | THRESH_OTSU);
vector<vector<Point>> contours2;
vector<Vec4i> hierarchy2;
findContours(thresh2, contours2, hierarchy2, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
sort(contours2.begin(), contours2.end(), ascendSort);//ascending sort
Moments sample_moments = cv::moments(contours2[0]);
Mat sample_hu;
HuMoments(sample_moments, sample_hu);
for (size_t i = 0; i< contours.size(); i++) {
double area = contourArea(contours[i]);
if (area < 11000) {
continue;
}
Moments m = cv::moments(contours[i]);
Mat hu;
HuMoments(m, hu);
double dist = matchShapes(hu, sample_hu, CONTOURS_MATCH_I1, 0);
printf("contour match distance : %.2f\n", dist);
if (dist < 0.5) {
RotatedRect rrt = minAreaRect(contours[i]);
Point2f pt[4];
rrt.points(pt);
line(src, pt[0], pt[1], Scalar(0, 0, 255), 8, 8);
line(src, pt[1], pt[2], Scalar(0, 0, 255), 8, 8);
line(src, pt[2], pt[3], Scalar(0, 0, 255), 8, 8);
line(src, pt[3], pt[0], Scalar(0, 0, 255), 8, 8);
}
}
imshow("result", src);
waitKey(0);
return 0;
}
sample 图:
匹配到 sample 中的物体,并用红线框出:
matchShapes() 函数能够比较两个形状或两个轮廓,并返回一个显示相似性的度量。其结果越小,匹配就越好。
4. 总结
轮廓的矩特征是描述轮廓形状、大小、位置等信息的一种重要特征。轮廓的矩特征在图像处理、计算机视觉等领域有广泛的应用,矩特征可以用来进行轮廓的匹配、分类、识别等工作。