膨胀和腐蚀运算的问题:

边缘形状发生了变化,膨胀发生了扩张,腐蚀发生了收缩
目标物体变形,对识别时的特征提取会造成影响

解决方法:

开操作:


B对A的开操作就是先B对A腐蚀,紧接着用B对结果进行膨胀

先腐蚀再膨胀的结果并不是恢复原状,而是会消除黏连部分,同时不影响其他部分的形状.
平滑物体的轮廓,断开较窄的狭颈并消除较细的突出。
效果:

闭操作:


B对A的闭操作就是先B对A膨胀,紧接着用B对结果进行腐蚀

先膨胀再腐蚀的结果并不是恢复原状,而是填充小的裂缝、孔隙,且不影响形状.
平滑物体的轮廓,弥合较窄的间断和细小的沟壑,消除小的孔洞,填充轮廓中的断痕。
效果:

更加详细的过程如下:

除了开闭运算,黑帽顶帽运算也是形态学操作比较重要的操作。

顶帽变换:原图-灰度开运算(灰度腐蚀+灰度膨胀)

效果:
1、保留比结构元素小的部分
2、保留比周围环境亮的像素

底帽变换:灰度闭运算(灰度膨胀+灰度腐蚀)-原图 效果:

1、保留比结构元素小的部分
2、保留比周围环境暗的像素

解释:
顶帽处理使背景变得趋于一致了,前景和背景的对比度加深了
这是因为,在顶帽处理中当结构元素比前景目标物的大小
大的时候,腐蚀的步骤会选择周围比较暗的值代替比较亮的值
所以背景变暗了,同时前景被去掉了。再用原图和结果相减,就可以把背景去掉,把开运算中去掉的前景给保留下来

代码实现

