【OpenCV】图像的矩与轮廓匹配

了解了轮廓之后,一个跟轮廓相关的最常用的功能是如何匹配多条轮廓。我们或许需要比较两条计算好的轮廓,或者比较一条轮廓和一个抽象模板。

比较两条轮廓最简洁的方法之一是比较它们的轮廓矩:
期望、方差、协方差在数学上都是矩。
矩是描述图像特征的算子。常见的矩描述自可以分为以下几种:几何矩、正交矩、复数矩和旋转矩。
图像的几何矩,这里的图像指的是单同道,也就是灰度图像。我们把图像可以看成是一个平板的物体,每个像素点的值看成是该处的密度。对某点求期望就是该图像在该点处的矩。我们一般说图像矩,指的是原点矩。一阶矩和零阶矩就可以计算某个形状的重心,而二阶矩就可以拿来计算形状的方向。
在一定条件下,并不总是出现相同结果的现象称为随机现象。表示随机现象各种结果的变量(一切可能的样本点)称为随机变量。随机变量的函数仍然是随机变量。针对于一幅图像,我们把像素的坐标看成是一个二维随机变量(X,Y),那么一幅灰度图像可以用二维灰度密度函数来表示,因此可以用矩来描述灰度图像的特征.不变矩(Invariant Moments)是一处高度浓缩的图像特征,具有平移、灰度、尺度、旋转不变性。
几何矩
-原点矩
其中(i+j)和等于 几阶矩
-中心距 在这里插入图片描述
其中x横杠和y横杠表示它的中心质点
-中心归一化矩-
在这里插入图片描述

矩的数值定义如下:
在这里插入图片描述
在上式中,mp,q代表对象中所有像素的总和,其中每个像素x,y的像素值都乘以因子xpyq。在m00时,这个因子等于1.因此若图像为二值图(例如,所有像素都等于0或者1),则m00代表图像上所有值非零的区域。当处理轮廓时,结果是轮廓的长度。
【纯数学论者可能不同意m00为轮廓边界长度,他们认为应该是面积。但此处我们处理的是一个轮廓,而不是一个被填充的多边形,因此多边型的边长和 边界上的像素在离散的像素空间里是相同的(至少在像素空间里是跟距离相关的)。同样也有计算cv::array图像的矩函数。对于图像,m00一般对应非0像素的面积。然而事实上,这个区别并不只有学术意义。例如一条轮廓由一些列顶点组成,那么直接采用公式计算轮廓长度得到的面积,与先把轮廓栅格化(比如使用cv::drawContours()函数)再计算得到的面积并不完全相同。尽管两者在分辨率无限大的情况下应该趋近于同一个值。】
当处理点集时,它代表的仅是点的数量。经过思考,你应该能理解对于同一张二值图,将m10和m01相加再除以m00,能得到整个对象的平均x值和y值。“矩”这个名称与数值中的矩有关,而更高阶的矩则与数值分布(如面积、均值、方差等)中的矩有关。从这个意义上来说,可以将非二值图的矩看作是特殊情况下的二值图的矩,只不过其中每个像素点上存在多个值。
刚刚描述的矩计算给出了一些轮廓的简单属性,可以用来比较两个轮廓。但是在很多实际使用中,刚才这种方法计算得到的矩并不是做比较时最好的参数。具体来说,目前为止我们所讨论的矩,对于形状相同但大小不同,或者存在相互位移或旋转的两条轮廓,会有不同的值。
中心距的位移不变性
给定一条轮廓或一幅图像,不管轮廓出现在图像中的哪个地方,m00矩显然都是相同的,那些更高阶的矩则会改变。考虑之前我们用对象中像素x坐标均值定义过的m10矩,显然,当同样的物体出现在不同的地方时,对象的x坐标均值也会不同。尽管粗看不明显,但体现了物体铺开范围的二阶中心矩同样具有平移不变性。若你不太理解这些数学术语,“平移不变性”指的是物体的某些计算量不随物体在图像中的移动(例如平移)而变化。类似的,“旋转不变性”指的是物体的某些计算量不随物体在图像中的旋转而变化。在许多情况下,我们需要利用这些矩,将可能出现在图像中任意位置的物体与参考图像中可能出现在另外位置的参考物体进行比较。这以问题的解决方法是计算中心矩。中心距常用up,q标注,定义如下:
在这里插入图片描述
其中:
在这里插入图片描述
且:
在这里插入图片描述
当然,很明显u00=m00(因为含有p和q的项合并消失了),并且u10和u01中心矩都等于0.更高阶的矩与非中心距相同,只不过是相对物体质心(或基于物体之心坐标系)测量得到的。由于这些值是相对质心得到的,所以它们也不随物体在图像中的绝对位置改变而改变。

归一化中心矩的缩放不变性
中心矩已经能够帮助我们比较图像中不同位置的两个物体。同样,比较图像中两个除了尺度大小其他全部相同的物体也有重要意义。有时候,这样做是为了在图像中寻找本来就尺度不一的物体。但大部分时候还是因为我们不知道物体距离开始拍摄图像的相机有多远。
中心矩通过减去均值而获得平移不变性,类似的归一化中心矩通过除以物体的总尺寸而获得缩放不变性。归一化中心矩定义式如下:
在这里插入图片描述
这个略微复杂的公式表明,归一化中心矩就是中心矩加上一个归一化因子,这个因子是物体面积的幂(对于更高阶的矩,这个幂会更大)。在opencv中,并没有特定的函数用于计算归一化矩,因为cv::moments()在计算标准矩和中心矩时会自动计算归一化矩。

Hu不变矩的旋转不变性
Hu不变矩是归一化中心矩的线性组合。通过组合不同的归一化中心矩,我们可以得到一个反应图像不同特征的不变函数,这个函数不随尺度、旋转、镜面映射(除了h1)变化而变化。
为了完整性,这里我们给出Hu矩的实际定义:
在这里插入图片描述

用cv::HuMoments()计算Hu不变矩
其它的矩都能用cv::moments()函数计算,Hu矩的计算用到了cv::HuMoments()函数。它接受cv::moments()函数返回的cv::Moments对象作为输入,并返回7个hu矩的值。函数定义如下:
void cv::HuMoments(
const cv::Moments& moments,
double hu
);
cv::HuMoments()函数接受cv::Moments对象作为输入,并返回一个指针,指向一个预分配好内存的C语言风格数组,数组中存储了7个Hu矩值。
使用Hu矩进行匹配
自然,我们想要使用Hu矩比较两个物体,并判定它们是否相似。当然,对“相似”的定义可能有很多。为了是比较过程变得简单,opencv的函数cv::matchshapes()允许我们简单提供两个物体,然后计算它们的矩,并根据我们提供的标准进行比较。

猜你喜欢

转载自blog.csdn.net/weixin_42104289/article/details/84344155