Mathematical Morphology是法国和德国的科学家在研究岩石结构时建立的一门学科,形态学的用途主要是获取物体拓扑和结构信息,它通过物体和结构元素相互作用的某些运算,得到物体更本质的形态。这种方法被应用到图像上,图像形态学操作主要有腐蚀、膨胀、开、闭、击中击不中、细化、粗化、骨架、突壳、裁剪、形态学重建等等。
包含属于的关系应该都很清楚,就说一下击中和击不中:
图1 击中 |
图2 不击中 |
把结构元素B平移a后得到Ba,若Ba包含于X,我们记下这个a点,所有满足上述条件的a点组成的集合称做X被B腐蚀(Erosion)的结果。用公式表示为:E(X)={a| Ba X}=X B,如下图所示:(腐蚀的方法是,拿B的中心点和X上的点一个一个地对比,如果B上的所有点都在X的范围内,则该点保留,否则将该点去掉)
图3 腐蚀的示意图
注意:上面的B是对称的,即B的对称集Bv=B,所以X被B腐蚀的结果和X被Bv腐蚀的结果是一样的。如果B不是对称的,就会发现X被B腐蚀的结果和X被 Bv腐蚀的结果不同。
图4 结构元素非对称时,腐蚀的结果不同
函数及测试代码:
C版本的函数:
void cvErode(//腐蚀
IplImage* src,
IplImage* dst,
IplConvKernel* B = NULL, //B即核
int iterations = 1 //如名,迭代次数
);
C++版本函数:
void erode( InputArray src, OutputArray dst, //输入输出矩阵
InputArray kernel, //输入核,默认3x3矩阵( If element=Mat() , a 3 x 3 rectangular structuring element is used.),如需特别指定,需使用Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
Point anchor=Point(-1,-1), // anchor=Point(-1,-1)表示定点设为核中心。
int iterations=1, //迭代次数
int borderType=BORDER_CONSTANT, //Pixel extrapolation method,也就是边界类型
const Scalar& borderValue=morphologyDefaultBorderValue() ); //Border value in case of a constant border,边界值
erode(image,eroded,Mat());//默认3*3核,默认迭代一次
Mat element(7,7,CV_8U,Scalar(1));
erode(image,eroded,element);//7*7的核
erode(image,eroded,Mat(),Point(-1,-1),3);//默认核迭代三次
2、膨胀
膨胀(dilation)可以看做是腐蚀的对偶运算,其定义是:把结构元素B平移a后得到Ba,若Ba击中X,我们记下这个a点。所有满足上述条件的a点组成的集合称做X被B膨胀的结果。用公式表示为:D(X)={a | Ba↑X}=X B。膨胀的方法是,拿B的中心点和X上的点及X周围的点一个一个地对,如果B上有一个点落在X的范围内,则该点就为黑。
图5 膨胀的示意图
两种膨胀函数代码:
void cvDilate(//膨胀
IplImage* src,
IplImage* dst,
IplConvKernel* B = NULL,
int iterations = 1
);
dilate( InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1), int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue() );
dilate(image,dilated,Mat());
3、开运算 和 闭运算
先腐蚀后膨胀称为开(open),即OPEN(X)=D(E(X))。
先膨胀后腐蚀称为闭(close),即CLOSE(X)=E(D(X))。
开运算的一般会平滑物体的轮廓,断开较窄的狭颈,并消除细的突出物和一些孤立点。闭操作也会平滑轮廓的一部分,但与开操作相反,通常会弥合较窄的间断和细长的沟壑,消除小的孔洞,填补轮廓线中的断裂。
下面这幅图是《数字图像处理》这本书上的配图,讲的非常好,一目了然:
注意:如果B是非对称的,进行开运算时要用B的对称集Bv膨胀,否则,开运算的结果和原图相比要发生平移。进行闭运算时也要用B的对称集Bv膨胀。
图6 用B膨胀后,结果向左平移了 图7 用Bv膨胀后位置不变
void morphologyEx( InputArray src, OutputArray dst,
int op, InputArray kernel,
Point anchor=Point(-1,-1), int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue() );
morphologyEx(image,opened,MORPH_OPEN,element5);//开运算
morphologyEx(image,closed,MORPH_CLOSE,element5);//闭运算
morphologyEx(image,image,MORPH_OPEN,element5);
morphologyEx(image,image,MORPH_CLOSE,element5);//in-place,先开后闭操作
morphologyEx(image,image,MORPH_CLOSE,element5);
morphologyEx(image,image,MORPH_OPEN,element5);//先闭后开
不断更新中……