#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>using namespace cv;
using namespace std;//*--------------------------【练习】形态学操作morphology大练习------------------------------------*/
//请调整滚动条观察图像效果
//按键操作说明 :
//键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环
//键盘按键【1】- 使用椭圆结构元素
//键盘按键【2】- 使用矩形结构元素
//键盘按键【3】- 使用十字形结构元素
Mat g_secImage, g_dstImage; //原图和效果图
int g_nElementShape = MORPH_RECT;  //初始化元素结构形状//变量接受的Trackbar值
int  g_nMaxIterationMun = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 0;//*--------------------------【全局函数声明】-----------------------------------*/
static void on_OpenClose(int, void*);       //回调函数
static void on_ErodeDilate(int, void*);     //回调函数
static void on_TopBlakHat(int, void*);      //回调函数
void ShowHelpText1();
void ShowHelpText2();
int main()
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);     //字体为绿色//载入原图g_secImage = imread("D:\\opencv_picture_test\\形态学操作\\黑白.jpg");//判断图像是否加载成功if (g_secImage.empty()){cout << "图像加载失败!" << endl;return -1;}elsecout << "图像加载成功!" << endl << endl;//显示原图像namedWindow("原图像", WINDOW_NORMAL);     //定义窗口显示属性imshow("原图像", g_secImage);//创建三个窗口namedWindow("【开运算/闭运算】", WINDOW_NORMAL);    namedWindow("【腐蚀/膨胀】", WINDOW_NORMAL);namedWindow("【顶帽/黑帽】", WINDOW_NORMAL);//参数赋值g_nOpenCloseNum = 9;g_nErodeDilateNum =9;g_nTopBlackHatNum =2;//分别为三个窗口建立滑动条createTrackbar("迭代值", "【开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationMun*2+1,on_OpenClose);createTrackbar("迭代值", "【腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationMun * 2 + 1, on_ErodeDilate);createTrackbar("迭代值", "【顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationMun * 2 + 1, on_TopBlakHat);//show帮助信息ShowHelpText1();//轮询获取按键信息while (1){int c;//执行回调函数on_OpenClose(g_nOpenCloseNum,0);on_ErodeDilate(g_nErodeDilateNum,0);on_TopBlakHat(g_nTopBlackHatNum,0);//获取按键c = waitKey(0);//按下按键ESC程序退出if ((char)c == 27){break;}//按键1,使用椭圆结构元素if ((char)c == 49){g_nElementShape = MORPH_ELLIPSE;}//按键2,使用矩形结构元素else if ((char)c == 50){g_nElementShape = MORPH_RECT;}//按键3,使用十字形结构元素else if ((char)c == 51){g_nElementShape = MORPH_CROSS;}//按键空格,换一种结构元素else if ((char)c == ' '){g_nElementShape = (g_nElementShape+1)%3;}}
}
//*--------------------------【回调函数】-----------------------------------*/static void on_OpenClose(int, void*)
{//偏移量定义int offset = g_nOpenCloseNum - g_nMaxIterationMun; //偏移量int Abs_offset = offset > 0 ? offset : -offset;    //偏移量的绝对值//自定义核Mat element = getStructuringElement(g_nElementShape,Size(Abs_offset*2+1, Abs_offset*2+1),Point(Abs_offset, Abs_offset));  //返回的是内核矩阵//进行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_OPEN, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_CLOSE, element);}//显示效果图imshow("【开运算/闭运算】", g_dstImage);
}
static void on_ErodeDilate(int, void*)
{//偏移量定义int offset = g_nErodeDilateNum - g_nMaxIterationMun;   //偏移量int Abs_offset = offset > 0 ? offset : -offset;    //偏移量的绝对值//自定义核Mat element = getStructuringElement(g_nElementShape, Size(Abs_offset * 2 + 1, Abs_offset * 2 + 1), Point(Abs_offset, Abs_offset));    //返回的是内核矩阵//进行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_ERODE, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_DILATE, element);}//显示效果图imshow("【腐蚀/膨胀】", g_dstImage);
}
static void on_TopBlakHat(int, void*)
{//偏移量定义int offset = g_nTopBlackHatNum - g_nMaxIterationMun;   //偏移量int Abs_offset = offset > 0 ? offset : -offset;    //偏移量的绝对值//自定义核Mat element = getStructuringElement(g_nElementShape, Size(Abs_offset * 2 + 1, Abs_offset * 2 + 1), Point(Abs_offset, Abs_offset));    //返回的是内核矩阵//进行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_TOPHAT, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_BLACKHAT, element);}//显示效果图imshow("【顶帽/黑帽】", g_dstImage);
}//-----------------------------------【ShowHelpText( )函数】-----------------------------
//          描述:输出一些帮助信息//关于morphologyEx参数的问题://MORPH_BLACKHAT:黑帽运算//MORPH_TOPHAT:顶帽运算//MORPH_CLOSE:闭运算//MORPH_OPEN:开运算//MORPH_GRADIENT:形态学梯度//MORPH_ERODE:腐蚀运算//MORPH_DILATE:膨胀运算//关于getStructuringElement参数的问题://MORPH_RECT:矩形内核//MORPH_CROSS:交叉型内核//MORPH_ELLIPSE:椭圆形矩阵
//请调整滚动条观察图像效果
//按键操作说明 :
//键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环
//键盘按键【1】- 使用椭圆结构元素
//键盘按键【2】- 使用矩形结构元素
//键盘按键【3】- 使用十字形结构元素
//----------------------------------------------------------------------------------------------
void ShowHelpText1()
{//输出一些帮助信息printf("\n\n\n请调整滚动条观察图像效果\n");printf("\n\n\t按键操作说明\n");printf("\n\n\t键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环\n");printf("\n\n\t键盘按键【1】- 使用椭圆结构元素\n");printf("\n\n\t键盘按键【2】- 使用矩形结构元素\n");printf("\n\n\t键盘按键【3】- 使用十字形结构元素\n");
}
void ShowHelpText2()
{//输出一些帮助信息printf("\n\n\n\morphologyEx 参数有以下几种类型\n");printf("\n\n\tMORPH_BLACKHAT:黑帽运算\n");printf("\n\n\tMORPH_TOPHAT:顶帽运算\n");printf("\n\n\tMORPH_CLOSE:闭运算\n");printf("\n\n\tMORPH_OPEN:开运算\n");printf("\n\n\t//MORPH_GRADIENT:形态学梯度\n");printf("\n\n\tMORPH_ERODE:腐蚀运算\n");printf("\n\n\tMORPH_DILATE:膨胀运算\n");printf("\n\n\n\getStructuringElement参数的问题:\n");printf("\n\n\tMORPH_RECT:矩形内核\n");printf("\n\n\tMORPH_CROSS:交叉型内核\n");printf("\n\n\tMORPH_ELLIPSE:椭圆形矩阵\n");
}

代码实现效果:

代码解释

调用opencv库函数morphologyEx,通过调整参数就可以实现不同的形态学操作。
其中回调函数中要求得变量:偏移量(当前迭代值和预置最大迭代值之差),用它的正负来判断是进行哪种对偶操作。用它的绝对值来决定矩阵核的大小(边长为奇数),以及结构元素锚点的位置。
另外需要注意:十字形的element形状唯一依赖于锚点的位置。
而在其他情况下,锚点只是影响形态学运算结果的偏移。

