当前位置: 首页 > article >正文

OpenCV计算机视觉实战(10)——形态学操作详解

OpenCV计算机视觉实战(10)——形态学操作详解

    • 0. 前言
    • 1. 腐蚀与膨胀
      • 1.1 为什么要做腐蚀与膨胀
      • 1.2 OpenCV 实现
    • 2. 开运算与闭运算
      • 2.1 开运算与闭运算原理
      • 2.2 OpenCV 实现
    • 3. 形态学梯度与骨架提取
      • 3.1 形态学梯度
      • 3.2 骨架提取
    • 小结
    • 系列链接

0. 前言

形态学操作 (Morphological Operations) 是图像预处理和特征提取的利器。通过简单的腐蚀与膨胀,我们便能去除噪点、填补孔洞;借助开闭运算,能够剔除干扰、平滑结构;而形态学梯度与骨架提取,则能够精准地捕捉边缘轮廓与中轴骨架。无论是在工业质检、文档清洗,还是道路检测与手写识别,掌握这些基本工具,都将为图像处理带来质的飞跃。

1. 腐蚀与膨胀

腐蚀 (Erosion) 是图像中的前景物体边界向内“收缩”,可去除小的噪点、分离相连物体;而膨胀 (Dilation) 则是图像中的前景物体边界向外“扩张”,可填补小的孔洞、连接分散物体。

1.1 为什么要做腐蚀与膨胀

去噪与分割:在二值化后的小颗粒噪声或连通区域中,腐蚀可以帮我们“吃掉”那些孤立的噪点,让结果更干净;膨胀则可填补目标内部的小孔,增强连通性。
形状变换:当需要放大或缩小目标形态时,腐蚀/膨胀提供了一种简单又高效的“膨胀器”或“压缩机”效果。

1.2 OpenCV 实现

要实现腐蚀与膨胀,首先需要读取二值图,然后定义结构元素 (kernel),分别调用 cv2.erodecv2.dilate,最后对比展示腐蚀后与膨胀后的效果。

import cv2
import numpy as np# 1. 读取二值图像
img = cv2.imread('1.jpeg', cv2.IMREAD_GRAYSCALE)# 2. 定义结构元素:3x3 矩形
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))# 3. 腐蚀与膨胀
eroded = cv2.erode(img, kernel, iterations=1)
dilated = cv2.dilate(img, kernel, iterations=1)# 4. 显示结果
cv2.imshow('Original', img)
cv2.imshow('Eroded (Iterations=1)', eroded)
cv2.imshow('Dilated (Iterations=1)', dilated)
cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV
关键函数解析:

  • cv2.getStructuringElement(shape, ksize):生成指定形状和大小的结构元素,用于定义腐蚀/膨胀的邻域
    • shape:决定邻域的拓扑结构,MORPH_RECT (矩形),最基础、对角方向也有效果;MORPH_ELLIPSE (椭圆),圆润过渡,更贴近自然形态;MORPH_CROSS (交叉),只在上下左右方向操作,可保留更多背景细节
    • ksize:决定邻域的影响范围,尺寸越大,对图像变化越剧烈,小尺寸适合轻微去噪,大尺寸可用于强力平滑或局部特征压缩
  • cv2.erode(src, kernel, iterations):对图像进行腐蚀操作,iterations 控制重复次数(值大则形态变化剧烈);每次腐蚀都将前景边界向内收缩一个结构元素大小
  • cv2.dilate(src, kernel, iterations):对图像进行膨胀操作,将前景边界向外扩张

2. 开运算与闭运算

2.1 开运算与闭运算原理

开运算 (Opening):先腐蚀后膨胀,常用于消除小的“白色”噪点(前景噪声),在工业检测中,常用来去除小的油污斑点或粉尘噪声。
闭运算 (Closing):先膨胀后腐蚀,常用于填充前景中的小孔、连接相邻对象,在文档处理或车牌识别中,常用来填补字符中字母、数字内部的断裂。

2.2 OpenCV 实现

