在http://blog.csdn.net/piaoxuezhong/article/details/77966132中,为了消除睫毛等对边缘识别的影响,对采集的虹膜图像进行闭操作,由于形态学运算在图像预处理中应用还是比较广泛的,本篇单独进行总结。
形态学指的是对象的形式和结构,或说是对象中各个部分之间的布局和相互关系,形态学和形状相关,数码形态学指的是一种对数字对象的形状的描述和分析(摘自《图像处理及计算机视觉算法及应用,第二版》)。1964年法国学者在积分几何的研究成果上,将数学形态学引入图像处理领域,并研制了基于数学形态学的图像处理系统。1982年出版的专著《Image Analysis and Mathematical Morphology》表明数学形态学在理论上的完备和在应用上的深入。目前,数学形态学已在计算机视觉、信号处理与图像分析、模式识别、计算方法与数据处理等方面得到了极为广泛的应用。在图像处理方面,数学形态学可以用于抑制噪声、特征提取、边缘检测、图像分割、形状识别、纹理分析、图像恢复与重建、图像压缩等问题。
数学形态学背后的数学理论是集合论,图像是由一组图片元素组成的,这些像素组合起来组成二维结构,即是形状。其基本思想是用具有一定形态的结构元素去度量和提取图像中的对应形状,从而达到对图像分析和识别的目的。数学形态学的应用可以简化图像数据,但保持基本的形状特征,除去不相干的结构。数学形态学的基本运算有4种:膨胀、腐蚀、开启和闭合。基于这些基本运算还可以推导和组合成其他数学形态学实用算法。
形态学的运算背后的概念有连通性(就是常说的4邻域,8邻域等概念),二值操作等,这些图像处理里的基本知识,不多说了,下面进入正题吧:膨胀与腐蚀。
膨胀,就是用一个核去扫描原图,即卷积,用核所覆盖区域的最大像素值代替锚点位置的像素。核函数生成一般使用getStructuringElement函数,返回指定形状和尺寸的结构元素。
int g_nStructElementSize = 3; //内核矩阵的尺寸
Mat element = getStructuringElement(MORPH_RECT,
Size(2*g_nStructElementSize+1,2*g_nStructElementSize+1),
Point( g_nStructElementSize, g_nStructElementSize ));
其中,getStructuringElement函数的第一个参数表示内核的形状,可以选择一下三种形状之一:opencv实现函数:
void cv::dilate( InputArray src,OutputArray dst, InputArray kernel,
Point anchor, int iterations,
int borderType, constScalar& borderValue )
{
morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType,borderValue );
}
实例:
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat image = imread("desertEagle.jpg");
namedWindow("【原图】膨胀操作");
namedWindow("【效果图】膨胀操作");
imshow("【原图】膨胀操作", image);
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
Mat out;
dilate(image, out, element);
imshow("【效果图】膨胀操作", out);
waitKey(0);
return 0;
}
腐蚀,是用一个核去扫描原图,即卷积,用核所覆盖区域的最小像素值代替锚点位置的像素。opencv实现函数:
void cv::erode( InputArray src, OutputArraydst, InputArray kernel,
Point anchor, int iterations,
int borderType, constScalar& borderValue )
{
morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType,borderValue );
}
实例:
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat image = imread("desertEagle.jpg");
namedWindow("【原图】腐蚀操作");
namedWindow("【效果图】腐蚀操作");
imshow("【原图】腐蚀操作", image);
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
Mat out;
erode(image, out, element);
imshow("【效果图】腐蚀操作", out);
waitKey(0);
return 0;
}
小结:腐蚀和膨胀都是对白色部分说的,膨胀使得图像中的高亮部分进行膨胀、扩张,膨胀后图像比原图拥有更大的高亮区域。腐蚀则恰恰相反,效果图拥有比原图更小的高亮区域。腐蚀是消除物体的边界点的过程,使剩下的物体沿其周边比原物体小一个像素的面积;膨胀运算是将与某物体接触的所有背景点合并到该物体中的过程,使物体的面积增大了相应数量的点,如果两个物体在某一点的任意方向相隔少于三个像素,它们将在该点连通起来。也可以说腐蚀可以消除图像中小的噪声区域,膨胀可以填补物体中的空洞。
开操作/闭操作。
通常情况下,含有噪声的图像二值化后,得到的边界是不平滑的,物体区域具有一些错判的孔洞,背景区域散布着一些小的噪声物体。对一个图像先进行腐蚀运算然后再膨胀的操作过程称为开运算,它可以消除细小的物体、在纤细点处分离物体、平滑较大物体的边界时不明显的改变其面积。对一个图像先膨胀然后再收缩,称为闭运算,它具有填充物体内细小的空洞、连接邻近物体、在不明显改变物体面积的情况下平滑其边界的作用。
形态学梯度、顶帽、黑帽等操作。
其中,形态学梯度(Morphological Gradient)是指膨胀图与腐蚀图的差值,这样就可以得到边缘轮廓;
顶帽运算(Top Hat)是指原图像与“开运算“结果图的差值,开运算可以放大裂缝或者局部低亮度的区域,原图减去开运算后的图,得到的图突出了比原图轮廓周围区域更明亮的区域。顶帽一般用于校正不均匀光照的影响(补充:均匀光照在从背景中提取目标的处理中扮演核心的角色)。
黑帽(Black Hat)是指”闭运算“结果图与原图像的差值。黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域。黑帽运算一般用来分离比邻近点暗一些的斑块。
opencv中的morphologyEx函数,可以实现上述操作,源码为:
void cv::morphologyEx( InputArray _src,OutputArray _dst, int op,
InputArray kernel, Pointanchor, int iterations,
int borderType, constScalar& borderValue )
{
Mat src = _src.getMat(), temp;
_dst.create(src.size(), src.type());
Mat dst = _dst.getMat();
switch( op )
{
case MORPH_ERODE:
erode( src, dst, kernel, anchor, iterations, borderType, borderValue );
break;
case MORPH_DILATE:
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
break;
case MORPH_OPEN:
erode( src, dst, kernel, anchor, iterations, borderType, borderValue );
dilate( dst, dst, kernel, anchor, iterations, borderType, borderValue );
break;
case CV_MOP_CLOSE:
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
erode( dst, dst, kernel, anchor, iterations, borderType, borderValue );
break;
case CV_MOP_GRADIENT:
erode( src, temp, kernel, anchor, iterations, borderType, borderValue );
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
dst -= temp;
break;
case CV_MOP_TOPHAT:
if( src.data != dst.data )
temp = dst;
erode( src, temp, kernel, anchor, iterations, borderType, borderValue );
dilate( temp, temp, kernel, anchor,iterations, borderType, borderValue );
dst = src - temp;
break;
case CV_MOP_BLACKHAT:
if( src.data != dst.data )
temp = dst;
dilate( src, temp, kernel, anchor, iterations, borderType, borderValue);
erode( temp, temp, kernel, anchor, iterations, borderType, borderValue);
dst = temp - src;
break;
default:
CV_Error( CV_StsBadArg, "unknown morphological operation" );
}
}
morphologyEx函数根据不同的标识符采取不同的操作,对图像腐蚀和膨胀操作进行不同的运算。
参考: