opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)

膨胀与腐蚀及trackbar滑动条

  • 膨胀与腐蚀
    • 膨胀
    • 腐蚀
    • opencv中的函数讲解
    • 注意膨胀与腐蚀的对象
  • 创建滑动条createTrackbar
  • 运行效果
  • 代码实现

膨胀与腐蚀

膨胀和腐蚀的主要用途:

  • 消除噪声;
  • 分割出独立的图像元素,在图像中连接相邻的元素;
  • 寻找图像中明显的极大值或极小值区;
  • 求出图像的梯度;
  • 参考链接:https://blog.csdn.net/qq_40855366/article/details/81177174
    https://jingyan.baidu.com/article/f96699bbf99d9e894f3c1b4c.html

膨胀

转载于https://blog.csdn.net/qq_40855366/article/details/81177174

  • 膨胀就是求局部最大值的操作。
  • 按数学方面来说,膨胀或者腐蚀操作就是将图像(或图像的一部分区域,我们称之为A)与核(我们称之为B)进行卷积。
  • 核可以是任何的形状和大小,它拥有一个单独定义出来的参考点,我们称其为锚点(anchorpoint)。多数情况下,核是一个小的中间带有参考点和实心正方形或者圆盘,其实,我们可以把核视为模板或者掩码。
  • 而膨胀就是求局部最大值的操作,核B与图形卷积,即计算核B覆盖的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素。这样就会使图像中的高亮区域逐渐增长。如下图所示,这就是膨胀操作的初衷。
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第1张图片
    右图比左图大一圈

腐蚀

转载于https://jingyan.baidu.com/article/f96699bbf99d9e894f3c1b4c.html
腐蚀原理:
腐蚀:局部最小值(与膨胀相反);
①定义一个卷积核B,
核可以是任何的形状和大小,且拥有一个单独定义出来的参考点-锚点(anchorpoint);
通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
②将核B与图像A进行卷积,计算核B覆盖区域的像素点最小值;
③将这个最小值赋值给参考点指定的像素;
因此,图像中的高亮区域逐渐减小。
opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第2张图片

opencv中的函数讲解

  1. OpenCV中膨胀函数-dilate()
void dilate(
InputArray src,//输入
OutputArray dst, //输出
InputArray kernel, //核大小
Point anchor=Point(-1,-1),// 锚位置,默认值(-1,-1)为中心
int iterations=1, //迭代次数,默认值1
int borderType=BORDER_CONSTANT,//图像边界像素模式,默认值BORDER_CONSTANT
const Scalar& borderValue =morphologyDefaultBorderValue()//边界值,有默认值,一般默认即可
)

使用dilate函数,一般只需要填前面的三个参数,后面的四个参数都有默认值,而且往往会结合getStructuringElement()

  1. OpenCV中腐蚀函数-erode()
void erode(
InputArray src,//输入
OutputArray dst, //输出
InputArray kernel, //核大小,当为NULL时,表示使用参考点位于中心3*3的核。一般使用函数getStructuringElement()配合使用
Point anchor=Point(-1,-1),// 锚位置,(-1,-1)为中心
int iterations=1, //迭代次数
int borderType=BORDER_CONSTANT,//图像边界像素模式
const Scalar& borderValue=morphologyDefaultBorderValue()//边界值
)

erode函数与膨胀函数类似前三个参数需要填写,后面的四个参数有默认值可根据需要填写。

  1. 结构元素
getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1));
参数:
shape:表核的形状,矩形MORPH_RECT;交叉形MORPH_CROSS;椭圆形MORPH_ELLIPSE;
ksize:核尺寸大小;
anchor:锚点的位置,锚点只影响形态学运算结果的偏移;
功能:返回指定形状和尺寸的结构元素;

注意膨胀与腐蚀的对象

  1. 此处需要明确图片中的前景像素和背景像素对应像素值,或者说要明确图片中的像素值较大的部分,因为膨胀、腐蚀的操作对象是相对于像素值较大的部分而言的,即高亮白部分而不是黑色部分,要注意下面几点。
  • 膨胀是图像中的高亮部分进行膨胀,领域扩张,效果图拥有比原图更大的高亮区域;
  • 腐蚀是图像中的高亮部分被腐蚀掉,领域缩减,效果图拥有比原图更小的高亮区域;
  1. 膨胀
  • 如下图所示对左图进行膨胀操作时,会发现白色背景区域变大,黑色区域的字变小,因为膨胀操作对应的是像素值较高的部分如白色区域,所以白色区域膨胀了,黑色区域缩小了。
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第3张图片
  • 而对下图白色为前景黑色为背景的图进行膨胀时,结果如下,同样是白色的区域变大了,黑色的区域变小了。但前景的白色字变大了,而不是像上图中的黑色字变小了
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第4张图片
  1. 对左侧图像进行腐蚀操作结果如下,像素值高的部分白色区域变小,而像素值低的部分黑色区域变大
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第5张图片
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第6张图片

创建滑动条createTrackbar

转载于:https://www.cnblogs.com/geek-hao/p/11668248.html
此链接关于createTrackbar的用法很详尽,尤其是代码部分

  1. 函数原型:
CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname,int* value, int count,TrackbarCallback onChange = 0, void* userdata = 0);
参数1:trackbarname,这个参数用来给这个滚动条取一个名字;
参数2:winname,这个参数用来指定你要吧这个滚动条用到那个窗口上;
参数3:value,这个参数用来设置滑块初始值位置,同时记录滑块以后的位置;
参数4:count,这个参数用来指定滚动条可以滚动的最大值;
参数5:onChange,这个参数可以理解为一个函数类型的变量(当然这样说感觉有点怪),用来接收回调函数函数名的,默认值为0;
参数6:userdata,这个变量这个参数是用户传给回调函数的数据,用来处理轨迹条事件,默认值为0。
  1. 回调函数的函数原型:
    void (TrackbarCallback)(int pos, void userdata);
  • 有些代码中定义回调函数时为什么必须要有上面俩参数。回调函数是一个必须依托于createTrackbar()函数而使用的函数,他不能单独拿来使用。
  • 第一个形参pos,它表示的是当前滑块所在的位置,它的值是createTrackbar()传给他的,也就是createTrackbar()形参value的值,这个传输过程是在createTrackbar()内部实现的,无需深究。
  • 然后回调函数形参userdata的值就是通过createTrackbar()的形参userdata直接得到的,所以createTrackbar()的形参userdata其实就是专门给回调函数准备的。可以传递各种类型数据如Mat,但在回调函数使用时需要转换类型如下

示例:

//TrackBar发生改变的回调函数
void onChangeTrackBar(int pos, void* userdata);

//主函数
int main()
 {
     //trackbar的值
    int posTrackBar = 0;
     //trackbar的最大值
    int maxValue = 255;
    //读入图像,以灰度图形式读入
     Mat img = imread("F:\\图片\\timg.jpg", 0);
    //新建窗口
    namedWindow("二值化");
     imshow("二值化", img);
     
    //创建trackbar,我们把img作为数据传进回调函数中
    createTrackbar("pos", "二值化", &posTrackBar, maxValue, onChangeTrackBar, &img);

    waitKey();
    return 0;
 }
// 回调函数
void onChangeTrackBar(int posTrackBar, void* img)
 {
     // 强制类型转换
    Mat src = *(Mat*)(img);
     Mat dst;
    // 二值化
    threshold(src, dst, posTrackBar, 255, 0);
     imshow("二值化", dst);
 }

运行效果

  1. 如下图所示,当膨胀的值为1时,实际在回调函数中的卷积核的大小为1*2+1即Size(3,3)大小的,因为卷积核必须是奇数,而滑动条则是由0到定义最大值的整数,所以要将其在回调函数中转化一下,这样在滑动滑块的时候可以看到一系列的变化,有利于对膨胀的理解。此处膨胀后,白色像素值大的区域变大,而黑色像素值为0的区域就变小了。
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第7张图片
    下面图片的背景及前景颜色与上方图片相反
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第8张图片
  2. 同理对图片进行腐蚀操作
  • 前景为黑色,背景为黑色时
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第9张图片

  • 前景为白色,背景为黑色时
    opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)_第10张图片

代码实现

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

Mat src, dst;
char OUTPUT_WIN[] = "output image";//定义一个输出窗口名
//int element_size = 3;//此处定义滑动条当前值,若此处使用全局变量,就无需在回调函数中定义形参,回调函数可定义为void CallBack_dilate(int , void* );
//int max_size = 21;//定义滑动条最大值
void CallBack_dilate(int pos, void* userdata);	//声明膨胀的回调函数
void CallBack_erode(int pos, void* userdata);	//声明腐蚀的回调函数
int main(){
	src = imread("G:/OpenCV/opencv笔记所用图片/wen2.png");
	if (src.empty())
	{
		cout << "could not load image..."<< endl;
		getchar();
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);//命名一个窗口显示输入图像
	imshow("input image", src);

	int element_size = 3;//此处定义滑动条当前值
	int max_size = 21;//定义滑动条最大值
	Mat strElement;
	namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);//命名一个窗口显示输出图像
	//创建膨胀滑动条
	createTrackbar("膨胀 :", OUTPUT_WIN, &element_size, max_size, CallBack_dilate);//滑动条名称,//窗口名称,//滑动条当前值,//滑动条最大值,//回调函数,//最后的用户参数默认不写(也可以传递各种类型数据如Mat,但在回调函数使用时需要转换类型)
	//创建腐蚀滑动条
	createTrackbar("腐蚀 :", OUTPUT_WIN, &element_size, max_size, CallBack_erode);

	waitKey(0);
	return 0;
}

//定义膨胀的回调函数
void CallBack_dilate(int element_size, void* strElement) {
	int s = element_size * 2 + 1;	//此处将createTrackbar传递过来的element_size值变为奇数
									//此处s必须为奇数,因为后面获取结构元素中的Size(s, s)必须是奇数
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));//此处定义的结构元素为方形,大小长s,宽s,锚点为中心
	dilate(src, dst, structureElement, Point(-1, -1), 1);//膨胀函数,对原始图像进行膨胀,核的大小为structureElement,通过调节核的大小来调节膨胀程度的大小
	//erode(src, dst, structureElement);
	imshow(OUTPUT_WIN, dst);
	return;
}

//定义腐蚀的回调函数
void CallBack_erode(int element_size, void* userdata) {
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));//此处定义的结构元素为方形,大小长s,宽s,锚点为中心
	// dilate(src, dst, structureElement, Point(-1, -1), 1);
	erode(src, dst, structureElement);//腐蚀函数,对原始图像进行腐蚀操作,此处后4个参数采用默认值
	imshow(OUTPUT_WIN, dst);
	return;
}

你可能感兴趣的:(opencv,c++)