图像形态学中两种最基本的操作就是对图形的腐蚀和膨胀,可以说,形态学中的中高级操作都是建立在这两种操作之上。通过这两种基本的运算可以去除图像中的噪声,分割出独立的区域或者将两个区域连接在一起。

关于图像腐蚀和膨胀的概念,不严谨的简单理解是:经过腐蚀和膨胀操作后最终的效果是对图像中物体的边界进行一层一层的腐蚀和膨胀操作,这个边界包括内边界和外边界。
严谨的理解是这样的:图像的腐蚀和膨胀实际上是用某种形状的窗去遍历图像中的每一个元素,并用这个形状中的最大值或最小值做为锚点的值(锚点的概念可参考我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/124173092)。若取的是最大值,则是膨胀操作,若取的是最小值,则是腐蚀操作。这里某种形状可以是十字形、菱形、矩形、X形等。这里我补充说明一下,其实所有的窗都是矩形的,那么怎样定义不同的形状呢?是这样操作的:通过把矩形窗中的元素置为1形成不同的形状。更详细的说明可见本文下面对函数getStructuringElement()参数shape的介绍。

OpenCV提供了函数erode()和函数dilate()分别用于图像形态学的腐蚀与膨胀操作,下面分别介绍。

函数dilate()的数学运算表达式如下:
dst ( x , y ) = min ⁡ ( x ′ , y ′ ) : element ( x ′ , y ′ ) ≠ 0 src ( x + x ′ , y + y ′ ) \texttt{dst} (x,y) = \min _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y') dst(x,y)=min(x′,y′):element(x′,y′)​=0​src(x+x′,y+y′)
其中(x’,y’)是窗中的元素坐标。

函数erode()的数学运算表达式如下:
dst ( x , y ) = max ⁡ ( x ′ , y ′ ) : element ( x ′ , y ′ ) ≠ 0 src ( x + x ′ , y + y ′ ) \texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y') dst(x,y)=max(x′,y′):element(x′,y′)​=0​src(x+x′,y+y′)
其中(x’,y’)是窗中的元素坐标。

图像形态学的腐蚀操作函数erode()的原型如下:

void erode( InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );

图像形态学的腐蚀操作函数dilate()的原型如下:

void dilate(     InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = morphologyDefaultBorderValue() );

可见,两个函数的原型除了函数名不一样,其它都是一样的,所以我们就统一介绍两个函数参数的意义。
参数意义如下:
src—输入图像,通道数任意,数据深度只能为 CV_8U, CV_16U, CV_16S, CV_32F,CV_64F中的一种。每个通道将被单独处理。
ds—为输出图像,尺寸和数据类型与输入图像一致。
kernel—erode()使用某种形状的窗侵蚀一个图像,dilate()也使用某种形状的窗对图像进行膨胀。参数kernel就表示这个窗。显然这个窗越大,显然每次对图像的腐蚀或膨胀越多,反之亦然。有下面两种构造这个窗的方法。有下面两种构造这个窗的方法。
 ①使用函数getStructuringElement()来获取,函数getStructuringElement()的原型如下:

  Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));

 函数getStructuringElement()的参数意义如下:
 shape—窗的形状,MORPH_RECT为矩形,矩形中的每一个元素的值为1;MORPH_CROSS代表十字形结构,十字形的长和宽由ksize定,十字形上的元素值也为1;MORPH_ELLIPSE为椭圆,椭圆中的每一个元素的值也为1,椭圆内切于参数ksize定义的矩形大小。可以结合下面这个表更好理解。

 ksize—其意义见对参数shape的讲解。
 anchor—当shape为十字形时,这个参数表示十字线的横线和竖线的交点位置。
 ②自定义kernel窗,此种方法的示例可以参见下面这篇博文:
 https://blog.csdn.net/wenhao_ir/article/details/51915869
继续讲函数erode()和函数dilate()的参数意义。
anchor—锚点位置。
iterations—表示迭代次数,即对图像做几次腐蚀和膨胀。
borderType—边界扩展处理方式,详情见 https://blog.csdn.net/wenhao_ir/article/details/124177989
borderValue—关于这个值,也请参见 https://blog.csdn.net/wenhao_ir/article/details/124177989

下面上使用函数erode()和函数dilate()进行腐蚀和膨胀处理的示例代码:
代码中用到的图像下载链接:https://pan.baidu.com/s/1Acoq3mR2RK0KHtYBCtq9qg?pwd=708g