要实现开运算与闭运算,首先需要读取二值图,然后定义结构元素 (kernel),调用 cv2.morphologyEx,分别指定 MORPH_OPENMORPH_CLOSE,最后对比展示开运算后与闭运算后的效果。

import cv2
import numpy as np# 1. 读取二值图像
img = cv2.imread('1.jpeg', cv2.IMREAD_GRAYSCALE)# 2. 定义结构元素:5x5 椭圆
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))# 3. 开运算与闭运算
opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=1)
closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=1)# 4. 显示结果
cv2.imshow('Original', img)
cv2.imshow('Opened', opened)
cv2.imshow('Closed', closed)
cv2.waitKey(0)
cv2.destroyAllWindows()

开运算与闭运算
关键函数解析:

  • cv2.morphologyEx(src, op, kernel, iterations):通用形态学函数,op 参数可选 MORPH_OPEN (开运算)、MORPH_CLOSE (闭运算)、MORPH_GRADIENT (梯度)等
  • 开运算 (MORPH_OPEN) = Erosion → Dilation;闭运算 (MORPH_CLOSE) = Dilation → Erosion

3. 形态学梯度与骨架提取

形态学梯度 (Morphological Gradient):膨胀结果与腐蚀结果之差,突出物体边缘轮廓。
骨架提取 (Skeletonization):将前景对象不断腐蚀并减去开运算结果,迭代至完全消失,得到细丝状“骨架”。

3.1 形态学梯度

形态学梯度可以定义为:梯度 = 膨胀结果 − 腐蚀结果。得到的直观效果:只保留前景的边缘像素,其余部分变黑。

import cv2
import numpy as np# 读取并二值化
img = cv2.imread('1.jpeg', cv2.IMREAD_GRAYSCALE)
_, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)# 定义结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 计算梯度
gradient = cv2.morphologyEx(binary, cv2.MORPH_GRADIENT, kernel)cv2.imshow('Binary', binary)
cv2.imshow('Morphological Gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()

形态学梯度

关键函数解析:

  • cv2.MORPH_GRADIENT:在 cv2.morphologyEx 中使用,自动计算膨胀与腐蚀的差值,突出边缘信息

3.2 骨架提取

算法流程详解

初始化:复制原始二值图为 temp,创建空图 skeleton
 循环迭代:
  用同一结构元素对 temp 腐蚀,得到 eroded
  对 eroded 做开运算,得到 opened
  edge = eroded − opened,提取该层“细丝”
  将 edgeskeleton 做按位或,累加骨架
  更新 temp = eroded
 终止条件:当 temp 中前景像素消失 (countNonZero(temp) == 0) 时退出。

import cv2
import numpy as np# 1. 读取二值图像
img = cv2.imread('7.jpeg', cv2.IMREAD_GRAYSCALE)
_, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)# 2. 准备
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
skeleton = np.zeros_like(binary)
temp = binary.copy()# 3. 迭代提取骨架
while True:eroded = cv2.erode(temp, kernel)opened = cv2.morphologyEx(eroded, cv2.MORPH_OPEN, kernel)edge = cv2.subtract(eroded, opened)skeleton = cv2.bitwise_or(skeleton, edge)temp = eroded.copy()if cv2.countNonZero(temp) == 0:break# 4. 显示结果
cv2.imshow('Original Binary', binary)
cv2.imshow('Skeleton', skeleton)
cv2.waitKey(0)
cv2.destroyAllWindows()

骨架提取

小结

在本节中,我们介绍了腐蚀与膨胀:理解了结构元素的形状与尺寸如何影响图像噪声去除与连通性增强;开运算与闭运算:掌握了“先破后立”与“先立后破”的组合套路,轻松去除斑点与填补空洞;形态学梯度与骨架提取:学会了如何从二值图中提取清晰的边缘轮廓,并将复杂形状瘦身为一像素宽的中轴线。在实际项目中,我们可以根据噪声类型和应用需求,自由组合这些操作:先用开运算去噪,再用闭运算恢复结构,或在边缘检测和形状分析前加入梯度与骨架处理。

系列链接

OpenCV计算机视觉实战(1)——计算机视觉简介
OpenCV计算机视觉实战(2)——环境搭建与OpenCV简介
OpenCV计算机视觉实战(3)——计算机图像处理基础
OpenCV计算机视觉实战(4)——计算机视觉核心技术全解析
OpenCV计算机视觉实战(5)——图像基础操作全解析
OpenCV计算机视觉实战(6)——经典计算机视觉算法
OpenCV计算机视觉实战(7)——色彩空间详解
OpenCV计算机视觉实战(8)——图像滤波详解
OpenCV计算机视觉实战(9)——阈值化技术详解

相关文章:

OpenCV计算机视觉实战(10)——形态学操作详解

OpenCV计算机视觉实战(10)——形态学操作详解 0. 前言1. 腐蚀与膨胀1.1 为什么要做腐蚀与膨胀1.2 OpenCV 实现 2. 开运算与闭运算2.1 开运算与闭运算原理2.2 OpenCV 实现 3. 形态学梯度与骨架提取3.1 形态学梯度3.2 骨架提取 小结系列链接 0. 前言 形态…...

libiec61850 mms协议异步模式

之前项目中使用到libiec61850库,都是服务端开发。这次新的需求要接收服务端的遥测数据,这就涉及到客户端开发了。 客户端开发没搞过啊,挑战不少,但是人不就是通过战胜困难才成长的嘛。通过查看libiec61850的客户端API发现&#xf…...

[论文阅读] 人工智能 | 利用负信号蒸馏:用REDI框架提升LLM推理能力

【论文速读】利用负信号蒸馏:用REDI框架提升LLM推理能力 论文信息 arXiv:2505.24850 cs.LG cs.AI cs.CL Harnessing Negative Signals: Reinforcement Distillation from Teacher Data for LLM Reasoning Authors: Shuyao Xu, Cheng Peng, Jiangxuan Long, Weidi…...

基于 NXP + FPGA+Debian 高可靠性工业控制器解决方案

在工业系统开发中,**“稳定”**往往比“先进”更重要。设备一旦部署,生命周期动辄 5~10 年,系统重启或异常恢复成本高昂。 这时候,一套“值得托付”的软硬件组合,就显得尤为关键。 ✅ NXP —— 提供稳定、长期供货的工…...

CSS 选择器全解析:分组选择器/嵌套选择器,从基础到高级

一、CSS 选择器基础&#xff1a;从单个元素到多个元素 CSS 选择器是用来定位 HTML 元素的工具&#xff0c;就像 “元素的地址”。最基础的选择器有&#xff1a; 元素选择器&#xff08;按标签名定位&#xff09; css p { color: red; } /* 所有<p>标签 */ div { b…...

uniapp 对接腾讯云IM群公告功能

UniApp 实战&#xff1a;腾讯云IM群公告功能 一、前言 在即时通讯场景中&#xff0c;群公告是信息同步的重要渠道。本文将基于uniapp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群公告的发布、修改、历史记录查询等核心功能。 群公告的数据结构设计权限校…...

垂起固定翼无人机应用及技术分析

一、主要应用行业 1. 能源基础设施巡检 电力巡检&#xff1a;适用于超高压输电线路通道的快速巡查&#xff0c;实时回传数据提升智能运检效率。 油田管道监测&#xff1a;利用长航时特性&#xff08;1.5-2小时&#xff09;对大范围管道进行隐患排查&#xff0c;减少人力巡…...

Python Robot Framework【自动化测试框架】简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

vite配置@别名,以及如何让IDE智能提示路经

1.配置路径(vite.config.js) // vite.config.js import { defineConfig } from "vite"; import vue from "vitejs/plugin-vue"; import path from "path";// https://vite.dev/config/ export default defineConfig({server: {port: 8080,},plu…...

c#bitconverter操作,不同变量类型转byte数组

缘起:串口数据传输的基础是byte数组&#xff0c;write(buff,0,num)或者writeline(string)&#xff0c;如果是字符串传输就是string变量就可以了&#xff0c;但是在modbus这类hex传递时&#xff0c;就要遇到转换了&#xff0c;拼凑byte数组时需要各种变量的值传递&#xff0c;解…...

