形态学基本概念
图像形态学即数学形态学(Mathematical morphology)是一门建立在格伦和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论;常见图像形态学运算:腐蚀,膨胀,开运算,闭运算,骨架抽取,极线腐蚀,击中击不中变换,顶帽变换,颗粒分析,流域变换,形态学梯度等。
腐蚀和膨胀是最基本的形态学运算。
腐蚀和膨胀是针对白色部分(高亮部分)而言的。
膨胀(dilate)是对图像高亮部分进行“领域扩张”,领域扩张,效果图拥有比原图更大的高亮区域;
腐蚀(erode)是原图中的高亮区域被蚕食,领域缩减,效果图拥有比原图更小的高亮区域。
开运算:先腐蚀再膨胀,用来消除小物体
闭运算:先膨胀再腐蚀,用于排除小型黑洞
形态学梯度:就是膨胀图与俯视图之差,用于保留物体的边缘轮廓。
顶帽:原图像与开运算图之差,用于分离比邻近点亮一些的斑块。
黑帽:闭运算与原图像之差,用于分离比邻近点暗一些的斑块。
高级形态学变换函数:MorphologyEx
函数原型:
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() )
参数:
- src:源图像Mat对象
- dst:目标图像Mat对象
- op:操作的类型,通过源码我们得知总共有以下几种类型:
enum MorphTypes{ MORPH_ERODE = 0, //腐蚀 MORPH_DILATE = 1, //膨胀 MORPH_OPEN = 2, //开操作 MORPH_CLOSE = 3, //闭操作 MORPH_GRADIENT = 4, //梯度操作 MORPH_TOPHAT = 5, //顶帽操作 MORPH_BLACKHAT = 6, //黑帽操作 MORPH_HITMISS = 7 };
- kernel:用于膨胀操作的结构元素,如果取值为Mat(),那么默认使用一个3 x 3 的方形结构元素,可以使用getStructuringElement()来创建结构元素
- anchor:参考点,其默认值为(-1,-1)说明位于kernel的中心位置。
- borderType:边缘类型,默认为BORDER_CONSTANT。
- borderValue:边缘值,用它的默认值即可。
形态学开运算
开操作(先腐蚀后膨胀)可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。
它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。
函数使用:
morphologyEx(src, dst, MORPH_OPEN, kernel);
开运算案例:
#include<iostream> #include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using namespace cv; using namespace std; int main() { Mat img = imread("./morphologyEx.jpg"); cout << img.size() << endl; imshow("原图", img); Mat dst; //获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(10, 10)); //形态学开操作 #if 1 morphologyEx(img, dst, MORPH_OPEN, element); #else erode(img, dst, element); dilate(dst, dst, element); #endif imshow("形态学开操作", dst); waitKey(); return 0; }
注:形态学操作可使用高级函数morphologyEx。
形态学闭运算
闭操作(先膨胀后腐蚀)可以消弭狭窄的间断,消除小的孔洞。先膨胀后腐蚀的操作称之为闭操作。
它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。
函数使用:
morphologyEx(src, dst, MORPH_CLOSE, kernel);
闭运算案例:
#include<iostream> #include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using namespace cv; using namespace std; int main() { Mat img = imread("./morphologyEx.jpg"); cout << img.size() << endl; imshow("原图", img); Mat dst; //获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(10, 10)); //形态学闭操作 morphologyEx(img, dst, MORPH_CLOSE, element); imshow("形态学闭操作", dst); waitKey(); return 0; }
形态学梯度运算
形态学梯度操作能描述图像亮度变化的剧烈程度;当我们想要突出高亮区域的外围时,则可以选用形态学梯度来突出边缘,可以保留物体的边缘轮廓。
形态学梯度运算案例:
#include<iostream> #include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using namespace cv; using namespace std; int main() { Mat img = imread("./morphologyEx.jpg"); cout << img.size() << endl; imshow("原图", img); Mat dst; //获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(10, 10)); //形态学梯度运算 morphologyEx(img, dst, MORPH_GRADIENT, element); imshow("形态学梯度运算", dst); waitKey(); return 0; }
礼/顶帽(Top hat)
顶帽是原图与原图的开运算的差值图像。
开运算放大了裂缝或者局部低亮度的区域,所以,从原图中减去开运算后的图,得到的结果突出了比原图轮廓周围的区域更明亮的区域,这个操作与选择的核的大小有关。TopHat运算一般用来分离比邻近点亮一些的斑块,可以使用这个运算提取背景。
礼帽案例:
#include<iostream> #include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using namespace cv; using namespace std; int main() { Mat img = imread("./morphologyEx.jpg"); cout << img.size() << endl; imshow("原图", img); Mat dst,dst_open; // 获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(5, 5)); // 形态学礼帽 morphologyEx(img, dst_open, MORPH_OPEN, element); morphologyEx(img, dst, MORPH_TOPHAT, element); imshow("开运算", dst_open); imshow("形态学礼帽", dst); waitKey(); return 0; }
黑帽(Black hat)
黑帽是闭运算结果与原图的差值图像。
黑帽运算的结果突出了比原图轮廓周围区域更暗的区域,所以黑帽运算用来分离比邻近点暗一些的斑块。
黑帽案例:
#include<iostream> #include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using namespace cv; using namespace std; int main() { Mat img = imread("./morphologyEx.jpg"); cout << img.size() << endl; imshow("原图", img); Mat dst, dst_close; // 获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(5, 5)); // 形态学黑帽 morphologyEx(img, dst_close, MORPH_CLOSE, element); morphologyEx(img, dst, MORPH_BLACKHAT, element); imshow("闭运算", dst_close); imshow("形态学黑帽", dst); waitKey(); return 0; }