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

发布于:2025-06-05 ⋅ 阅读:(22) ⋅ 点赞:(0)

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)——阈值化技术详解


网站公告

今日签到

点亮在社区的每一天
去签到