相关链接:[https://www.cnblogs.com/zsb517/archive/2012/06/08/2541193.html(https://www.cnblogs.com/zsb517/archive/2012/06/08/2541193.html)

形态学操作——开闭运算、顶帽底(黑)帽变换相关推荐

  1. OpenCV_05 形态学操作:连通性+腐蚀和膨胀+开闭运算+礼帽和黑帽

    1 连通性 在图像中,最小的单位是像素,每个像素周围有8个邻接像素,常见的邻接关系有3种:4邻接.8邻接和D邻接.分别如下图所示: 4邻接:像素p(x,y)的4邻域是:(x+1,y):(x-1,y): ...

  2. 开运算和闭运算_OpenCV计算机视觉学习(5)——形态学处理(腐蚀膨胀,开闭运算,礼帽黑帽,边缘检测)...

    Fly-AI竞赛服务平台 flyai.com 在开始学习之前推荐大家可以多在FlyAI竞赛服务平台多参加训练和竞赛,以此来提升自己的能力.FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站 ...

  3. C++ OpenCV形态学操作--开闭操作,形态学梯度,顶帽,黑帽

    https://my.oschina.net/u/4582134/blog/4582844

  4. [图像形态学操作]——腐蚀和膨胀、开闭运算、黑帽礼帽

    形态学转换是基于图像形状的一些简单操作,它通常在二进制图像上执行.腐蚀和膨胀是两个基本的形态学运算符.然后它的变体形式如:开运算.闭运算.礼帽黑帽等. 一.连通性 在图像学当中,图像的最小单位是像素, ...

  5. OpenCV与图像处理学习六——图像形态学操作:腐蚀、膨胀、开、闭运算、形态学梯度、顶帽和黑帽

    OpenCV与图像处理学习六--图像形态学操作:腐蚀.膨胀.开.闭运算.形态学梯度.顶帽和黑帽 四.图像形态学操作 4.1 腐蚀和膨胀 4.1.1 图像腐蚀 4.1.2 图像膨胀 4.2 开运算与闭运 ...

  6. opencv 实现图像形态学操作 膨胀和腐蚀 开闭运算 形态学梯度 顶帽和黑帽

    图像膨胀和腐蚀 图解 原理及python实现 更多内容:图像膨胀和腐蚀原理及python实现 opencv中膨胀和腐蚀函数 dilation = cv.dilate(img, kernel) # 膨胀 ...

  7. 形态学操作之腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽和黑帽

    1.腐蚀和膨胀 图像的腐蚀和膨胀实际上是用某种形状的窗去遍历图像中的每一个像素,并用这个形状中的最大值或最小值做为锚点的值.若取的是最小值,则是腐蚀操作,若取的是最大值,则是膨胀操作.这里某种形状可以 ...

  8. OpenCV 形态学操作之腐蚀与膨胀,开运算与闭运算,顶帽与黑帽,图像梯度运算相关知识点回顾

    Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧.本篇博客是这个系列的第 45 篇. 该系列文章导航参考:https://blog.csdn.net/hihell/categ ...

  9. 《OpenCV3编程入门》学习笔记6 图像处理(四)形态学滤波(2):开运算、闭运算、形态学梯度、顶帽、黑帽

    6.4 形态学滤波(2):开运算.闭运算.形态学梯度.顶帽.黑帽 高级形态学变换,基于腐蚀与膨胀,利用morphologyEx函数实现 6.4.1 开运算 1.腐蚀后膨胀的过程,数学表达式:dst=o ...

最新文章

  1. 深度学习NN、CNN、RNN、和DNN你了解吗?
  2. Gartner预计2018年全球人工智能商业价值将达到1.2万亿美元
  3. data.frame类型数据如何将第一列值替换为行号
  4. (专题四)01 二维曲线
  5. android程序数据迁移sd,如何迁移安卓手机及SD卡的数据?方法很简单!
  6. 请问我应该怎么做,才能让前端的基础打牢固?
  7. 大学数学实验习题--统计推断 03(附答案)
  8. Ubuntu 手动更新firefox的flash插件
  9. 软件工程毕设项目 - 基于SSM的毕业设计管理系统(含源码+论文)
  10. 思科交换机配置命令大全
  11. 100首英文经典歌曲
  12. C# 方法练习-制作简易飞行棋游戏
  13. 99%的程序员都不明白:弱者和强者的唯一区别
  14. 李国庆:建议被降级降薪员工主动辞职,网友炸了
  15. 基于matlab数字基带传输系统,通信原理基于MATLAB Simulink 基带传输系统仿真实现...
  16. 常数和基本初等函数导数公式推导
  17. ChatGPT不到1分钟生成全部代码,你就说慌不慌吧?
  18. Extreme Table简介及使用
  19. 跨境电商如何降低商品退货率
  20. python语言是多模型语言-Python的语言特点

热门文章

  1. 【前端面试题】2021/3/12挺经典的面试题,这个经历很深刻。
  2. Java实现qq截图工具
  3. uniapp踩坑指南之坑多到写不完
  4. ThinkPHP 5.0.x、5.1.x、5.2.x 全版本远程命令执行漏洞
  5. 修改mysql 外删除用户_mysql添加用户、删除用户、授权、修改密码等
  6. Only digits (0-9) can be put inside [] in the path string: formData.XXX
  7. 函数的自执行,变量提升和函数提升
  8. CSS盒子模型之详解
  9. 靠谱的div引入任何外链内容
  10. unity中怎么在InspectorI面板加LOGO