目录
矩的概念介绍
空间矩,中心矩,中心归一化矩,Hu矩
空间矩的公式为:
中心矩的公式为:
归一化的中心矩公式为
Hu不变距
OpenCV中计算Hu矩的公式为:
OpenCV计算矩的函数
OpenCV计算矩moments的函数
空间矩10个
OpenCV中计算Hu矩函数:
中心矩/归一化中心矩(7个)
示例程序
轮廓匹配/形状匹配
利用matchShape函数比较两个轮廓
matchShapes函数第三个参数说明
矩函数在图像分析中有着广泛的应用,如模式识别、目标分类、目标识别与方位估计、图像的编码与重构等。从一幅图像计算出来的矩集,不仅可以描述图像形状的全局特征,而且可以提供大量关于该图像不同的几何特征信息,如大小,位置、方向和形状等。图像矩这种描述能力广泛应用于各种图像处理、计算机视觉和机器人技术领域的目标识别与方位估计中。
一阶矩:与形状有关;
二阶矩:显示曲线围绕直线平均值的扩展程度;
三阶矩:关于平均值的对称性测量;
由二阶矩和三阶矩可以导出7个不变矩。而不变矩是图像的统计特性,满足平移、伸缩、旋转均不变的不变性、在图像识别领域得到广泛的应用。
参考opencv官网 https://docs.opencv.org/3.3.0/d8/d23/classcv_1_1Moments.html
在OpenCV中,可以很方便的计算多边形区域的3阶特征矩,opencv中的矩主要包括以下几种:空间矩,中心矩和中心归一化矩。
参考https://docs.opencv.org/3.3.0/d8/d23/classcv_1_1Moments.html
class Moments { public: ......
// 空间矩 double m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;
// 中心矩 double mu20, mu11, mu02, mu30, mu21, mu12, mu03;
// 中心归一化矩 double nu20, nu11, nu02, nu30, nu21, nu12, nu03; }
1 、空间矩/几何矩
空间矩的实质为面积或者质量。可以通过一阶矩计算质心/重心。
2、中心矩
中心矩体现的是图像强度的最大和最小方向(中心矩可以构建图像的协方差矩阵),其只具有平移不变性,所以用中心矩做匹配效果不会很好。
3、归一化的中心矩
归一化后具有尺度不变性。
4、Hu矩
Hu矩由于具有尺度、旋转、平移不变性,可以用来做匹配。
可以知道,对于01二值化的图像,m00即为轮廓的面积。
其中:
注意
,因此不会存储值。(由二阶矩和三阶矩可以导出7个不变矩)
轮廓的矩以相同的方式定义,但使用格林公式计算(参见http://en.wikipedia.org/wiki/Green_theorem )。 因此,由于光栅分辨率有限,为轮廓计算的力矩与为相同光栅化轮廓计算的力矩略有不同。
注意
由于轮廓矩是使用格林公式the Green's formula (see http://en.wikipedia.org/wiki/Green_theorem)公式计算的,因此对于具有自交叉的轮廓,您可能会得到看似奇怪的结果,例如,对于蝴蝶形轮廓,零区域(m00).
矩的基本概念可参考:在OpenCV中,还可以很方便的得到Hu不变距,Hu不变矩在图像旋转、缩放、平移等操作后,仍能保持矩的不变性,所以有时候用Hu不变距更能识别图像的特征。Hu不变矩的基本概念请参考paper:Hu. Visual Pattern Recognition by Moment Invariants, IRE Transactions on Information Theory, 8:2, pp. 179-187, 1962, 或者参考中文介绍:http://www.cnblogs.com/skyseraph/archive/2011/07/19/2110183.html
Hu矩由于具有尺度、旋转、平移不变性,可以用来做匹配。
Hu不变矩主要是利用归一化中心矩构造了7个不变特征矩,由二阶矩和三阶矩可以导出7个不变矩:
一阶矩:与形状有关;二阶矩:显示曲线围绕直线平均值的扩展程度;三阶矩:关于平均值的对称性测量;
OpenCV中计算矩的函数为:Moments moments(InputArray array, bool binaryImage=false )
Moments (double m00, double m10, double m01, double m20, double m11, double m02, double m30, double m21, double m12, double m03)
HuMoments(const Moments& m, OutputArray hu)
void HuMoments(const Moments& moments, double hu[7])
由二阶矩和三阶矩可以导出7个不变矩。
利用归一化中心矩构造了7个不变特征矩.由二阶矩和三阶矩可以导出7个不变矩。
下面的代码计算轮廓的矩,并根据1阶中心矩得到轮廓的质心,代码如下:
src = imread( "../star1.jpg" ,1 );
/// Convert image to gray and blur it
cvtColor( src, src_gray, CV_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
namedWindow( "image", CV_WINDOW_AUTOSIZE );
imshow( "image", src );
Mat canny_output;
vector > contours;
vector hierarchy;
//利用canny算法检测边缘
Canny( src_gray, canny_output, thresh, thresh*2, 3 );
namedWindow( "canny", CV_WINDOW_AUTOSIZE );
imshow( "canny", canny_output );
//查找轮廓
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
//计算轮廓矩
vector mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mu[i] = moments( contours[i], false ); }
//计算轮廓的质心
vector mc( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }
//画轮廓及其质心
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
circle( drawing, mc[i], 4, color, -1, 8, 0 );
}
namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
//打印轮廓面积和轮廓长度
printf("\t Info: Area and Contour Length \n");
for( int i = 0; i< contours.size(); i++ )
{
printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) );
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
circle( drawing, mc[i], 4, color, -1, 8, 0 );
}
程序执行后效果图:
最后我们再利用matchShape函数比较两个轮廓,如果结果为0,表示两个轮廓完全相似,结果值越大,越不相似,但这个最大值好像并没有归一化,我曾经比较两个轮廓,结果值达到了10。
比较的代码为:
double comres;
comres = matchShapes(contours[0], contours[1],CV_CONTOURS_MATCH_I1, 0.0);
printf("CV_CONTOURS_MATCH_I1 比较结果是: %f\n", comres);
comres = matchShapes(contours[0], contours[1],CV_CONTOURS_MATCH_I2, 0.0);
printf("CV_CONTOURS_MATCH_I2 比较结果是: %f\n", comres);
comres = matchShapes(contours[0], contours[1],CV_CONTOURS_MATCH_I3, 0.0);
printf("CV_CONTOURS_MATCH_I3 比较结果是: %f\n", comres);
matchShapes函数其实比较的是两个轮廓的Hu不变矩,第三个参数决定比较的方式,下面是第三个参数的三个可选值。
Moment矩,Hu不变矩,轮廓匹配/形状匹配 -1
Moment矩,轮廓特征,轮廓匹配,形状匹配 -2