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

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

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

0. 前言

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

1. 腐蚀与膨胀

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

1.1 为什么要做腐蚀与膨胀

去噪与分割:在二值化后的小颗粒噪声或连通区域中,腐蚀可以帮我们"吃掉"那些孤立的噪点,让结果更干净;膨胀则可填补目标内部的小孔,增强连通性。

形状变换:当需要放大或缩小目标形态时,腐蚀/膨胀提供了一种简单又高效的"膨胀器"或"压缩机"效果。

1.2 OpenCV 实现

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

python 复制代码
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()

关键函数解析:

  • 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,最后对比展示开运算后与闭运算后的效果。

python 复制代码
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 形态学梯度

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

python 复制代码
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) 时退出。

python 复制代码
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)------阈值化技术详解

相关推荐
天天扭码13 分钟前
从图片到语音:我是如何用两大模型API打造沉浸式英语学习工具的
前端·人工智能·github
Tony沈哲14 分钟前
macOS 上为 Compose Desktop 构建跨架构图像处理 dylib:OpenCV + libraw + libheif 实践指南
opencv·算法
张彦峰ZYF1 小时前
从检索到生成:RAG 如何重构大模型的知识边界?
人工智能·ai·aigc
刘海东刘海东1 小时前
结构型智能科技的关键可行性——信息型智能向结构型智能的转变(修改提纲)
人工智能·算法·机器学习
**梯度已爆炸**1 小时前
NLP文本预处理
人工智能·深度学习·nlp
uncle_ll1 小时前
李宏毅NLP-8-语音模型
人工智能·自然语言处理·语音识别·语音模型·lm
Liudef061 小时前
FLUX.1-Kontext 高效训练 LoRA:释放大语言模型定制化潜能的完整指南
人工智能·语言模型·自然语言处理·ai作画·aigc
静心问道1 小时前
大型语言模型中的自动化思维链提示
人工智能·语言模型·大模型
众链网络2 小时前
你的Prompt还有很大提升
人工智能·prompt·ai写作·ai工具·ai智能体
汀沿河2 小时前
2 大模型高效参数微调;prompt tunning
人工智能·深度学习·prompt