**
前言
**
形态学较之前面的,简单多了。而且,滤波后的结果很形象。
**
膨胀和腐蚀
**
数学形态学是一门建立在格论和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论。基本运算包括:二值开闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、顶帽变换、颗粒分析、流域变换、灰值腐蚀与膨胀、灰值开闭运算、灰值形态学梯度等。
形态学操作就是基于形状的一系列图像处理操作。Opencv为进行图像的形态学变换提供了快捷、方便的函数。最基本的操作就是膨胀dilate和腐蚀erode。
他们的功能如下:
- 消除噪声
- 分割isolate出独立的图像元素,在图像中连接join相邻的元素
- 寻找图像中的明显的极大值区域或极小值区域
- 求出图像的梯度
膨胀
膨胀dilate就是求局部最大值的操作。从数学角度说,膨胀或腐蚀操作就是将图像(或图像的一部分区域,称为A)与核B进行卷积。
核B与图形做卷积,计算核B覆盖区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素。这样图像中的高亮的区域会逐渐增长。
腐蚀
类似膨胀,只不过是求区域局部最小值。
下面使用十字CROSS来进行膨胀腐蚀:
#include<iostream>
#include<opencv2/opencv.hpp>
#include<cmath>
using namespace std;
using namespace cv;
//使用createTrackbar创建滑动按钮,动态调节腐蚀参数
void callback_demo(int, void*);
int elementSize = 1, maxSize = 10;
string windowName = "dilate img";
Mat src, dst;
int main() {
src = imread("E:/File/fusionImage2.bmp");
if (!src.data) {
cout << "cannot load image...";
return -1;
}
imshow("src img", src);
/*
//矩形: MORPH_RECT 交叉形: MORPH_CROSS 椭圆形: MORPH_ELLIPSE
Mat structureElement = getStructuringElement(MORPH_RECT, Size(3, 3));//设置膨胀、腐蚀的核为矩形,大小3*3
dilate(src, dst, structureElement);//膨胀
//erode(dst, dst, structureElement);//先膨胀后腐蚀
imshow("dilate img", dst);
Mat dst2;
erode(src, dst2, structureElement);//腐蚀
imshow("erode img", dst2);
*/
namedWindow(windowName, WINDOW_AUTOSIZE);
createTrackbar("element size", windowName, &elementSize, maxSize,callback_demo);
callback_demo(0, 0);
waitKey(0);
}
void callback_demo(int, void*) {
cout << "element size : " << elementSize << endl;
int s = elementSize * 2 + 1;
Mat structureElement = getStructuringElement(MORPH_CROSS, Size(s, s));
//dilate(src, dst, structureElement);
erode(src,dst,structureElement);
imshow(windowName, dst);
return;
}
原图:
膨胀后,可以看到白色的CROSS:
腐蚀后,黑色的更明显:
**
开闭运算等
**
开运算
先腐蚀后膨胀。可以消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积。
闭运算
先膨胀后腐蚀。可以排除小型黑色区域。
形态学梯度
膨胀图像与腐蚀图像的差。对二值图像进行这一操作可以把团块blob的边缘凸显出来。所以,使用形态学梯度可以用来保留物体的边缘轮廓。
顶帽
源图像与开运算结果之差。因为开运算放大了裂缝或者局部低亮度区域。因此,从原图中减去开运算后,就得到凸显了比原图轮廓周围区域更明亮的区域的图像。这一操作与选择的核的大小有关。
在微笑物品比较有规律的情况下,可以用顶帽运算进行背景提取。
黑帽
闭运算的结果与源图像之差。
黑帽运算后的效果图突出了比原图轮廓周围区域更暗的区域,这操作也与核的大小有关。所以,黑帽是用来分离比邻近点暗一些的斑块。
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
string windowName = "open img";
Mat src, dst;
int main() {
src = imread("E:/File/ziwen.png");
if (!src.data) {
cout << "cannot load image...";
return -1;
}
resize(src, src, Size(300, 300));
imshow("src img", src);
Mat kernel = getStructuringElement(MORPH_RECT, Size(7, 7));
morphologyEx(src, dst, MORPH_OPEN, kernel);
//namedWindow(windowName, WINDOW_AUTOSIZE);
imshow(windowName, dst);
morphologyEx(src, dst, MORPH_CLOSE, kernel);
imshow("close img", dst);
morphologyEx(src, dst, MORPH_GRADIENT, kernel);
imshow("gradient img", dst);
morphologyEx(src, dst, MORPH_TOPHAT, kernel);
imshow("tophat img", dst);
morphologyEx(src, dst, MORPH_BLACKHAT, kernel);
imshow("black img", dst);
waitKey(0);
destroyAllWindows();
}
/*
MORPH_OPEN(开) --- 先腐蚀后膨胀
MORPH_CLOSE(闭) ---- 先膨胀后腐蚀
MORPH_GRADIENT(梯度) ------ 膨胀减去腐蚀,又称为基本梯度(包括内部梯度、方向梯度)
MORPH_TOPHAT(顶帽) ---- 原图像减去开操作图像
MORPH_BLACKHAT(黑帽) ---- 闭操作减去原图像
*/
参考:《Opencv3编程入门》