【OpenCV入门】第六部分——腐蚀与膨胀

文章结构

  • 腐蚀
  • 膨胀
  • 开运算
  • 闭运算
  • 形态学方法
    • 梯度运算
    • 顶帽运算
    • 黑帽运算

腐蚀

腐蚀操作可以让图像沿着自己的边界向内收缩。OpenCV通过”核“来实现收缩计算。“核”在形态学中可以理解为”由n个像素组成的像素块“,像素块包含一个核心(通常在中央位置,也可以定义在其他位置)。像素块会在图像的边缘移动,在移动过程中,核会将图像边缘那些与核重合但又没有越过核心的像素点都抹除,效果如下:

在这里插入图片描述

OpenCV将腐蚀操作封装成了erode()方法:

dst = ccv2.erode(src, kernel, anchor, iterations, borderType, borderValue)
  • src: 原始图像
  • kernel: 腐蚀使用的核
  • anchor:(可选)核的锚点位置
  • iteration:(可选)腐蚀操作的迭代次数,默认值为1
  • borderType:(可选)边界样式,建议默认
  • borderValue:(可选)边界值,建议默认
  • dst :经过腐蚀之后的图像

在OpenCV做腐蚀或其他形态学操作时,通常使用NumPy模块来创建核数组,例如:

import numpy as np
k = np.ones((5,5), np.uint8)

这两行代码创建了一个数组,可以当作erode()方法的核参数。除了5×5的结构,还可以使用3×3、9×9等其他结构,行列数越大,计算出来的效果就越粗糙,行列数越小,计算出的效果就越精细。

实例1: 将仙人球图像中的刺都抹除掉

import cv2
import numpy as np
img = cv2.imread("cactus.jpg")  # 读取原图
k = np.ones((3, 3), np.uint8)  # 创建3*3的数组作为核
cv2.imshow("img", img)  # 显示原图
dst = cv2.erode(img, k)  # 腐蚀操作
cv2.imshow("dst", dst)  # 显示腐蚀效果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

在这里插入图片描述
如果是(1,1),等于没削;如果是(5,5),直接削皮了。

膨胀

膨胀操作与腐蚀操作正好相反,膨胀操作可以让图像沿着自己的边界向外扩张。同样是通过核计算,当核在图像的边缘移动时,核会将图像边缘填补新的像素,效果如下:

dst = cv2.dilate(src, kernel, anchor, iterations, borderType, borderValue)
  • src: 原始图像
  • kernel: 膨胀使用的核
  • iteration:(可选)膨胀操作的迭代次数,默认值为1
  • borderType:(可选)边界样式,建议默认
  • borderValue:(可选)边界值,建议默认
  • dst :经过膨胀之后的图像

实例2: 将图像加工成”近视眼“效果

import cv2
import numpy as np
img = cv2.imread("sunset.jpg")  # 读取原图
k = np.ones((9, 9), np.uint8)  # 创建9*9的数组作为核
cv2.imshow("img", img)  # 显示原图
dst = cv2.dilate(img, k)  # 膨胀操作
cv2.imshow("dst", dst)  # 显示膨胀效果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:
在这里插入图片描述

开运算

开运算就是先将图像进行腐蚀操作,再进行膨胀操作。开运算可以用来抹除图像外部的细节(或者噪声)

例如图 7.13 是一个简单的二叉树,父子节点之间都有线连接。如果对此图像进行腐蚀操作,可以得出如图 7.14 所示的图像,连接线消失了,节点也比原图节点小一圈。此时再执行膨胀操作,让缩小的节点膨胀回原来的大小,就得出了如图 7.15 所示的效果。
在这里插入图片描述
这三张图就是开运算的过程,从结果可以明显地看出: 经过开运算之后,二叉树中的连接线消失了,只剩下光秃秃的节点。因为连接线被核当成“细节”抹除了,所以利用检测轮廓的方法就可以统计出二叉树节点数量,也就是说在某些情况下,开运算的结果还可以用来做数量统计。

实例3: 抹除黑种草图像中的针状叶子

import cv2
import numpy as np
img = cv2.imread("nigella.png")  # 读取原图
k = np.ones((5, 5), np.uint8)  # 创建5*5的数组作为核
cv2.imshow("img", img)  # 显示原图
dst = cv2.erode(img, k)  # 腐蚀操作
dst = cv2.dilate(dst, k)  # 膨胀操作
cv2.imshow("dst", dst)  # 显示开运算结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:
在这里插入图片描述

闭运算

闭运算就是将图像先进行膨胀操作,再进行腐蚀操作。闭运算可以抹除图像内部的细节(或者噪声)。

例如图 7.19 是一个身上布满斑点的小蜘蛛,这些斑点就是图像的内部细节。先将图像进行膨胀操作,小蜘蛛身上的斑点 (包括小眼睛)就被抹除掉,效果如图 7.20 所示。然后再将图像进行腐蚀操作,让膨胀的小蜘蛛缩回原来的大小,效果如图 7.21 所示。

在这里插入图片描述
闭运算除了会抹除图像内部的细节,还会让一些里的较近的区域合并成一块区域。

形态学方法

OpenCV提供了一个morphologyEx()形态学方法,包含了所有常用的运算。

dst = cv2.morphologyEx(src, op, kernel, anchor, iterations, borderType, borderValue)
  • src: 原始图像
  • op: 操作类型
参数值含义
cv2.MORPH_ERODE腐蚀操作
cv2.MORPH_DILATE膨胀操作
cv2.MORPH_OPEN开运算,先腐蚀后膨胀
cv2.MORPH_CLOSE闭运算,先膨胀后腐蚀
cv2.MORPH_GRADIENT梯度运算,膨胀图减腐蚀图,可以得出简易的轮廓
cv2.MORPH_TOPHAT顶帽运算,原始图像减开运算图像
cv2.MORPH_BLACKHAT黑帽运算,闭运算图像减原始图像
  • kernel: 操作过程中所使用的核
  • anchor:(可选),核的锚点位置
  • iteration:(可选)操作的迭代次数,默认值为1
  • borderType:(可选)边界样式,建议默认
  • borderValue:(可选)边界值,建议默认
  • dst :操作之后得到的图像

梯度运算

这里的梯度指的是图像梯度,可以简单地理解为像素的变化程度。几个连续的像素,其像素值跨度越大,则梯度值越大。

梯度运算就是让原图的膨胀图像减去原图的腐蚀图像。因为膨胀图比原图大,腐蚀图像比原图小,利用腐蚀图像将膨胀图像掏空,就得到了原图的 轮廓图像(大概,并不精准)。
在这里插入图片描述

实例4: 通过梯度运算画出小蜘蛛的轮廓

import cv2
import numpy as np
img = cv2.imread("spider.png")  # 读取原图
k = np.ones((5,5), np.uint8)  # 创建5*5的数组作为核
cv2.imshow("img", img)  # 显示原图
dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, k) # 进行梯度运算
cv2.imshow("dst", dst)  # 显示梯度运算结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

在这里插入图片描述

顶帽运算

顶帽运算就是让原图减去原图的开运算图像,得到图像的外部细节

实例5: 通过顶帽运算画出小蜘蛛的腿

import cv2
import numpy as np
img = cv2.imread("spider.png")  # 读取原图
k = np.ones((5, 5), np.uint8)  # 创建5*5的数组作为核
cv2.imshow("img", img)  # 显示原图
dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, k)  # 进行顶帽运算
cv2.imshow("dst", dst)  # 显示顶帽运算结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

在这里插入图片描述

黑帽运算

黑帽运算就是让原图的闭运算图像减去原图,得到原图像的内部细节

实例6: 通过黑帽运算画出小蜘蛛身上的花纹

import cv2
import numpy as np
img = cv2.imread("spider2.png")  # 读取原图
k = np.ones((5, 5), np.uint8)  # 创建5*5的数组作为核
cv2.imshow("img", img)  # 显示原图
dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, k)  # 进行黑帽运算
cv2.imshow("dst", dst)  # 显示黑帽运算结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/63588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构建现代应用:Java中的热门架构概览

文章目录 1. 三层架构2. Spring框架3. 微服务架构4. Java EE(Enterprise Edition)5. 响应式架构6. 大数据架构7. 领域驱动设计(Domain-Driven Design,DDD)8. 安卓开发架构结论 🎉欢迎来到Java学习路线专栏~…

如何伪造http头,让后端认为是本地访问

0x00 前言 这个知识点纯粹就是为了ctf准备的,很少有系统会出现这种情况。 0x01 正文 1.host头 如果后端从host取值来判断是否是本地就可以通过此方法进行绕过: host: 127.0.0.12.X-Forwarded-For X-Forwarded-For(XFF)是用来…

使用Arrays.asList生成的List集合,操作add方法报错

早上到公司,刚到工位,测试同事就跑来说"功能不行了,报服务器异常了,咋回事";我一脸蒙,早饭都顾不上吃,要来了测试账号复现了一下,然后仔细观察测试服务器日志,发现报了一个…

芯探科技--泛自动驾驶激光雷达解决方案

泛自动驾驶应用领域: 无人配送车 无人叉车 服务机器人 无人清扫车 …… 泛自动驾驶激光雷达解决方案介绍 在中低速移动过程中,类似无人配送车、无人叉车、服务型机器人、无人清扫车等具有自动驾驶功能的车辆,其需要对周围的环境进行探测,进而实现…

【已解决】激活虚拟环境报错:此时不应有Anaconda3\envs\[envs]\Library\ssl\cacert.pem。

新建虚拟环境后,进入虚拟环境的时候出现这样的报错: 此时不应有Anaconda3 envs yolov5 Library ssl cacert.pem。 但是之前装的虚拟环境也还能再次激活,base环境也无任何问题,仅新装的虚拟环境无法激活。 查遍了百度谷歌&#xff…

eclipse/STS(Spring Tool Suite)安装CDT环境(C/C++)

在线安装 help -> eclipse marketplace 可以发现,我所使用eclipse给我推荐安装的CDT是10.5版本 离线安装 下载离线安装包 下载地址:https://github.com/eclipse-cdt/cdt/blob/main/Downloads.md 可以看到利息安装包主要有如下四大类,…

