【OpenCV实现平滑图像形态学变化】
文章目录
- 概要
- 目标
- 腐蚀
- 膨胀
- 开运算
- 结构元素(内核)
- 小结
概要
形态学变化是一组简单的图像操作,主要用于处理二值图像,即只包含黑和白两种颜色的图像。这些操作通常需要两个输入,原始图像和一个内核(kernel),内核的形状和大小决定了操作的性质。
文章将首先介绍腐蚀和膨胀这两个基本的形态学算子。腐蚀操作通过内核在图像上滑动,将像素值置为内核覆盖区域内的最小值,用于消除图像中的小物体或者噪点。相反,膨胀操作将像素值置为内核覆盖区域内的最大值,常用于连接图像中的物体或者填充小的空洞。
随后,文章将介绍其他常见的形态学算子,如开运算和闭运算。开运算是先进行腐蚀操作,再进行膨胀操作,常用于去除噪声和分离物体。闭运算则是先进行膨胀操作,再进行腐蚀操作,常用于填充小洞和连接物体
目标
不同的形态学运算例如腐蚀、膨胀、开运算、闭运算。
不同的函数列如cv.erode()、cv.dilate()、cv.morphologyEx()等等。
腐蚀
是一种基本的形态学操作,其原理类似于自然界中的水土流失现象。在腐蚀操作中,一个内核(kernel)在图像上滑动,如果内核覆盖下的所有像素都为1(即白色,表示前景物体),那么中心像素点就会被赋值为1,否则被腐蚀掉(赋值为0)。
这种操作导致了图像中前景物体的边界被侵蚀,保持前景物体为白色的同时,减小了其厚度或尺寸。换句话说,图像中的白色区域会逐渐减小。腐蚀操作在去除小白点噪声(例如图像中的小杂点)和分离连接在一起的对象等方面非常有效。通过选择合适的内核大小,可以调整腐蚀的程度,使其更加适应不同场景下的图像处理需求。
import cv2 as cv
import numpy as np# 读取图像
img = cv.imread('img.png', 0)# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)# 使用腐蚀操作,iterations参数表示腐蚀操作的次数
erosion = cv.erode(img, kernel, iterations=1)# 显示原始图像
cv.imshow('Original Image', img)# 显示腐蚀后的图像
cv.imshow('Eroded Image', erosion)# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()
腐蚀结果:

膨胀
膨胀是一种形态学操作,与腐蚀相反。它的基本思想是通过内核的滑动,只要内核下的像素中有一个为1,中心像素就会被赋值为1(这类似于逻辑或运算)。膨胀操作会扩大白色物体(或前景物体)的区域或大小。在去除噪声时,通常会先进行腐蚀操作,然后再进行膨胀操作。这是因为腐蚀能够去除小的白色噪声,但同时也可能腐蚀掉我们需要保留的物体。膨胀操作的目的就是扩大物体,使其恢复到原始大小和形状。
在膨胀操作中,噪声已经在腐蚀阶段被去除,因此在膨胀时不会再次引入噪声,但物体的大小和体积会得到恢复。此外,膨胀操作还对有破损或间断连接的物体部分进行恢复,使其更加完整。通过膨胀操作,可以使图像中的白色区域逐渐增大,从而更好地突出物体的特征。

开运算
开运算只是先腐蚀后膨胀的另一个名称。正如我们上面所解释的,它对于消除噪音很有用。这里我们函数cv.morphologyEx()。
import cv2 as cv
import numpy as np# 读取图像
img = cv.imread('img.png', 0)# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)# 使用开运算,先腐蚀后膨胀,可以去除噪声并保持物体的整体形状
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)# 显示原始图像
cv.imshow('Original Image', img)# 显示开运算后的图像
cv.imshow('Opened Image', opening)# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

闭运算
闭运算和开运算相反,先膨胀后腐蚀。它对于关闭前景对象内的小孔或对象上的小黑点非常有用。
import cv2 as cv
import numpy as np# 读取图像
img = cv.imread('img.png', 0)# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)# 使用闭运算,先膨胀后腐蚀,可以填充前景物体内部的小孔,平滑物体的边界
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)# 显示原始图像
cv.imshow('Original Image', img)# 显示闭运算后的图像
cv.imshow('Closed Image', closing)# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

