图像形态学即数学形态学(Mathematical morphology)是一门建立在格伦和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论;常见图像形态学运算:腐蚀,膨胀,开运算,闭运算,骨架抽取,极线腐蚀,击中击不中变换,顶帽变换,颗粒分析,流域变换,形态学梯度等。
腐蚀和膨胀是最基本的形态学运算。
腐蚀和膨胀是针对白色部分(高亮部分)而言的。
膨胀(dilate)是对图像高亮部分进行“领域扩张”,领域扩张,效果图拥有比原图更大的高亮区域;
腐蚀(erode)是原图中的高亮区域被蚕食,领域缩减,效果图拥有比原图更小的高亮区域。
开运算:先腐蚀再膨胀,用来消除小物体
闭运算:先膨胀再腐蚀,用于排除小型黑洞
形态学梯度:就是膨胀图与俯视图之差,用于保留物体的边缘轮廓。
函数原型:
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
#include
#include
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
#include
#include
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
#include
#include
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;
}
顶帽是原图与原图的开运算的差值图像。
开运算放大了裂缝或者局部低亮度的区域,所以,从原图中减去开运算后的图,得到的结果突出了比原图轮廓周围的区域更明亮的区域,这个操作与选择的核的大小有关。TopHat运算一般用来分离比邻近点亮一些的斑块,可以使用这个运算提取背景。
#include
#include
#include
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;
}
黑帽是闭运算结果与原图的差值图像。
黑帽运算的结果突出了比原图轮廓周围区域更暗的区域,所以黑帽运算用来分离比邻近点暗一些的斑块。
#include
#include
#include
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;
}