【拜小白opencv】43-形态学滤波——综合示例【腐蚀、膨胀、开运算、闭运算、顶帽、黑帽 形态学梯度、内部梯度、外部梯度、X方向梯度、Y方向梯度】
来源:互联网 发布:金星舞蹈水平 知乎 编辑:程序博客网 时间:2024/05/29 18:48
常言道“温故而知新”,写此文章就是对自己目前学习内容的小小的总结与记录。
本文力求用最简洁的语言,详细的代码将此部分内容讲解清楚,但由于博主同样是刚刚接触OpenCV,或许表达上有些瑕疵,还望读者能够指教探讨,大家共同进步。
博主机器配置为:VS2013+opencv2.4.13+Win-64bit。
若本文能给读者带来一点点启示与帮助,我就很开心了。
====================分割线====================
本次,将前几篇关于形态学滤波的一些操作,综合了一下,编写了一个程序,可以操作这几种方法。
一共实现了11种操作:腐蚀、膨胀、开运算、闭运算、顶帽、黑帽、形态学梯度(又为基本梯度)、内部梯度、外部梯度、X方向梯度、Y方向梯度。
放一张思维导图,看不清的话,右键进行保存。
首先,还是先介绍每个操作是什么。 为方便,请直接点击链接,进行相关的查看。
【腐蚀】—— 【拜小白opencv】36-形态学滤波1——腐蚀
【膨胀】—— 【拜小白opencv】37-形态学滤波2——膨胀
【开运算】—— 【拜小白opencv】38-形态学滤波3——开运算
【闭运算】—— 【拜小白opencv】39-形态学滤波4——闭运算
【顶帽】—— 【拜小白opencv】41-形态学滤波6——顶帽运算(OR礼帽运算、高帽运算)
【黑帽】—— 【拜小白opencv】42-形态学滤波7——黑帽运算
【形态学滤波】 以及内部梯度、外部梯度、X方向梯度、Y方向梯度都在这篇文章中——【拜小白opencv】40-形态学滤波5——形态学梯度(基本梯度、内部梯度、外部梯度、方向梯度)
=====================分割线===================
1-代码演示
/*功能:综合示例——形态学滤波一共包含11中操作:腐蚀、膨胀、开运算、闭运算、顶帽、黑帽形态学梯度(又为基本梯度)、内部梯度、外部梯度、X方向梯度、Y方向梯度*/#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace cv;using namespace std;#define WINDOWNAME "【形态学滤波-效果图】"//-------------------【全局变量声明部分】------------------------Mat g_srcImage; //源图像Mat g_dstImage; //得到的效果图int g_nElementShape = MORPH_RECT;//元素结构的形状int g_nStructElementSize = 3;//结构元素(内核矩阵)的尺寸int g_nMaxNum = 21; //内核最大值int g_nTypeChoice = 0; //形态学操作类型选择//-------------------【全局函数声明部分】------------------------void on_TrackbarNumChange(int, void*); //类型选择-回调函数void on_ElementSizeChange(int, void*); //内核大小变换-回调函数void ShowHelpText();//帮助文字显示void Process();//对应的形态学操作void ErodeProcess();//腐蚀操作void DilateProcess();//膨胀操作void OpenProcess();//开运算操作void CloseProcess();//闭运算操作void TopHatProcess();//顶帽操作void BlackHatProcess();//黑帽操作void GradienteProcess();//形态学梯度操作-即基本梯度void InternalGradientProcess();//内部梯度操作void ExternalGradientProcess();//外部操作void xDirectGradientProcess();//X方向梯度操作void yDirectGradientProcess();//Y方向梯度操作//--------------------------------【主函数】------------------------------int main(){//载入图像g_srcImage = imread("D:\\OutPutResult\\ImageTest\\ju.jpg");if (!g_srcImage.data){cout << "读取图片错误,请重新输入正确路径!\n";system("pause");return -1;}namedWindow("【原始图】", WINDOW_AUTOSIZE);namedWindow(WINDOWNAME, WINDOW_AUTOSIZE);imshow("【原始图】", g_srcImage);//显示原始图ShowHelpText();//创建轨迹条createTrackbar("类型选择", WINDOWNAME, &g_nTypeChoice, 10, on_TrackbarNumChange);createTrackbar("内核", WINDOWNAME, &g_nStructElementSize, g_nMaxNum, on_ElementSizeChange);//轮询获取按键信息while (1){//执行回调函数on_TrackbarNumChange(g_nTypeChoice, 0);on_ElementSizeChange(g_nStructElementSize, 0);//获取按键int c;c = waitKey(0);//按下键盘Q键或者ESC,程序退出if ((char)c == 'q' || (char)c == 27 || (char)c == 'Q')break;//按下键盘按键1,使用矩形(Rectangle)结构元素MORPH_RECT if ((char)c == 49)//键盘按键1的ASII码为49g_nElementShape = MORPH_RECT;//按下键盘按键2,使用十字形(Cross)结构元素MORPH_CROSS else if ((char)c == 50)//键盘按键2的ASII码为50g_nElementShape = MORPH_CROSS;//按下键盘按键3,使用椭圆(Elliptic)结构元素MORPH_ELLIPSEelse if ((char)c == 51)//键盘按键3的ASII码为51g_nElementShape = MORPH_ELLIPSE;}return 0;}//------------【on_TrackbarNumChange()函数】-------------void on_TrackbarNumChange(int, void*){//类型之间效果已经切换,回调函数体内需调用一次对应的操作函数,使改变后的效果立即生效并显示出来Process();}//------------【on_ElementSizeChange()函数】--------------void on_ElementSizeChange(int, void*){//内核尺寸已改变,回调函数体内需调用一次Process函数,使改变后的效果立即生效并显示出来Process();}//------------【进行对应的形态学操作】--------------void Process(){switch (g_nTypeChoice){case 0:ErodeProcess(); break;case 1:DilateProcess(); break;case 2:OpenProcess(); break;case 3:CloseProcess(); break;case 4:TopHatProcess(); break;case 5:BlackHatProcess(); break;case 6:GradienteProcess(); break;case 7:InternalGradientProcess(); break;case 8:ExternalGradientProcess(); break;case 9:xDirectGradientProcess(); break;case 10:yDirectGradientProcess(); break;}}//-----------【描述:进行腐蚀操作】-----------void ErodeProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核erode(g_srcImage, g_dstImage, element);//进行腐蚀或膨胀操作imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行膨胀操作】-----------void DilateProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核dilate(g_srcImage, g_dstImage, element);//进行膨胀操作imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行开运算操作】-----------void OpenProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);//进行开运算操作:先腐蚀后膨胀imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行闭运算操作】-----------void CloseProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);//进行闭运算操作:先膨胀再腐蚀imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行顶帽操作】-----------void TopHatProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);//进行顶帽操作:原图像与开运算结果图之差imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行黑帽操作】-----------void BlackHatProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);//进行黑帽操作:闭运算结果图与原图像之差imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行形态学梯度操作】-----------void GradienteProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_GRADIENT, element);//进行形态学梯度操作:膨胀图像与腐蚀图像的之差imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行内部梯度操作】-----------void InternalGradientProcess(){Mat erode_ouput;Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核morphologyEx(g_srcImage, erode_ouput, MORPH_ERODE, element);//进行腐蚀操作subtract(g_srcImage, erode_ouput, g_dstImage, Mat());//计算内部梯度:原图像减去腐蚀之后的图像imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行外部梯度操作】-----------void ExternalGradientProcess(){Mat dilate_output;Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核morphologyEx(g_srcImage, dilate_output, MORPH_DILATE, element);//进行膨胀操作subtract(dilate_output, g_srcImage, g_dstImage, Mat());//计算外部梯度:膨胀后的图像减去原图像imshow(WINDOWNAME, g_dstImage);//显示效果图}//-----------【描述:进行X方向梯度操作】-----------void xDirectGradientProcess(){if (g_nStructElementSize == 0){imshow(WINDOWNAME, g_srcImage);//显示原图}else{Mat hse = getStructuringElement(g_nElementShape, Size(g_srcImage.cols / g_nStructElementSize, 1));Mat erode_direct, dilate_direct;erode(g_srcImage, erode_direct, hse);dilate(g_srcImage, dilate_direct, hse);subtract(dilate_direct, erode_direct, g_dstImage, Mat()); // X 方向梯度:膨胀与腐蚀之后得到图像求差值 imshow(WINDOWNAME, g_dstImage);//显示效果图}}//-----------【描述:进行Y方向梯度操作】-----------void yDirectGradientProcess(){if (g_nStructElementSize == 0){imshow(WINDOWNAME, g_srcImage);//显示原图}else{Mat vse = getStructuringElement(g_nElementShape, Size(1, g_srcImage.rows / g_nStructElementSize));Mat erode_direct, dilate_direct;erode(g_srcImage, erode_direct, vse);dilate(g_srcImage, dilate_direct, vse);subtract(dilate_direct, erode_direct, g_dstImage, Mat()); // Y 方向梯度:膨胀与腐蚀之后得到图像求差值 imshow(WINDOWNAME, g_dstImage);//显示效果图}}//------------------【程序一些提示操作信息】-----------------void ShowHelpText(){cout << "-----------------------------------------------------------" << endl;cout << "\t请调整滚动条观察效果\n" << endl;cout << "\t按键操作说明:" << endl;cout << "\t\t键盘按键【Esc】或者【Q】-退出程序" << endl;cout << "\t\t键盘按键【1】--使用矩形<Rectangle>结构内核" << endl;cout << "\t\t键盘按键【2】--使用十字形<Cross-shaped>结构内核" << endl;cout << "\t\t键盘按键【3】--使用椭圆<Elliptic>结构内核" << endl;cout << "-----------------------------------------------------------" << endl;cout << "\t类型选择说明:" << endl;cout << "\t\t0——腐蚀" << endl;cout << "\t\t1——膨胀" << endl;cout << "\t\t2——开运算" << endl;cout << "\t\t3——闭运算" << endl;cout << "\t\t4——顶帽操作" << endl;cout << "\t\t5——黑帽操作" << endl;cout << "\t\t6——形态学梯度(基本梯度)" << endl;cout << "\t\t7——内部梯度" << endl;cout << "\t\t8——外部梯度" << endl;cout << "\t\t9——X方向梯度" << endl;cout << "\t\t10——Y方向梯度" << endl;}
=====================分割线====================
2-显示结果
【原图像】
【0-腐蚀结果-见下图】
【1-膨胀结果-见下图】
【2-开运算结果-见下图】
【3-闭运算结果-见下图】
【4-顶帽结果-见下图】
【5-黑帽结果-见下图】
【6-形态学梯度结果-见下图】
【7-内部梯度结果-见下图】
【8-外部结果-见下图】
【9-X方向梯度结果-见下图】
【10-Y方向梯度结果-见下图】
======================分割线====================
3-程序解释
1)窗口【形态学滤波-效果图】中写的内核,并不是真正内核的大小,而应该是Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1)。显示是仅是g_nStructElementSize 的值,要注意区分。
2)可以在窗口【形态学滤波-效果图】上,通过按数字【1】、【2】、【3】来改变内核的形状,有三种,矩形、十字形、椭圆形。
=====================END=======================
- 【拜小白opencv】43-形态学滤波——综合示例【腐蚀、膨胀、开运算、闭运算、顶帽、黑帽 形态学梯度、内部梯度、外部梯度、X方向梯度、Y方向梯度】
- 【拜小白opencv】40-形态学滤波5——形态学梯度(基本梯度、内部梯度、外部梯度、方向梯度)
- 形态学处理:膨胀、腐蚀、开运算、闭运算、形态学梯度、顶帽、黑帽
- opencv学习形态学滤波:开运算,闭运算,形态学梯度,顶帽,黑帽
- 图像形态学概要-腐蚀、膨胀、开运算、闭运算、形态学梯度(形态学边缘提取)、顶帽操作、黑帽操作
- 【OpenCV3图像处理】形态学 --- 膨胀、腐蚀、开运算 闭运算、形态学梯度、顶帽运算、黑帽运算
- 形态学图像处理—开运算、闭运算、形态学梯度、顶帽、黑帽
- OpenCV之形态学(开运算、闭运算、形态学梯度、顶帽、黑帽)
- 6.4OpenCV形态学图像处理:开运算、闭运算、形态学梯度、顶帽、黑帽
- OpenCV 形态学图像处理 开运算、闭运算、形态学梯度、顶帽、黑帽合辑(轨迹条控制)综合示例
- opencv中的开运算,闭运算,形态学梯度,顶帽和黑帽
- Opencv学习之开运算、闭运算、形态学梯度、顶帽、黑帽
- opencv中的开运算,闭运算,形态学梯度,顶帽和黑帽
- 【OpenCV入门教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽
- openCV 形态学 腐蚀、膨胀、开操作和比操作、形态梯度 、顶帽、黑帽
- 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑
- 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑
- 【OpenCV入门教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑
- 用java以正确的姿势刷CSP
- python入门(2)
- C++关键字之explicit
- 真实实践中的MeritMS与Project Wise的校审流程对比
- 超详细的系统时钟和定时器原理解析
- 【拜小白opencv】43-形态学滤波——综合示例【腐蚀、膨胀、开运算、闭运算、顶帽、黑帽 形态学梯度、内部梯度、外部梯度、X方向梯度、Y方向梯度】
- Bzoj3998 弦论
- JVM--详解类加载机制
- Android混淆机制
- 返回栈上的对象、对象的引用及各构造器发生的时机
- 自顶向下,逐步求精----计算机哲学
- week13-leetcode #300-Longest-Increasing-Subsequence
- java中将Oracle数据局中blob型数据转换为byte型的两种方法
- vi命令