//博主微信/QQ 2487872782
//有问题可以联系博主交流
//有图像处理需求也可联系博主
//图像处理技术交流QQ群 271891601//OpenCV版本:3.0
//VS版本:2013#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>using namespace cv;int main()
{//载入原图   Mat image = imread("F:/material/images/P0046-erode_dilate-02.bmp",0);//显示原图  imshow("原图的灰度图", image);//获取自定义核  Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));Mat out1, out2;//进行膨胀操作  dilate(image, out1, element);//进行腐蚀操作  erode(image, out2, element,cv::Point(-1,-1),2);//显示效果图  imshow("膨胀操作效果图", out1);imshow("腐蚀操作效果图", out2);waitKey(0);return 0;
}

代码运行结果如下图所示:

上面的示例代码是对图像的腐蚀操作和膨胀操作的直观认识,接下来,我们再通过Python示例代码来从数据运算上看一看图像的腐蚀操作和闭操作是怎么回事。
先来探究膨胀操作:
探究膨胀操作的示例代码如下:

# 博主微信/QQ 2487872782
# 有问题可以联系博主交流
# 有图像处理需求也可联系博主
# 图像处理技术交流QQ群 271891601# !/usr/bin/env python
# -*- coding: utf-8 -*-
# OpenCV的版本为4.1import cv2 as cv
import numpy as npA = np.zeros((9, 9), dtype='uint8')A[3:6, 3:6] = 5
A[4, 4] = 9structure1 = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
structure2 = cv.getStructuringElement(cv.MORPH_CROSS, (3, 3))dilate_out1 = cv.dilate(A, structure1)
dilate_out2 = cv.dilate(A, structure2)

运行结果如下图所示:





从以上运行结果可以看出,膨胀操作的运算规则的确是我上面介绍的那样。为了避免大家来回滚动页面,我再将运算规则摘录如下:
图像的腐蚀和膨胀实际上是用某种形状的窗去遍历图像中的每一个元素,并用这个形状中的最大值或最小值做为锚点的值(锚点的概念可参考我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/124173092)。若取的是最大值,则是膨胀操作,若取的是最小值,则是腐蚀操作。这里某种形状可以是十字形、菱形、矩形、X形等。这里我补充说明一下,其实所有的窗都是矩形的,那么怎样定义不同的形状呢?是这样操作的:通过把矩形窗中的元素置为1形成不同的形状。更详细的说明可见本文对函数getStructuringElement()参数shape的介绍。
函数dilate()的数学运算表达式如下:
dst ( x , y ) = min ⁡ ( x ′ , y ′ ) : element ( x ′ , y ′ ) ≠ 0 src ( x + x ′ , y + y ′ ) \texttt{dst} (x,y) = \min _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y') dst(x,y)=min(x′,y′):element(x′,y′)​=0​src(x+x′,y+y′)
其中(x’,y’)是窗中的元素坐标。

再来探究腐蚀操作。
探究腐蚀操作的示例代码如下:

运行结果如下:






从以上运行结果可以看出,腐蚀操作的运算规则的确是我上面介绍的那样。为了避免大家来回滚动页面,我再将运算规则摘录如下:
图像的腐蚀和膨胀实际上是用某种形状的窗去遍历图像中的每一个元素,并用这个形状中的最大值或最小值做为锚点的值(锚点的概念可参考我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/124173092)。若取的是最大值,则是膨胀操作,若取的是最小值,则是腐蚀操作。这里某种形状可以是十字形、菱形、矩形、X形等。这里我补充说明一下,其实所有的窗都是矩形的,那么怎样定义不同的形状呢?是这样操作的:通过把矩形窗中的元素置为1形成不同的形状。更详细的说明可见本文对函数getStructuringElement()参数shape的介绍。
函数erode()的数学运算表达式如下:
dst ( x , y ) = max ⁡ ( x ′ , y ′ ) : element ( x ′ , y ′ ) ≠ 0 src ( x + x ′ , y + y ′ ) \texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y') dst(x,y)=max(x′,y′):element(x′,y′)​=0​src(x+x′,y+y′)
其中(x’,y’)是窗中的元素坐标。

知道了腐蚀和膨胀的具体运算过程后,我们便可以知道当参数shape取不同形状时,效果有什么区别。具体效果有什么不同,大家在理解以上运算过程后,便可以在脑海中想像了,这里博主就不再码字了。

扩展阅读:
图像的形态学开操作(开运算)和闭操作(闭运算)的概念和作用,并用OpenCV的函数morphologyEx()实现对图像的开闭操作
图像的形态学梯度运算(基本梯度、外部梯度、内部梯度、X方向梯度、Y方向梯度)的概念、作用以及相关的OpenCV示例代码
图像形态学操作之顶帽操作(TopHat)与黑帽操作(BlackHat)
详解图像形态学中的击中击不中变换操作(HMT),并提醒大家OpenCV4中的击中击不中变换操作是有问题的