形态梯度
这是图像的膨胀和腐蚀之间做了一次差
结果将看起来像只留下对象的轮廓。
import cv2 as cv
import numpy as np# 读取图像
img = cv.imread('img.png', 0)# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)# 使用形态梯度,通过膨胀和腐蚀的差别,突出物体的边缘
gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)# 显示原始图像
cv.imshow('Original Image', img)# 显示形态梯度后的图像
cv.imshow('Gradient Image', gradient)# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

顶帽
它是输入图像和开运算图像之间的差。下面的示例是针对 9x9 内核完成的。
import cv2 as cv
import numpy as np# 读取图像
img = cv.imread('img.png', 0)# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)# 显示原始图像
cv.imshow('Original Image', img)# 显示形态梯度后的图像
cv.imshow('Gradient Image', tophat)# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

底帽
它是闭运算图像和输入图像的差
import cv2 as cv
import numpy as np# 读取图像
img = cv.imread('img.png', 0)# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)
# 显示原始图像
cv.imshow('Original Image', img)# 显示形态梯度后的图像
cv.imshow('Gradient Image', blackhat)# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

结构元素(内核)
在形态学变换中,我们经常需要定义一个内核来指导图像处理。在前面的例子中,我们手动创建了一个矩形内核,但在实际应用中,可能需要不同形状和大小的内核。为了方便地获取这些内核,OpenCV提供了一个函数cv.getStructuringElement()。
使用该函数,您只需要传递内核的形状和大小,就可以获得所需的内核。
cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
如果需要一个椭圆形内核,可以使用以下代码:
cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
类似地,如果需要一个十字形内核,可以使用
cv.getStructuringElement(cv.MORPH_CROSS, (5, 5))
小结
形态学变换是一种基于图像形状的简单而有效的处理方法,通常应用于二值图像(只包含黑白两种颜色)。在形态学变换中,我们使用内核(也称为结构化元素)来定义操作的性质和形状。
腐蚀是一种形态学变换,它侵蚀了前景物体(白色区域)的边界,通常用于去除小白点噪声或分离连接的对象。使用cv.erode()函数,我们可以将内核滑动在图像上,将内核覆盖下的像素点都为1时,中心像素点就会被赋值为1,其他时候都为0,从而缩小白色区域。
膨胀则与腐蚀相反,它会扩大白色物体的区域,常用于恢复连接对象的大小和形状。使用cv.dilate()函数,内核覆盖下的像素点只需有一个为1,中心像素点就会被赋值为1,从而扩大白色区域。
开运算是先腐蚀后膨胀的组合操作,它可以去除噪声并保持物体的整体形状。闭运算则是先膨胀后腐蚀的组合操作,它可以填充前景物体内部的小孔,平滑物体的边界。这两种操作分别使用cv.morphologyEx()函数中的cv.MORPH_OPEN和cv.MORPH_CLOSE参数实现。
为了方便地定义不同形状和大小的内核,OpenCV提供了cv.getStructuringElement()函数。通过传递内核的形状和大小参数,可以获得所需的内核。矩形、椭圆和十字形内核是常见的选择,可以根据具体任务的要求灵活选择合适的内核形状。
相关文章:
【OpenCV实现平滑图像形态学变化】
文章目录 概要目标腐蚀膨胀开运算结构元素(内核)小结 概要 形态学变化是一组简单的图像操作,主要用于处理二值图像,即只包含黑和白两种颜色的图像。这些操作通常需要两个输入,原始图像和一个内核(kernel&a…...
Ubuntu服务器中java -jar 后台运行Spring Boot项目
问:我在我的服务器中java -jar 运行springboot项目,但是我操作不了命令了,必须要终止掉才能执行后面的操作,怎么样才能让他后台运行呢?比如我的jar包名是tools-boot-0.0.1-SNAPSHOT.jar 使用nohup命令: 在…...
微服务parent工程和子工程pom文件配置注意
parent工程 重要配置: <!-- 父工程 --><packaging>pom</packaging><!-- 聚合 --><modules><module>../base</module><module>../gateway</module><module>../user-service</module><mod…...
STM32G030F6P6点灯闪烁
前言 (1)如果有嵌入式企业需要招聘湖南区域日常实习生,任何区域的暑假Linux驱动实习岗位,可C站直接私聊,或者邮件:zhangyixu02gmail.com,此消息至2025年1月1日前均有效 (2࿰…...
K8s开发人员也需要了解的相关知识
工作变动总结一下之前的笔记,整理一个速查的东西,方便之后查阅 K8s开发相关 1、k8s yml apiverison: Kubernetes (k8s) 的 API 版本表示资源定义在 API 服务器中的稳定性和支持程度。API 版本由一个字符串表示,如 v1 或 apps/v1,…...
创建并启动华为HarmonyOS本地与远程模拟器及远程真机
1.打开设备管理器 2.选择要添加的手机设备,然后点击安装 3.正在下载华为手机模拟器 4.下载完成 5.创建新模拟器 下载系统镜像 点击下一步,创建模拟器 创建成功 启动模拟器 华为模拟器启动成功 6.登陆华为账号并使用远程模拟器 7.使用远程真机...
责任链模式应用案例
前几天系统商品折扣功能优化,同事采用了责任链模式重构了代码,现整理如下。 一、概念 责任链模式是为请求创建一个处理者对象的链条,所有处理者(除最末端)都含有下一个对象的引用从而形成一条处理链,该模…...
给你一个整数 num ,返回 num 中能整除 num 的数位的数目
给你一个整数 num ,返回 num 中能整除 num 的数位的数目。 如果满足 nums % val 0 ,则认为整数 val 可以整除 nums 。 示例 1: 输入:num 7 输出:1 解释:7 被自己整除,因此答案是 1 。 示例 2&…...
Java后端开发——房贷计算器(Ajax版、Json版、等额本息+等额本金)
MVC房贷计算器(Ajax版) 1.新建一个JavaWeb项目hslcalweb,设置tomcat10。 2.创建房贷计算器JavaBean:HslCalBean.java,增加以下的属性,并生成Getter/Setter方法。 private double total; //贷款额度pr…...
2023.10.28 关于 synchronized 原理
目录 synchronized 特性 synchronized 优化机制 锁升级(锁膨胀) 其他优化机制 锁消除 锁粗化 synchronized 特性 开始时是乐观锁,如果锁冲突频繁,就转为悲观锁开始是轻量级锁,如果锁被持有的时间较长,…...
力扣 27. 移除元素
目录 1.解题思路2.代码实现 1.解题思路 利用双指针思路,当让一个指针先走,指针指向的位置不等于val时,将此时该指针的值给另一个指针并且两个指针都加一,如果等于val,则让该指针加一继续走.最后另一个指针的下标就为排好的数组的…...
redis爆满导致数据丢失
记一则redis爆满导致数据丢失的一场事故 某功能上线后,发现出现问题,最后定位到了 redis. 由于存储的数据过多,导致阿里云4G大小的 redis 爆满,触发了回收策略。 于是临时扩容,运维同学当时未找到阿里云配置。 后面我用工具连接了…...
Android14 WMS启动流程
一 概述 本文Android14源代码可参考:Search 在 Android 系统中,从设计的角度来看,窗口管理系统是基于 C/S 模式的。整个窗口系统分为服务端和客户端两大部分,客户端负责请求创建窗口和使用窗口,服务端完成窗口的维护…...
磁盘管理(初始化,引导块,坏块管理,固态硬盘)
目录 1.磁盘初始化2.引导块3.坏块的管理1.坏块检查2.坏块链表3.扇区备用 4.固态硬盘(SSD)1.原理2.组成3.读写性能特性4.与机械硬盘相比5.磨损均衡技术 1.磁盘初始化 ①进行低级格式化(物理格式化),将磁盘的各个磁道划分…...
mysql冷拷贝大表
1、简述: mysql数据迁移有多种方式,最常见的就是先把数据库导出,然后导入新的数据库。拷贝数据目录data是另外一种方式。 尤其是当数据库启动不了,或者大型数据库迁移的时候,可以考虑这个方式。 2、场景:…...
苍穹外卖-01
苍穹外卖-01 课程内容 软件开发整体介绍苍穹外卖项目介绍开发环境搭建导入接口文档Swagger 项目整体效果展示: 管理端-外卖商家使用 用户端-点餐用户使用 当我们完成该项目的学习,可以培养以下能力: 1. 软件开发整体介绍 作为一名…...
GAMP源码阅读(中)伪距单点定位 SPP
原始 Markdown文档、Visio流程图、XMind思维导图见:https://github.com/LiZhengXiao99/Navigation-Learning 文章目录 一、SPP 解算1、spp():单点定位主入口函数2、estpos()3、estpose_()4、valsol():GDOP和卡方检验结果有效性 二、卫星位置钟…...
Epinoia-有状态网络的意图验证模块,略读
Epinoia relies on a unified model for NFs by leveraging the causal precedence relationshipsthat exist between NF packet I/Os and states. 这句话的意思是:“Epinoia依靠一种统一的网络功能(NF)模型,通过利用存在于 NF 包…...
14.力扣c++刷题-->有效括号
题目:给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合…...
scrapy-redis分布式爬虫(分布式爬虫简述+分布式爬虫实战)
一、分布式爬虫简述 (一)分布式爬虫优势 1.充分利用多台机器的带宽速度 2.充分利用多台机器的ip地址 (二)Redis数据库 1.Redis是一个高性能的nosql数据库 2.Redis的所有操作都是原子性的 3.Redis的数据类型都是基于基本数据…...
Unity ShaderGraph工程化实践:从可视化到生产级渲染
1. 为什么我劝新手别急着写第一行Shader代码——从Unity ShaderGraph的“可视化错觉”说起 刚接触Unity渲染管线的新手,十有八九会经历这样一个阶段:在B站搜“Unity Shader教程”,点开前三个视频,前两分钟听着“顶点着色器负责位置…...
TBP-9000-R0AE无风扇工控机:6网口4PoE+,严苛工业环境下的边缘计算与机器视觉平台
1. 项目概述:一台为严苛环境而生的工业“大脑”在工业自动化、机器视觉、轨道交通这些领域里,选一台靠谱的工控机,远比在办公室挑台电脑复杂得多。它不仅要算力够用,更得扛得住震动、耐得了高低温、接得了五花八门的工业设备&…...
量子虚时演化算法:原理、实现与应用
1. 量子虚时演化算法概述虚时演化(Imaginary-Time Evolution, ITE)是量子物理模拟中的核心数学工具,其核心思想是将时间变量t替换为虚数-iβ(β为实数)。这种变换将薛定谔方程中的幺正演化算符e^(-iHt)转化为非幺正的e…...
手算反向传播:从链式法则到梯度消失的物理直觉
1. 项目概述:这不是又一节“神经网络入门”,而是一次真正踩进反向传播泥潭的实操复盘“Intro to Neural Networks Part II — Brilliant.org”这个标题乍看平平无奇,像是在线教育平台里再普通不过的一节进阶课。但如果你真点开它,…...
机器学习论文阅读的解码协议:从扫读到复现的四步实战法
1. 为什么读论文这件事,比写代码还容易让人焦虑“How to Read Machine Learning Papers Effectively”——这个标题乍看像是一篇方法论指南,但在我带过三十多个算法实习生、审过两百多份顶会投稿、自己连续七年保持每周精读2–3篇NeurIPS/ICML/ACL论文的…...
计算硬件安装与调试以及组成的原理
一、计算机的组成原理:程序和数据提前存入内存,计算机自动逐条取指令、执行,无需人工拨开关。由此定下六大特征:五大部件(运算器、控制器、存储器、输入、输出)指令和数据 同等地位 存在内存中二进制表示指…...
网络安全实战工具链:从信息收集到漏洞修复的工程化闭环
1. 这不是“黑客速成班”,而是安全工程师真实工作流的切片很多人看到“挖漏洞”三个字,第一反应是黑进某个网站、弹出个红色命令行、屏幕上飞速滚动着看不懂的字符——然后“啪”一声,系统瘫痪。现实里我干了八年渗透测试和红队支撑ÿ…...
Wireshark深度解析:HTTP/1.1协议层隐写与pcapng元数据取证
1. 这不是一次普通的数据包分析,而是一场“协议层藏宝游戏”Wireshark实战:解密http1.pcapng中的隐藏flag——光看标题,你可能以为这只是又一篇教你怎么点开Filter框、输http然后截图的入门教程。但实际操作中,我连续三次在http1.…...
JMeter断言实战:从误配到分层校验的避坑指南
1. 为什么断言不是“加个检查框”就完事了?很多人第一次在 JMeter 里点开“添加 → 断言 → 响应断言”,填上“包含文本:success”,跑完看绿色小勾就以为接口测试闭环了。我带过三届测试团队,新同事交来的脚本里&#…...
陆渔科技投入三千万学费:用AI擦去水产养殖不确定性,带来养殖确定性
创业故事:从偶然入局到屡败屡战陆渔科技深耕农业AI,两次失败、投入三千万学费,才拿到这张真实的“入场券”。鲁敏等四人原本与农业毫无关联,一次偶然饭局结识养鱼伙伴,了解到鲈鱼苗孵化项目。当时互联网、房地产市场饱…...
