opencv学习(二十四)之腐蚀与膨胀
腐蚀和膨胀是对二维图片的进行操作的形态学运算,简单来讲形态学操作就是基于形状的一系列图像处理操作,通过将结构元素作用于输入图像来产生输出图像。腐蚀(Erosion)和膨胀(Dilation)是最基本的形态学操作,他们运用广泛主要有:
. 消除噪声
. 分割(ioslate)独立的图像元素以及连接(join)相邻的元素
. 寻找图像中的明显的极大值区域或极小值区域
. 求出图像的梯度
给出图片如下:
图片背景为白色,字母为黑色。下面将根据此图形对膨胀腐蚀的原理进行说明。
1.膨胀
膨胀(dilate)就是求局部最大值的操作,从数学的角度来讲膨胀或者腐蚀就是将一幅二维图像或图像的一部分(称之为A)与一个模板也就是核(称为B)进行卷集运算的过程。
核可以是任何形状和大小,与之前介绍的模板一样,核有一个可定义的锚点。
. 膨胀操作是将图像A与任意形状的内核B(通常为正方形或者圆形)进行卷集
. 内核B中可定义的锚点通称定义为内核中心点
. 进行膨胀操作时,将内核B在图像A上进行滑动操作,将内核B覆盖的区域的最大像素值提取并提到内核B锚点位置的像素。
. 上述操作将会导致图像中的亮区开始扩展,因为白色的像素值要远远大于黑色的像素值。经膨胀运算后其图形如下
对于膨胀运算其数学表达式如下:
opencv提供了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: 输出图像,与原图像有相同的尺寸和类型。
. InpurArray kernel: 用于膨胀操作的kernel,当参数=Mat()即NULL时,kernel是一个锚点位于中心的3x3模板。可以通过getStructuringElement函数来制定kernel的形状和尺寸,其函数原型如下:
Mat cv::getStructuringElement ( int shape,Size ksize,Point anchor = Point(-1,-1) )
参数解释:
. int shape: kernel的形状,由cv::MorphShapes指定,如下
分别是矩形(MORPH_RECT)、交叉形(MORPH_CROSS)、椭圆形(MORPH_ELLIPSE)
. Size ksize: kernel的尺寸
. Point anchor = Point(-1, -1): 锚点位置
一般在调用erode以及dilate函数之前需要定义一个Mat类型的变量来获得getStructuringElement()函数的返回值,对于锚点如果没有特殊要求使用默认值即可
. Point anchor = Point(-1, -1): 锚点位置
. int iterations=1: 迭代使用膨胀的次数
. int borderType = BORDER_CONSTANT: 用于推断图像外部像素的某种边界模式,其有默认值BORDER_CONSTANT,可以通过cv::BorderTypes查询其他的方法。
. const Scalar & borderValue = morphologyDefaultBorderValue() : 边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般不用进行设置,如果有特殊需要,可以查看 createMorphologyFilter()函数得到详细信息。
2.腐蚀
. 腐蚀在形态学操作家族里是膨胀操作的孪生姐妹,它是提取内核覆盖下的像素最小值
. 进行腐蚀操作时,将内核窗口在图像A上进行滑动,将内核B覆盖的区域最小像素值提取并代替锚点位置的像素值
. 腐蚀操作将会导致图像中像素值较低的元素进行扩展,造成黑色部分加粗,如下图所示:
腐蚀操作的数学表达式如下:
opencv提供erode来实现腐蚀操作,其原型如下:
void cv::erode ( 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: 输出图像,与输入图像尺寸类型一致。
. Input Array kernel: 用于腐蚀操作的kernel,当参数=Mat()即NULL时,kernel是一个锚点位于中心的3x3模板。可以通过getStructuringElement函数来制定kernel的形状和尺寸,具体用法请参考对膨胀的表述
. Point anchor = Point(-1, -1): 锚点位置
. int iterations = 1: 迭代腐蚀操作次数,有默认值1
. int borderType = BORDER_CONSTANT: 用于推断图像外部像素的某种边界模式,其有默认值BORDER_CONSTANT,可以通过cv::BorderTypes查询其他的方法。
. const Scalar & borderValue = morphologyDefaultBorderValue(): 边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般不用进行设置,如果有特殊需要,可以查看 createMorphologyFilter()函数得到详细信息。
示例程序:
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>using namespace std;
using namespace cv;//定义全局变量
Mat g_srcImage;
Mat g_dilateImage;
Mat g_erodeImage;//定义两个轨迹条属性
const int typeMaxValue = 2; //膨胀腐蚀采用图形的类型
const int kernelSizeMaxVale = 21; //采用kernel的尺寸最大值int dilateTypeValue = 0; //默认膨胀操作模板图像类型
int dilateSizeValue = 5; //默认模板图像尺寸
int erodeTypeValue = 0;
int erodeSizeValue = 5;//定义两个回调函数
void dilateFun(int, void*); //膨胀回调函数
void erodeFun(int, void*); //腐蚀回调函数int main()
{g_srcImage = imread("cat.jpg");//判断图像是否打开成功if(g_srcImage.empty()){cout << "图像加载失败!" << endl;return -1;}elsecout << "图像加载成功!" << endl << endl;namedWindow("原图像", WINDOW_AUTOSIZE);imshow("原图像",g_srcImage);//定义膨胀操作窗口属性及轨迹条性质namedWindow("图像膨胀", WINDOW_AUTOSIZE);namedWindow("图像腐蚀", WINDOW_AUTOSIZE);char typeName[20];sprintf(typeName, "模板类型 %d", typeMaxValue);char sizeName[20];sprintf(sizeName, "模板尺寸 %d", kernelSizeMaxVale);//创建膨胀轨迹条createTrackbar(typeName, "图像膨胀", &dilateTypeValue, typeMaxValue, dilateFun);createTrackbar(sizeName, "图像膨胀", &dilateSizeValue, kernelSizeMaxVale, dilateFun);dilateFun(dilateTypeValue, 0);dilateFun(dilateSizeValue, 0);//创建腐蚀轨迹条createTrackbar(typeName, "图像腐蚀", &erodeTypeValue, typeMaxValue, erodeFun);createTrackbar(sizeName, "图像腐蚀", &erodeSizeValue, kernelSizeMaxVale, erodeFun);erodeFun(erodeTypeValue, 0);erodeFun(erodeSizeValue, 0);waitKey(0);return 0;
}//膨胀回调函数
void dilateFun(int, void*)
{//确定模板图像类型int dilate_type;if(dilateTypeValue == 0)dilate_type = MORPH_RECT;else if (dilateTypeValue == 1)dilate_type = MORPH_CROSS;elsedilate_type = MORPH_ELLIPSE;Mat element = getStructuringElement(dilate_type, Size(2*dilateSizeValue + 1, 2*dilateSizeValue + 1));dilate(g_srcImage, g_dilateImage, element); //膨胀操作imshow("图像膨胀", g_dilateImage);}//腐蚀回调函数
void erodeFun(int, void*)
{//确定模板图像类型int erode_type;if(erodeTypeValue == 0)erode_type = MORPH_RECT;else if (erodeTypeValue == 1)erode_type = MORPH_CROSS;elseerode_type = MORPH_ELLIPSE;Mat element = getStructuringElement(erode_type, Size(2*erodeSizeValue + 1, 2*erodeSizeValue + 1));erode(g_srcImage, g_erodeImage, element); //腐蚀操作imshow("图像腐蚀", g_erodeImage);
}
运行结果如下:
opencv学习(二十四)之腐蚀与膨胀相关推荐
- OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()
OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack() 参考博客: Harris角点检测原理详解 Harri ...
- OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()
OpenCV学习(二十二) :反向投影:calcHist(),minMaxLoc(),compareHist() 参考博客: 反向投影backproject的直观理解 opencv 反向投影 颜色直方 ...
- OpenCV学习(二十) :分水岭算法:watershed()
OpenCV学习(二十) :分水岭算法:watershed() 参考博客: OpenCV-分水岭算法 图像处理--分水岭算法 OpenCV学习(7) 分水岭算法(1) Opencv分水岭算法--wat ...
- opencv学习(二十五)之开运算、闭运算、形态梯度、顶帽、黑帽
上一篇介绍了形态学的基本操作膨胀和腐蚀,我们这一篇将利用膨胀和腐蚀操作实现对图像更高级的形态学操作,而这些都是建立在膨胀和腐蚀操作基础之上. 首先形态学的主要用途是获取物体拓扑和结果信息,它通过物体和 ...
- OpenCV学习(二十) :直方图匹配、对比:calcHist(),minMaxLoc(),compareHist()
直方图匹配.对比:calcHist ,minMaxLoc,compareHist 1.calcHist()函数 2.归一化:normalize()函数 3.minMaxLoc()函数 4.compar ...
- OpenCV学习三十四:watershed 分水岭算法
1. watershed void watershed( InputArray image, InputOutputArray markers ); 第一个参数 image,必须是一个8bit 3通道 ...
- opencv学习(二十六)之图像金字塔(高斯金字塔、拉普拉斯金字塔)
在进行数字图像处理时,我们可能会需要将某种尺寸的图像转换为其他尺寸的图像,这样会存在放大图像核缩小图像两种可能.opencv提供了一个真正意义上的图像所方函数resize(),但在本篇中主要学习以下使 ...
- Golang学习(二十四)家庭记账项目
一.项目开发流程 需求分析-->设计阶段-->实现阶段(代码)-->测试阶段-->实施阶段-->维护阶段 二.项目需求说明 1.模拟实现基于文本界面的 <家庭记账软 ...
- Java多线程学习二十四:阻塞队列包含哪些常用的方法?add、offer、put 等方法的区别?
阻塞队列包含哪些常用的方法,以及 add,offer,put 等方法的区别. 在阻塞队列中有很多方法,而且它们都非常相似,所以非常有必要对这些类似的方法进行辨析,所以本课时会用分类的方式,和你一起,把 ...
- torch学习 (二十四):卷积神经网络之GoogleNet
文章目录 引入 1 Inception块 2 GoogleNet模型 3 模型训练 完整代码 util.SimpleTool 引入 GoogleNet吸收了NIN网络串联网络的思想,并在此基础上做 ...
最新文章
- 将图片的二进制序列转为numpy且有shape
- MySQL中文全文索引
- MMORPG大型游戏设计与开发(part3 of net)
- 改变Android ProgressBar样式颜色
- SharePoint 2010应用开发系列
- 网络安装LINUX系统原理,PXE网络引导系统自动化安装CentOS7
- .NET(c#) 移动APP开发平台 - Smobiler(1)
- 正向代理与反向代理;
- 冷饭新炒:理解JDK中UUID的底层实现
- 几款主流的 Python IDE
- MySQL安装下载教程
- STM32F412 串口接收不到数据的问题
- 短信服务商与短信运营商的区别在哪里?
- 微信公众平台开发入门教程[2020版]
- 计算机专业跨考为什么考不了,浙江大学计算机专业考研,为什么这么多跨考计算机...
- 获取焦点(onFocus)和失去焦点(onBlur) (js)
- Prometheus企业级监控——理论入门
- 机器学习入门之:使用 scikit-learn 决策分类树来预测泰坦尼克号沉船生还情况
- 危骆邦油邦快讯|一分钟看懂山东地炼成品油报价
- MATLAB对一子数组赋值
热门文章
- c语言程序设计二维数组ppt,C语言程序设计教程二维数组的应用优秀讲义.ppt
- C源程序完整编译过程
- 算法导论答案网Solutions to Introduction to Algorithms Third Edition_开源免费完整
- DroidCamX – 让您的 Android 安卓手机瞬间变成电脑的高清无线摄像头
- 大学生 计算机 毕业设计 xx管理系统 毕设(1)
- 7天下载破千万,让你“变老”的FaceApp如何爆发式增长?
- Java编译器和解释器
- 世界首例AI同性婚姻惊呆众人 | Siri和Alexa结婚了
- ai人工智能软件_在FuchsiaOS,AI助手和软件优化上
- 洛谷 P4099 SAO —— 树形dp