Springboot整合ClickHouse

一、快速开始 1、添加依赖 <dependency><groupId>ru.yandex.clickhouse</groupId><artifactId>clickhouse-jdbc</artifactId><version>0.3.1-patch</version> </dependency> <dependency><groupId>com.alibaba&…

【typeof instanceof Object.prototype.toString constructor区别】

几个数据类型判断区别 typeofinstanceofObject.prototype.toStringconstructor typeof 它返回的是一个字符串&#xff0c;表示未经过计算的操作数的类型 typeof(undefined) //"undefined"typeof(null) //"object"typeof(100) //"number"typeof…

DECLARE_DYNCREATE(DECLARE_DYNAMIC)与IMPLEMENT_DYNCREATE(IMPLEMENT_DYNAMIC)

一、问题 看源码&#xff0c;发现这两组宏的实现是有细微差别的&#xff0c;需要配合使用 二、原理 这两组宏的作用类似&#xff0c;但有一些细微的区别&#xff1a; DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE&#xff1a; DECLARE_DYNCREATE 用于在类的声明中启用支持对象…

如何使用 FabricJS 禁用椭圆的居中旋转?

椭圆形是 FabricJS 提供的各种形状之一。为了创建一个椭圆&#xff0c;我们必须创建一个 Fabric.Ellipse 类的实例并将其添加到画布中。默认情况下&#xff0c;FabricJS 中的所有对象都使用其中心作为旋转点。但是&#xff0c;我们可以使用 centeredRotation 属性来更改此行为。…

clickhouse的另类表引擎

clickhouse常用的MergeTree引擎外&#xff0c;还有特殊的引擎 1&#xff0c;memory引擎&#xff0c;顾名思义&#xff0c;数据是存储在内存中&#xff0c;数据不会被压缩也不会倍格式化转换数据在内存中保存的形态与查询时看到的如出一辙&#xff0c;重启ck数据丢失 2&#xff…

matlab的基本使用

matlab的基本使用&#xff0c;可以参考如下的教程&#xff1a;matlab教程 本文针对基本内容进行记录。 matlab简介 MATLAB是美国MathWorks公司出品的商业数学软件&#xff0c;用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人&…

xx音乐app逆向分析

目标 看一下评论的请求 抓包 这里使用httpcanary 请求包如下 POST /index.php?rcommentsv2/getCommentWithLike&codeca53b96fe5a1d9c22d71c8f522ef7c4f&childrenidcollection_3_1069003079_330_0&kugouid1959585341&ver10&clienttoken7123ecc548ec46d…

vs2008下的mfc hello world实现

笔者不知道会写这种博文&#xff0c;好久没写mfc程序&#xff0c;hello world都不会创建了。起因是来了个mfc任务&#xff0c;那就得把mfc熟悉起来&#xff0c;先看下实现效果吧 因为是基于2008的&#xff0c;那就按照2008创建吧 文章目录 第一步&#xff1a;文件新建项目第二…

【iOS】折叠cell

文章目录 前言一、实现效果二、折叠cell的实现原理三、实现折叠cell的高度变化四、实现选中点击的单元格总结 前言 在暑假的3GShare中用到了折叠cell控件&#xff0c;特此总结博客记录 一、实现效果 二、折叠cell的实现原理 首先我们需要知道ScrollView的是TableView的父类&a…

Gitee注册和使用

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.Gitee 1.1Gitee是什么 1.2Gitee的注册以及远程仓库的创建…

ClickHouse 使用

CREATE DATABASE test on cluster ck_00_1repl; DROP TABLE local_t_ordt_order on cluster ck_00_1repl; 创建本地 local 表 CREATE TABLE test.local_order_db_t_order on cluster ck_00_1repl ( forder_id_hash String, forder_id String, fuid Int32, forder_type Int32…

下面是实践百度飞桨上面的pm2.5分类项目_logistic regression相关

part1:数据的引入&#xff0c;和前一个linear regression基本是一样 part2:数据解析——也就是数据的“规格化” 首先&#xff0c;打算用dataMat[]和labelMat[]数据存储feature和label&#xff0c;并且文件变量fr 然后&#xff0c;是这个for line in fr.readlines()循环&#…

管理类联考——逻辑——形式逻辑——汇总篇——知识点突破——形式逻辑——联言选言假言——等价

角度 角度——汇总 性质 &#xff08;1&#xff09; 有的 S 是 P 有的 S → P &#xff1b;换位&#xff1a;有的 S 是 P 有的 P 是 S &#xff1b;不可逆否 有的S是P有的S→P&#xff1b;换位&#xff1a;有的S是P有的P是S&#xff1b;不可逆否 有的S是P有的S→P&#xff1…

Android AGP8.1.0组件化初探

Android AGP8.1.0组件化初探 前言&#xff1a; 前面两篇完成了从AGP4.2到 AGP8.1.0的升级&#xff0c;本文是由于有哥们留言说在AGP8.0中使用ARouter组件化有问题&#xff0c;于是趁休息时间尝试了一下&#xff0c;写了几个demo&#xff0c;发现都没有问题&#xff0c;跳转和传…