详解图像形态学操作之图形的腐蚀和膨胀的概念和运算过程,并利用OpenCV的函数erode()和函数dilate()对图像进行腐蚀和膨胀操作相关推荐

  1. 详解图像形态学中的击中击不中变换操作(HMT),并提醒大家OpenCV4中的击中击不中变换操作是有问题的

    大家看这篇博文前可以先看一看下面这篇博文,下面这篇博文是这篇博文的基础: 详解图像形态学操作之图形的腐蚀和膨胀的概念和运算过程,并利用OpenCV的函数erode()和函数dilate()对图像进行腐 ...

  2. 利用OpenCV的霍夫变换线检测函数HoughLines()得到直线的ρ和θ值后绘制直线的原理详解

    为了更好地看懂本文,大家可以先看下我写的另一篇博文,链接如下: https://blog.csdn.net/wenhao_ir/article/details/51774444 OpenCV的霍夫变换 ...

  3. 【OpenCV 4开发详解】形态学应用

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  4. 零基础多图详解图神经网络(GNN/GCN)【论文精读】

    视频链接:零基础多图详解图神经网络(GNN/GCN)[论文精读] - 哔哩哔哩 (bilibili.com) 博客链接:A Gentle Introduction to Graph Neural Ne ...

  5. 8.1 matlab图形窗口与坐标轴(图形对象的句柄和属性、坐标轴的操作、图形窗口的操作)

    1.图形对象的句柄 (1)句柄的概念 在MATLAB中,用句柄来标识对象,通过句柄来访问相应对象的属性:在MATLAB系统中建立-个对象,系统就会建立-个映射该对象的句柄,用于存诸相应对象的属性. 例 ...

  6. OpenCV之imgproc 模块. 图像处理(1)图像平滑处理 腐蚀与膨胀(Eroding and Dilating) 更多形态学变换 图像金字塔 基本的阈值操作

    图像平滑处理 目标 本教程教您怎样使用各种线性滤波器对图像进行平滑处理,相关OpenCV函数如下: blur GaussianBlur medianBlur bilateralFilter 原理 No ...

  7. 【Matplotlib】详解图像各个部分

    转自:https://www.cnblogs.com/nju2014/p/5620776.html [Matplotlib]详解图像各个部分 首先一幅Matplotlib的图像组成部分介绍. 在mat ...

  8. OpenCV4萌新之路——详解图像读取函数 “imread”

    OpenCV4萌新之路--详解图像读取函数 "imread" 一.函数简析 二.参数详解 1.String& filename 2.flags = IMREAD_COLOR ...

  9. WPS简单五步操作修改图形并调整图形位置大小和旋转角度

    在为大家介绍使用WPS如何操作修改图形之前,先了解下几个与之相关的问题: 问:WPS画好图怎么组合? 形状组合,可以使用快捷键,按SHIFT键,单击多个图形对象(或者使用选择窗格选择要组合的形状). ...

最新文章

  1. JSP利用servlet上传文件时的中文乱码问题
  2. python的循环语句机制_Python-for循环的内部机制
  3. window的war发布Linux失败,为什么war包在Windows的tomcat正常运行,在linux服务器报errorpage错误?...
  4. 电脑自带的画图工具怎么使用笔刷
  5. java并发初探ThreadPoolExecutor拒绝策略
  6. NSNtification 在多线程中的运用
  7. Flask 模版(四)- 时间 Flask-Moment
  8. ICC_lab总结——ICC_lab3:布局
  9. 男孩应该懂的,女孩应该懂的
  10. Keil:Undefined symbol ......(referred from......)
  11. 优矿API实现一个双均线策略
  12. 禾穗HERS | 没人diss你,你就厉害了?
  13. linux cut指令
  14. 局域网中最常用的三种网络协议简述
  15. [附源码]Java计算机毕业设计SSM大学生项目众筹系统
  16. 三菱CC-link IE field basic 控制伺服轴
  17. ECSHOP去版权教程
  18. Pandas将列表(List)转换为数据框(Dataframe)进阶篇
  19. iOS开发之直播App流程介绍,直播资料收集汇总,视频推流,视频拉流,SMTP、RTMP、HLS、 PLPlayerKit
  20. Github上bitcoin的CPU挖矿程序部署编译

热门文章

  1. 【ECharts学习】—实现中国地图
  2. python中的slice用法
  3. mac录屏快捷键 - mac截图截屏快捷键 - 自带录屏软件QuickTime Player如何使用
  4. Jmeter 添加kafka支持
  5. C++中的防卫式声明
  6. VS Code利用GIT对源码进行管理
  7. opencv学习之视频帧率
  8. Python模块之Pandas模块学习笔记
  9. 嵌入式开发必须学习qt吗?
  10. PC端自适应-rem