【Linux】LInux下第一个程序:进度条

前言&#xff1a; 在前面的文章中我们学习了LInux的基础指令 【Linux】初见&#xff0c;基础指令-CSDN博客【Linux】初见&#xff0c;基础指令&#xff08;续&#xff09;-CSDN博客 学习了vim编辑器【Linux】vim编辑器_linux vim insert-CSDN博客 学习了gcc/g【Linux】编译器gc…...

RPA+AI:自动化办公机器人开发指南

RPAAI&#xff1a;自动化办公机器人开发指南 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 RPAAI&#xff1a;自动化办公机器人开发指南摘要引言技术融合路径1. 传感器层&#xff1a;多模态数据接入2. 决策层&…...

daz3d + PBRSkin (MDL)+ SSS

好的&#xff0c;我们来解释一下 Daz3D 中的 PBRSkin (MDL) Shader。 简单来说&#xff0c;PBRSkin (MDL) 是 Daz Studio 中一种基于物理渲染&#xff08;PBR&#xff09;技术、专门用于创建高度逼真人物皮肤效果的着色器&#xff08;Shader&#xff09;。 它利用 NVIDIA 的材…...

计算矩阵A和B的乘积

根据矩阵乘法规则&#xff0c;编程计算矩阵的乘积。函数fix_prod_ele()是基本方法编写&#xff0c;函数fix_prod_opt()是优化方法编写。 程序代码 #define N 3 #define M 4 typedef int fix_matrix1[N][M]; typedef int fix_matrix2[M][N]; int fix_prod_ele(f…...

Houdini POP入门学习05 - 物理属性

接下来随着教程学习碰撞部分&#xff0c;当粒子较为复杂或者下载了一些粒子模板进行修改时&#xff0c;会遇到一些较奇怪问题&#xff0c;如粒子穿透等&#xff0c;这些问题实际上可以通过调节参数解决。 hip资源文件&#xff1a;https://download.csdn.net/download/grayrail…...

每日Prompt:双重曝光

提示词 新中式&#xff0c;这幅图像将人体头像轮廓与山水中式建筑融为一体&#xff0c;双重曝光&#xff0c;体现了反思、内心平静以及人与自然相互联系的主题&#xff0c;靛蓝&#xff0c;水墨画&#xff0c;晕染&#xff0c;极简...

sendDefaultImpl call timeout(rocketmq)

rocketmq 连接异常 senddefaultimpl call timeout-腾讯云开发者社区-腾讯云 第一种情况&#xff1a; 修改broker 的配置如下&#xff0c;注意brokerIP1 这个配置必须有&#xff0c;不然 rocketmq-console 显示依然是内网地址 caused by: org.apache.rocketmq.remoting.excep…...

【LLM】多智能体系统 Why Do Multi-Agent LLM Systems Fail?

note 构建一个成功的 MAS&#xff0c;不仅仅是提升底层 LLM 的智能那么简单&#xff0c;它更像是在构建一个组织。如果组织结构、沟通协议、权责分配、质量控制流程设计不当&#xff0c;即使每个成员&#xff08;智能体&#xff09;都很“聪明”&#xff0c;整个系统也可能像一…...

CSS 定位:原理 + 场景 + 示例全解析

一. 什么是CSS定位? CSS中的position属性用于设置元素的定位方式,它决定了元素在页面中的"定位行为" 为什么需要定位? 常规布局(如 display: block)适用于主结构 定位适用于浮动按钮,弹出层,粘性标题等场景帮助我们精确控制元素在页面中的位置 二. 定位类型全…...

如何在没有 iTunes 的情况下备份 iPhone

我可以在没有 iTunes 的情况下将 iPhone 备份到电脑吗&#xff1f;虽然 iTunes 曾经是备份 iPhone 的主要方法&#xff0c;但它并不是 iOS 用户唯一的备份选项。您可以选择多种方便的替代方案来备份 iPhone&#xff0c;无需使用 iTunes。您可以在这里获得更灵活、更人性化的备份…...

