OpenCv轮廓高级应用(轮廓匹配,几何直方图)
最近再次用到了opencv轮廓,在这里结合作者冰山一角的博客(http://www.cnblogs.com/slysky/)以及自己的体会在此稍加说明。其程序主要参见冰山一角的Blog,遗憾的是代码是OpenCV1.0写的,等有时间再用2.4.2改写一篇。
对于轮廓的相关数据结构表示和几本操作(查找轮廓,画轮廓),可参见前面两片关于轮廓的例程,在这里不多讲。
对于查找轮廓我们一般要对图像Canny检测。但是对于很特殊的场合其实我们还可以直接对二值化的图像进行轮廓的提取,找出的轮廓其实就是Blob(这个可能就是为什么OpenCV高版本里面把blob分析抛弃的原因吧,我猜的话),画上外截矩形就是一个ROI,是不是觉得很有用?下面介绍罗阔的高级应用。
轮廓的特性:
1.轮廓的多边形逼近 轮廓的多边形逼近指的是:使用多边形来近似表示一个轮廓。
多边形逼近的目的是为了减少轮廓的顶点数目。
多边形逼近的结果依然是一个轮廓,只是这个轮廓相对要粗旷一些。
可以使用方法cvApproxPoly()
2.轮廓的关键点 轮廓的关键点是:轮廓上包含曲线信息比较多的点。关键点是轮廓顶点的子集。
可以使用cvFindDominantPoints函数来获取轮廓上的关键点,该函数返回的结果一个包含 关键点在轮廓顶点中索引
的序列。再次强调:是索引,不是具体的点。如果要得到关键点的具体坐标,可以用索引到轮廓上去找。
3.轮廓的周长和面积 轮廓的周长可以用cvContourPerimeter或者cvArcLength函数来获取。
轮廓的面积可以用cvContourArea函数来获取。
4.轮廓的边界框 有三种常见的边界框:矩形、圆形、椭圆。
(1)矩形:在图像处理系统中提供了一种叫Rectangle的矩形,不过它只能表达边垂直或水平的特例;OpenCv中还有一种叫Box的矩形,它跟数学上的矩形一致,只要4个角是直角即可。
如果要获取轮廓的Rectangle,可以使用cvBoundingRect函数。
如果要获取轮廓的Box,可以使用cvMinAreaRect2函数。
(2)圆形
如果要获取轮廓的圆形边界框,可以使用cvMinEnclosingCircle函数。
(3)椭圆
如果要获取轮廓的椭圆边界框,可以使用cvFitEllipse2函数。
5.轮廓的矩
矩是通过对轮廓上所有点进行积分运算(或者认为是求和运算)而得到的一个粗略特征。
在连续情况下,图像函数为
f(x,y),那么图像的p+q阶几何矩(标准矩)定义为:
p
,q = 0,1,2……
p+q阶中心距定义为:
p,q
= 0,1,2……
其中
和
代表图像的重心,
,
对于离散的数字图像,采用求和号代替积分:
,
,p,q
= 0,1,2 ……
N和M分别是图像的高度和宽度;
归一化的中心距定义为:
;其中
在公式中,p对应x维度上的矩,q对应y维度上的矩,阶数表示对应的部分的指数。该计算是对轮廓界上所有像素(数目为n)进行求和。如果p和q全部为0,那么m00实际上对应轮廓边界上点的数目。
虽然可以直接计算出轮廓的矩,但是经常会用到归一化的矩(因此不同大小但是形状相同的物体会有相同的值)。同样,简单的矩依赖于所选坐标系,这意味着物体旋转后就无法正确匹配。
于是就产生了Hu矩以及其他归一化矩的函数。
Hu矩是归一化中心矩的线性组合。之所以这样做是为了能够获取代表图像某个特征的矩函数。这些矩函数对缩放,旋转和镜像映射出了(h1)具有不变性。
Hu矩是从中心矩中计算得到。即七个由归一化中心矩组合成的矩:
其中中心矩和归一化中心矩的定义为:
我们可以使用cvContoursMoments函数、cvMoments函数方便的得到轮廓的矩集,然后再相应的方法或函数获取各种矩。
特定的矩:cvGetSpatialMoment函数
中心矩:cvGetCentralMoment函数
归一化中心矩:cvGetNormalizedCentralMoment函数
Hu矩:cvGetHuMoments函数
6.轮廓的轮廓树 轮廓树用来描述某个特定轮廓的内部特征。注意:轮廓树跟轮廓是一一对应的关系;轮廓树不用于描述多个轮廓之间的层次关系。
轮廓树的创建过程:
从一个轮廓创建一个轮廓树是从底端(叶子节点)到顶端(根节点)的。