[学习OpenCV]Moment矩,Hu不变矩,轮廓匹配/形状匹配 -1

目录

矩的概念介绍

空间矩,中心矩,中心归一化矩,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

空间矩,中心矩,中心归一化矩,Hu矩

在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).

Hu不变距

矩的基本概念可参考:在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矩由于具有尺度、旋转、平移不变性,可以用来做匹配。

OpenCV中计算Hu矩的公式为:

Hu不变矩主要是利用归一化中心矩构造了7个不变特征矩,由二阶矩和三阶矩可以导出7个不变矩

image

 

OpenCV计算矩的函数

OpenCV计算矩moments的函数

一阶矩:与形状有关;二阶矩:显示曲线围绕直线平均值的扩展程度;三阶矩:关于平均值的对称性测量;

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)

空间矩10个

 

OpenCV中计算Hu矩函数:

HuMoments(const Moments& m, OutputArray hu)

void HuMoments(const Moments& moments, double hu[7])

中心矩/归一化中心矩(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<vector<Point> > contours;
vector<Vec4i> 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<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
    { mu[i] = moments( contours[i], false ); }

//计算轮廓的质心
vector<Point2f> 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 );
    }

程序执行后效果图:

imageimage

轮廓匹配/形状匹配

利用matchShape函数比较两个轮廓

最后我们再利用matchShape函数比较两个轮廓,如果结果为0,表示两个轮廓完全相似,结果值越大,越不相似,但这个最大值好像并没有归一化,我曾经比较两个轮廓,结果值达到了10。

image

 

比较的代码为:

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函数第三个参数说明

matchShapes函数其实比较的是两个轮廓的Hu不变矩,第三个参数决定比较的方式,下面是第三个参数的三个可选值。

Moment矩,Hu不变矩,轮廓匹配/形状匹配 -1 

Moment矩,轮廓特征,轮廓匹配,形状匹配 -2

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值