如何把 Mac Finder 用得更顺手?——高效文件管理定制指南

系统梳理提升 Mac Finder 体验的实用设置与技巧&#xff0c;助你用更高效的方式管理文件。文末引出进阶选择 Path Finder。 阅读原文请转到&#xff1a;https://jimmysong.io/blog/customize-finder-for-efficiency/ 作为一个用 Mac 多年的用户&#xff0c;我始终觉得 Finder 虽…...

赋能大型语言模型与外部世界交互——函数调用的崛起

大型语言模型 (LLM) 近年来在自然语言处理领域取得了革命性的进展&#xff0c;展现出强大的文本理解、生成和对话能力。然而&#xff0c;这些模型在与外部实时数据源和动态系统交互方面存在固有的局限性 1。它们主要依赖于训练阶段学习到的静态知识&#xff0c;难以直接访问和利…...

04 Deep learning神经网络编程基础 梯度下降 --吴恩达

梯度下降在深度学习的应用 梯度下降是优化神经网络参数的核心算法,通过迭代调整参数最小化损失函数。 核心公式 参数更新规则: θ t + 1 = θ t − η ∇ J ( θ...

手拉手处理RuoYi脚手架常见文问题

若依前后端分离版开发入门 基础环境&#xff1a;JDK1.8mysqlRedisMavenVue 取消登录验证码 后端 修改ruoyi-ui项目中的login.vue 在ruoyi-ui项目>src>views中找到login.vue文件 1、注释验证码展示及录入部分 2、 注释code必填校验&#xff0c;默认验证码开关为false …...

录制mp4

目录 单线程保存mp4 多线程保存mp4 rtsp ffmpeg录制mp4 单线程保存mp4 import cv2 import imageiocv2.namedWindow(photo, 0) # 0窗口大小可以任意拖动&#xff0c;1自适应 cv2.resizeWindow(photo, 1280, 720) url "rtsp://admin:aa123456192.168.1.64/h264/ch1/main…...

Dynamics 365 Finance + Power Automate 自动化凭证审核

&#x1f680; Dynamics 365 Finance Power Automate 自动化凭证审核 &#x1f4d1; 目录 &#x1f680; Dynamics 365 Finance Power Automate 自动化凭证审核1. 依赖 &#x1f527;2. 目标 &#x1f3af;3. 系统架构 &#x1f3d7;️4. 凭证审批全流程 &#x1f6e0;️4.1 …...

使用 Python + SQLAlchemy 创建知识库数据库(SQLite)—— 构建本地知识库系统的基础《一》

&#x1f4da; 使用 Python SQLAlchemy 创建知识库数据库&#xff08;SQLite&#xff09;—— 构建本地知识库系统的基础 &#x1f9e0; 一、前言 随着大模型技术的发展&#xff0c;越来越多的项目需要构建本地知识库系统来支持 RAG&#xff08;Retrieval-Augmented Generat…...

使用柏林噪声生成随机地图

简单介绍柏林噪声 柏林噪声&#xff08;Perlin Noise&#xff09;是一种由 Ken Perlin 在1983年提出的梯度噪声&#xff08;Gradient Noise&#xff09;算法&#xff0c;用于生成自然、连续的随机值。它被广泛用于计算机图形学中模拟自然现象&#xff08;如地形、云层、火焰等…...

P3 QT记事本(3.4)

3.4 文件选择对话框 QFileDialog 3.4.1 QFileDialog 开发流程 使用 QFileDialog 的基本步骤通常如下&#xff1a; 实例化 &#xff1a;首先&#xff0c;创建一个 QFileDialog 对象的实例。 QFileDialog qFileDialog;设置模式 &#xff1a;根据需要设置对话框的模式&…...

C++课设:实现简易文件加密工具(凯撒密码、异或加密、Base64编码)

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 专栏介绍&#xff1a;《编程项目实战》 目录 一、初识文件加密&#xff1a;为什么需要…...