《OpenCV3编程入门》学习笔记6 图像处理(三)形态学滤波(1):腐蚀与膨胀
第6章 图像处理
6.3 形态学滤波(1):腐蚀与膨胀
6.3.1 形态学概述
1.数学形态学(Mathematical morphology):建立在格论和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论。
2.基本运算:二值腐蚀和膨胀、二值开闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换、灰值腐蚀和膨胀、灰值开闭运算、灰值形态学梯度等
3.基本形态学操作:膨胀(dilate)、腐蚀(erode)
6.3.2 膨胀
1.求局部最大值的操作,数学角度:将图像与核进行卷积,即计算核覆盖区域的像素点最大值,并把最大值赋值给参考点指定像素,这样就会使图像中高亮区域逐渐增长。
2.核:带有一个参考点(锚点,anchor point),任意形状大小的区域。
3.膨胀数学表达式:
4.封装函数:dilate函数
5.函数原型:
void dilate(InputArray src,OutputArray dst,InputArray kernel,Point anchor=Point(-1,-1),int iteration=1,int borderType=BORDER_CONSTANT,const Scaler& borderValue=morphologyDefaultBorderValue());
6.参数说明:
(1)输入图像
(2)目标图像
(3)膨胀操作的核,为NULL时表示使用参考点位于中心3*3的核,常使用getStructuringElement返回指定形状和大小的结构元素
1)形状:矩型:MORPH_RECT,交叉型:MORPH_CROSS,椭圆形:MORPH_ELLIPSE
2)内核尺寸
3)锚点位置
4)调用示例:
Int g_nStructElementSize = 3;
Mat element = getStructuringElement(MORPH_RECT, Size(2*g_nStructuringElement+1, 2*g_nStructElementSize+1), Point(g_nStructElementSize,g_nStructElementSize ));
(4)锚的位置,默认(-1,-1)表示位于中心
(5)迭代使用dilate()函数的次数,默认1
(6)用于推断图像外部像素的某种边界模式,默认值BORDER_DFALUT
(7)当边界为常数时的边界值,默认值morphologyDefalutBorderValue()
6.3.3 腐蚀
1.求局部最小值的操作,将图像与核进行卷积,即计算核覆盖区域的像素点最小值,并赋值给参考点指定的像素,这样就会使图像中高亮区域逐渐增长。
2.腐蚀的数学表达式:
3.封装函数:erode()函数
4.函数原型:
void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& broderValue=morphologyDefalutBorderValue());
5.参数说明:
(1)输入图像
(2)目标图像
(3)腐蚀操作的核,为NULL时表示使用参考点位于中心3*3的核,常使用getStructuringElement返回指定形状和大小的结构元素
(4)锚的位置,默认(-1,-1)表示位于中心
(5)迭代使用erode()函数的次数,默认1
(6)用于推断图像外部像素的某种边界模式,默认值BORDER_DFALUT
(7)当边界为常数时的边界值,默认值morphologyDefalutBorderValue()
6.3.4 综合示例:腐蚀与膨胀
//滑动条1用于腐蚀与膨胀之间切换
//滑动条2用于调节内核尺寸
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//全局变量
Mat g_srcImage, g_dstImage;
int g_nTrackbarNumber = 0;//0表示腐蚀erode,1表示膨胀dilate
int g_nStructElementSize = 3;//结构元素(内核矩阵)的尺寸
//全局函数
void Process(); //膨胀和腐蚀的处理函数
void on_TrackbarNumChange(int, void*);//腐蚀和膨胀操作之间切换开关的回调函数
void on_ElementSizeChange(int, void*);//腐蚀和膨胀操作内核改变时的回调函数
int main()
{
//改变console颜色
system("color 5E");
//载入原图
g_srcImage = imread("love.jpg");
if (!g_srcImage.data)
{
printf("载入源图像错误~!\n");
return false;
}
//显示原图
namedWindow("【原始图】");
imshow("【原始图】", g_srcImage);
//创建效果图窗口
namedWindow("【效果图】");
//创建轨迹条
createTrackbar("腐蚀/膨胀", "【效果图】", &g_nTrackbarNumber, 1, on_TrackbarNumChange);
createTrackbar("内核尺寸", "【效果图】", &g_nStructElementSize, 21, on_ElementSizeChange);
on_TrackbarNumChange(g_nTrackbarNumber, 0);
waitKey(0);
return 0;
}
//进行自定义的腐蚀和膨胀操作
void Process()
{
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
//进行腐蚀或膨胀操作
if (g_nTrackbarNumber == 0)
{
erode(g_srcImage, g_dstImage, element);
}
else
{
dilate(g_srcImage, g_dstImage, element);
}
//显示效果图
imshow("【效果图】", g_dstImage);
}
//腐蚀和膨胀操作之间切换开关的回调函数
void on_TrackbarNumChange(int, void*)
{
//腐蚀和膨胀之间效果已经切换,回调函数体内需调用一次Process函数,使改变后的效果立即生效并显示出来
Process();
}
//腐蚀和膨胀操作内核改变时的回调函数
void on_ElementSizeChange(int, void*)
{
//内核尺寸已改变,回调函数体内需调用一次Process函数,使改变后的效果立即生效并显示出来
Process();
}
运行效果: