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.erode
与 cv2.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()
关键函数解析:
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_OPEN
与 MORPH_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
,提取该层“细丝”
将edge
与skeleton
做按位或,累加骨架
更新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)——阈值化技术详解