首先感谢@浅墨_毛星云,本篇博文是小武通过学习@浅墨_毛星云的博客以及书籍《opencv3.0编程入门》整理的笔记及疑问心得,小武水平有限,欢迎交流。
@浅墨_毛星云博文:https://blog.csdn.net/poem_qianmo/article/category/1923021
数学形态学(Mathematical morphology) 是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论。其基本的运算包括:二值腐蚀和膨胀、二值开闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换、灰值腐蚀和膨胀、灰值开闭运算、灰值形态学梯度等。
最基本的形态学操作有二种,他们是:膨胀与腐蚀(Dilation与Erosion)。
膨胀与腐蚀能实现多种多样的功能,主要如下:
1、膨胀——dilate函数
函数原型:
C++: void dilate(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);
参数详解:
- 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。
- 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
- 第三个参数,InputArray类型的kernel,膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核。
我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。
其中,getStructuringElement函数的第一个参数表示内核的形状,我们可以选择如下三种形状之一:
- 矩形: MORPH_RECT
- 交叉形: MORPH_CROSS
- 椭圆形: MORPH_ELLIPSE
而getStructuringElement函数的第二和第三个参数分别是内核的尺寸以及锚点的位置。
我们一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得getStructuringElement函数的返回值。对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心。且需要注意,十字形的element形状唯一依赖于锚点的位置。而在其他情况下,锚点只是影响了形态学运算结果的偏移。
2、腐蚀——erode函数
函数原型:
C++: void erode(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);
参数解释:
//添加头文件
#include
#include
#include
#include
using namespace std;
using namespace cv;
//参数预定义
int Way_num=0;
int struct_size=1;
Mat Img_in , Img_out;
//函数声明
void callback_Way_num(int ,void*);
void callback_struct_size(int ,void*);
void process();
//主函数
int main ()
{
Img_in=imread("lenna.jpg");
imshow("【原图】",Img_in);
namedWindow("【效果图】");
createTrackbar("腐蚀/膨胀","【效果图】",&Way_num, 1 , callback_Way_num);
callback_Way_num(Way_num,0);
createTrackbar("内核尺寸","【效果图】",&struct_size, 37 , callback_struct_size);
callback_struct_size(struct_size,0);
waitKey(0);
return 0;
}
//进行自定义的腐蚀和膨胀操作
void process()
{
Mat element=getStructuringElement(MORPH_RECT,Size(struct_size*2+1,struct_size*2+1),Point(struct_size,struct_size));
//Way_num=0,进行腐蚀操作
if (Way_num==0)
erode(Img_in,Img_out,element);
else
//否则,进行膨胀
dilate(Img_in,Img_out,element);
imshow("【效果图】",Img_out);
}
//腐蚀和膨胀之间切换开关的回调函数
void callback_Way_num(int ,void*)
{
process();
}
//腐蚀和膨胀操作内核改变时的回调函数
void callback_struct_size(int ,void*)
{
process();
}
效果: