形态学处理(二):开运算、闭运算、形态学梯度、顶帽、黒帽
一、形态学高级运算原理
常用的形态学高级运算,包括开运算、闭运算,形态学梯度,顶帽运算、黒帽运算五种。
1.1 开运算(Opening Operation)
开运算(Opening Operation),其实就是先腐蚀后膨胀的过程。其数学表达式如下:
开运算可以用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。效果图是这样的:
原图 开运算
1.2 闭运算(Closing Operation)
先膨胀后腐蚀的过程称为闭运算(ClosingOperation),其数学表达式如下:
闭运算能够排除小型黑洞(黑色区域)。效果图如下所示:
原图 闭运算
1.3 形态学梯度(MorphologicalGradient)
形态学梯度(MorphologicalGradient)为膨胀图与腐蚀图之差,数学表达式如下
对二值图像进行这一操作可以将团块(blob)的边缘突出出来。我们可以用形态学梯度来保留物体的边缘轮廓,如下所示:
原图 形态学梯度运算
1.4 顶帽(Top Hat)
顶帽运算(Top Hat)又常常被译为”礼帽“运算。为原图像与上文刚刚介绍的“开运算“的结果图之差,数学表达式如下:
因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。
顶帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。
如下所示:
原图 顶帽运算
1.5 黑帽(Black Hat)
黑帽(Black Hat)运算为”闭运算“的结果图与原图像之差。数学表达式为:
黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。
所以,黑帽运算用来分离比邻近点暗一些的斑块。非常完美的轮廓效果图:
原图 黒帽运算
二、MorphologyEx()函数
2.1 Morphology()函数介绍(一般用前4个参数)
voidmorphologyEx(
InputArray src,
OutputArray dst,
int op,
InputArraykernel,
Pointanchor = Point(-1, -1),
intiterations = 1,
intborderType = BORDER_CONSTANT,
constScalar&borderValue = morphologyDefaultBorderValue());
Ø 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U,CV_16U,CV_16S, CV_32F 或CV_64F。
Ø 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
Ø 第三个参数,int类型的op,表示形态学运算的类型,可以是如下之一的标识符:
MORPH_OPEN – 开运算(Opening operation)
MORPH_CLOSE – 闭运算(Closing operation)
MORPH_GRADIENT -形态学梯度(Morphological gradient)
MORPH_TOPHAT - “顶帽”(“Top hat”)
MORPH_BLACKHAT - “黑帽”(“Black hat“)
另有CV版本的标识符也可选择,如CV_MOP_CLOSE,CV_MOP_GRADIENT,CV_MOP_TOPHAT,CV_MOP_BLACKHAT,这应该是OpenCV1.0系列版本遗留下来的标识符,和上面的“MORPH_OPEN”一样的效果。
Ø 第四个参数,InputArray类型的kernel,形态学运算的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。关于getStructuringElement我们上篇文章中讲过了,这里为了大家参阅方便,再写一遍:
其中,getStructuringElement函数的第一个参数表示内核的形状,我们可以选择如下三种形状之一:
矩形:MORPH_RECT
交叉形:MORPH_CROSS
椭圆形:MORPH_ELLIPSE
Ø 第五个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
Ø 第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
Ø 第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_CONSTANT。
Ø 第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。
2.2 Morphology()函数用法
函数Morphology()可以实现:开运算,闭运算,形态学梯度,顶帽,黑帽,腐蚀,膨胀的效果。只要改变第三个参数,就可以一次实现上述效果,示例如下所示:
MatScrImage, OutImage1, OutImage2, OutImage3, OutImage4, OutImage5, OutImage6,OutImage7, OutImage8, OutImage9;
ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");//读入图像
namedWindow("【原图】");
imshow("【原图】", ScrImage);
morphologyEx(ScrImage,OutImage1, MORPH_OPEN, getStructuringElement(MORPH_RECT,Size(15, 15)));//开操作
morphologyEx(ScrImage,OutImage2, MORPH_CLOSE, getStructuringElement(MORPH_RECT,Size(15, 15)));//闭操作
morphologyEx(ScrImage,OutImage3, MORPH_GRADIENT, getStructuringElement(MORPH_RECT,Size(15, 15)));//梯度操作
morphologyEx(ScrImage,OutImage4, MORPH_TOPHAT, getStructuringElement(MORPH_RECT,Size(15, 15)));//顶帽操作
morphologyEx(ScrImage,OutImage5, MORPH_BLACKHAT, getStructuringElement(MORPH_RECT,Size(15, 15)));//黒帽操作
morphologyEx(ScrImage,OutImage6, MORPH_ERODE, getStructuringElement(MORPH_RECT,Size(15, 15)));//腐蚀操作
morphologyEx(ScrImage,OutImage7, MORPH_DILATE, getStructuringElement(MORPH_RECT,Size(15, 15)));//膨胀操作
namedWindow("开操作");
imshow("开操作", OutImage1);
namedWindow("闭操作");
imshow("闭操作", OutImage2);
namedWindow("梯度操作");
imshow("梯度操作", OutImage3);
namedWindow("顶帽操作");
imshow("顶帽操作", OutImage4);
namedWindow("黒帽操作");
imshow("黒帽操作", OutImage5);
namedWindow("腐蚀操作");
imshow("腐蚀操作", OutImage6);
namedWindow("膨胀操作");
imshow("膨胀操作", OutImage7);
三、完整程序示例
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
#include <cstdio>
using namespacestd;
using namespacecv;
int main()
{
Mat ScrImage, ScrImgaeCopy1, OutImage, OutImage1, OutImage2,OutImage3, OutImage4, OutImage5, OutImage6, OutImage7, OutImage8, OutImage9;
ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");//读入图像
namedWindow("【原图】");
imshow("【原图】", ScrImage);
morphologyEx(ScrImage,OutImage1, MORPH_OPEN, getStructuringElement(MORPH_RECT,Size(15, 15)));//开操作
morphologyEx(ScrImage,OutImage2, MORPH_CLOSE, getStructuringElement(MORPH_RECT,Size(15, 15)));//闭操作
morphologyEx(ScrImage,OutImage3, MORPH_GRADIENT, getStructuringElement(MORPH_RECT,Size(15, 15)));//梯度操作
morphologyEx(ScrImage,OutImage4, MORPH_TOPHAT, getStructuringElement(MORPH_RECT,Size(15, 15)));//顶帽操作
morphologyEx(ScrImage,OutImage5, MORPH_BLACKHAT, getStructuringElement(MORPH_RECT,Size(15, 15)));//黒帽操作
morphologyEx(ScrImage,OutImage6, MORPH_ERODE, getStructuringElement(MORPH_RECT,Size(15, 15)));//腐蚀操作
morphologyEx(ScrImage,OutImage7, MORPH_DILATE, getStructuringElement(MORPH_RECT,Size(15, 15)));//膨胀操作
namedWindow("开操作");
imshow("开操作", OutImage1);
namedWindow("闭操作");
imshow("闭操作", OutImage2);
namedWindow("梯度操作");
imshow("梯度操作", OutImage3);
namedWindow("顶帽操作");
imshow("顶帽操作", OutImage4);
namedWindow("黒帽操作");
imshow("黒帽操作", OutImage5);
namedWindow("腐蚀操作");
imshow("腐蚀操作", OutImage6);
namedWindow("膨胀操作");
imshow("膨胀操作", OutImage7);
waitKey(0);
return NULL;
}
参考内容:
http://www.cnblogs.com/mq0036/p/5902104.html