mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6mobile wallpaper 7mobile wallpaper 8mobile wallpaper 9mobile wallpaper 10mobile wallpaper 11mobile wallpaper 12mobile wallpaper 13
3687 字
11 分鐘
形态学图像处理
2026-04-27

第 9 章 形态学图像处理#

学习目标:掌握基于集合论的形状分析工具——腐蚀、膨胀、开、闭、顶帽、黑帽、击中-未击中、骨架化、距离变换,理解它们如何解决实际的”形状问题”。 形态学(Morphology)= 形状的学问,由法国学派(Matheron, Serra)在矿物分析中诞生,1960-80 年代发展为独立分支。


9.1 集合论基础#

9.1.1 为什么用集合?#

二值图像 = 一个平面上的点集: [ A = {(x, y) : f(x, y) = 1} ]

  • 前景 = 集合内点(1)
  • 背景 = 集合补(0)

形态学 = 用集合运算操作形状

9.1.2 基本集合运算#

运算符号定义
(A \cup B)(x \in A \text{ or } x \in B)
(A \cap B)(x \in A \text{ and } x \in B)
(A^c)(x \notin A)
(A - B)(A \cap B^c)
平移((A)_z)({a + z : a \in A})
反射(\hat{B})({-b : b \in B})

9.1.3 结构元 (Structuring Element, SE)#

核心概念。SE 是一个小”探针”,用来”扫描”图像做形状分析。

常见 SE:

方形 3×3: 十字 3×3: 线段 5×1:
┌─┬─┬─┐ ┌─┬─┬─┐
│■│■│■│ │ │■│ │ ■■■■■
├─┼─┼─┤ ├─┼─┼─┤
│■│■│■│ │■│■│■│
├─┼─┼─┤ ├─┼─┼─┤
│■│■│■│ │ │■│ │
└─┴─┴─┘ └─┴─┴─┘
圆盘 5×5:
┌─┬─┬─┬─┬─┐
│ │■│■│■│ │
│■│■│■│■│■│
│■│■│■│■│■│
│■│■│■│■│■│
│ │■│■│■│ │
└─┴─┴─┴─┴─┘

SE 的原点(origin,通常是中心)决定平移位置。

import cv2
se_rect = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
se_ellipse= cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
se_cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))

9.2 腐蚀与膨胀(两大基础运算)#

9.2.1 腐蚀 (Erosion)#

定义 9.1: [ A \ominus B = {z : (B)_z \subseteq A} ]

直觉:SE (B) 在图像 (A) 内”完全装得下”的所有中心位置。

A (前景): B (3×3 方块): A⊖B:
█████████ █████
█████████ ■■■ █████
█████████ ■★■ █████ ← 边界向内缩一圈
█████████ ■■■
█████████

效果

  • 前景变小 / 边界向内收缩
  • 小物体(比 B 还小)被完全消除
  • 连在一起的物体可能分开
  • 窄连接处被切断
eroded = cv2.erode(binary, kernel, iterations=1)

9.2.2 膨胀 (Dilation)#

定义 9.2: [ A \oplus B = {z : (\hat{B})_z \cap A \ne \emptyset} ]

直觉:SE 反射后,与 (A) 有任何重叠的所有中心位置。

等价:(A \oplus B = \bigcup_{a \in A} (B)_a)(把 B 贴在 A 的每个点上,取并)

A: A⊕B:
█████ █████████
█████ → █████████
█████ █████████ ← 向外膨胀一圈

效果

  • 前景变大 / 边界向外扩展
  • 填充小孔、裂缝
  • 连接邻近的物体(注意:可能过度连接)
dilated = cv2.dilate(binary, kernel, iterations=1)

9.2.3 对偶性#

腐蚀和膨胀是对偶的(De Morgan 律的形态学版本):

[ (A \ominus B)^c = A^c \oplus \hat{B} ]

意义:对前景腐蚀 = 对背景膨胀(反之亦然)。

9.2.4 性质#

  • 平移不变:((A)_z \ominus B = (A \ominus B)_z)
  • 增函数:(A \subseteq B \Rightarrow A \ominus C \subseteq B \ominus C)
  • 结合性:(A \oplus (B \oplus C) = (A \oplus B) \oplus C)(级联 SE 等价于大 SE)

实用性质

  • 两个 3×3 膨胀 = 一次 5×5 膨胀
  • N 次 3×3 = 一次 ((2N+1) \times (2N+1))
  • 大 SE 可拆为小 SE 级联 → 加速(FPGA/嵌入式常用)

9.2.5 灰度图像的腐蚀/膨胀#

对灰度图扩展: [ (A \ominus B)(x) = \min_{s \in B} {A(x + s)} ] [ (A \oplus B)(x) = \max_{s \in B} {A(x + s)} ]

局部最小 / 最大滤波


9.3 开运算与闭运算#

9.3.1 开运算 (Opening)#

[ A \circ B = (A \ominus B) \oplus B ]

流程:先腐蚀,再膨胀。

直觉:让 SE 在 (A) 内部”滚动”,能滚到的地方 = (A \circ B)。

A (有小点 + 细连): A ⊖ B: A ⊖ B ⊕ B:
██ ██ · ██ ██ ██ ██
██████· → ████ → ██████
██ ██· ██ ██ ██ ██
↑ 小点消失
细连接断开后不恢复

效果

  • 去除小物体(比 SE 小的)
  • 断开细连接
  • 平滑轮廓(凸出物被磨平)
  • 物体大小基本不变(主体被保留)

9.3.2 闭运算 (Closing)#

[ A \bullet B = (A \oplus B) \ominus B ]

流程:先膨胀,再腐蚀。

直觉:让 SE 在 (A) 的外部滚动,填不进去的地方 = (A \bullet B)。

效果

  • 填充小孔(比 SE 小的)
  • 连接近邻物体
  • 平滑轮廓(凹陷处被填)

9.3.3 开 vs 闭:对偶#

[ (A \circ B)^c = A^c \bullet \hat{B} ]

开对前景 = 闭对背景。

9.3.4 幂等性#

[ (A \circ B) \circ B = A \circ B ] [ (A \bullet B) \bullet B = A \bullet B ]

再做一次开 / 闭,结果不变。这是其他组合没有的性质。

9.3.5 典型应用#

指纹去毛刺

原图:指纹 + 细小噪点
→ 开运算去噪点

连通断裂字符

OCR 中字符扫描残缺
→ 闭运算补全

车牌预处理

去除小噪声(开)→ 合并小字符间的间隙(闭)
opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

9.4 击中-未击中变换 HMT#

9.4.1 动机#

想检测图像中特定形状的出现位置(如十字形、拐角)。

9.4.2 定义#

两个 SE:(B_1)(前景模板)、(B_2)(背景模板),通常 (B_1 \cap B_2 = \emptyset)。

[ A \otimes B = (A \ominus B_1) \cap (A^c \ominus B_2) ]

直觉:寻找满足

  • “(B_1) 在 (A) 内”(前景匹配)
  • “(B_2) 在 (A) 外”(背景匹配)

的所有位置。

9.4.3 应用:角点检测#

想找”左上角”(前景在右下、背景在左上):

B_1: B_2:
│ · · ·│ │■ ■ ·│
│· ■ ■│ │■ · ·│
│· ■ ■│ │· · ·│

击中位置 = 所有左上角点。

9.4.4 细化、增厚(基于 HMT)#

细化 (Thinning): [ A \oslash B = A - (A \otimes B) ]

反复用不同方向的 (B),逐步去除前景边界上”非结构性”的点。

增厚反向。


9.5 基本形态学算法#

9.5.1 边界提取#

[ \partial A = A - (A \ominus B) ]

前景 - 腐蚀后前景 = 边界。3×3 SE 给出 1 像素厚边界。

9.5.2 区域填充(孔洞填充)#

目的:二值图中某物体内有小黑洞,想填实。

算法

X_0 = 孔洞内某点
X_k = (X_{k-1} ⊕ B) ∩ A^c (膨胀 + 只在背景内增长)
重复直到 X_k = X_{k-1}
填充结果 = X_k ∪ A

OpenCV:

# 洞填充:先求背景的 flood fill 然后取反
h, w = binary.shape
mask = np.zeros((h+2, w+2), np.uint8)
cv2.floodFill(binary.copy(), mask, (0, 0), 255)
filled = binary | cv2.bitwise_not(binary) # 简化示意

9.5.3 连通分量提取#

4-连通 vs 8-连通

4-连通: 只考虑上下左右 8-连通: 加上对角
· ■ · ■ ■ ■
■ ★ ■ ■ ★ ■
· ■ · ■ ■ ■

算法(两遍扫描):

第一遍:逐像素扫描
若当前前景:
看上/左邻居的标签
最小的标签赋给当前
若两邻居标签不同,记录"等价"
第二遍:根据等价合并标签

OpenCV:

num_labels, labels = cv2.connectedComponents(binary, connectivity=8)
num, labels, stats, centroids = cv2.connectedComponentsWithStats(binary)
# stats[i] = [x, y, w, h, area]

用途:目标计数(细胞、米粒)、去小物体(面积阈值)。

9.5.4 凸包#

定义:包含前景的最小凸集。

形态学算法(Gonzalez):用 4 个 HMT 模板反复增厚直到收敛。

实用:OpenCV 的 cv2.convexHull 基于 Graham 扫描或 Sklansky 算法,比形态学方法快。

9.5.5 细化(骨架化前奏)#

目标:把宽条缩成 1 像素宽的”骨架”。

HMT 细化(Guo-Hall / Zhang-Suen):反复用 8 个方向 HMT 去除边界像素,保持连通。


9.6 骨架化 (Skeletonization)#

9.6.1 骨架的直觉:最大内切圆心轨迹#

定义 9.3(Blum 中轴):前景内所有点 (p),存在至少两个最近的背景点,则 (p) 在骨架上。

等价直觉:想象同时从前景所有边界点向内””,相遇的地方就是骨架。

矩形: 骨架:
█████████ · · · · · · · · ·
█████████ · · · ━━━━━ · · ·
█████████ → · · · · · · · · ·
█████████ · · · · · · · · ·

9.6.2 形态学定义#

[ S(A) = \bigcup_{k=0}^{K} S_k(A) ] [ S_k(A) = (A \ominus kB) - [(A \ominus kB) \circ B] ]

  • (kB) 表示 SE (B) 的 (k) 次膨胀
  • ((A \ominus kB)):腐蚀 (k) 次
  • 再减去对它开运算的结果

性质

  • 骨架是前景的细骨架表示
  • 可以从 (S) 重建 (A)(用最大内切圆):(A = \bigcup_{k} (S_k \oplus k B))

9.6.3 快速骨架化(Zhang-Suen 1984)#

算法

对每个前景像素 p,检查 8 邻居 (p1..p8):
条件 1: 2 ≤ N(p) ≤ 6 (N = 前景邻居数)
条件 2: S(p) = 1 (0→1 跃迁次数)
条件 3: p1·p3·p5 = 0 (子迭代 1) 或 p1·p3·p7 = 0 (子迭代 2)
条件 4: p3·p5·p7 = 0 (子迭代 1) 或 p1·p5·p7 = 0 (子迭代 2)
若四条件都满足 → 标记删除
两轮子迭代交替执行,直到无变化

效果:保证连通、1 像素宽、中心化。

应用

  • OCR 字符预处理
  • 指纹脊线提取
  • 血管追踪
  • 手写识别
from skimage.morphology import skeletonize
skel = skeletonize(binary > 0)

9.7 距离变换#

9.7.1 定义#

定义 9.4:对二值图像 (A),距离变换 (D) 满足: [ D(x) = \min_{y \in A^c} \text{dist}(x, y) ]

每个前景像素到最近背景的距离。

二值图: 距离变换 (D8, 8-连通):
0 0 0 0 0 0 0 0 0 0
0 1 1 1 0 0 1 1 1 0
0 1 1 1 0 0 1 2 1 0 ← 中心离背景 2 步
0 1 1 1 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0

9.7.2 距离度量#

度量公式备注
D4 (曼哈顿)(|dx| + |dy|)菱形扩展
D8 (切比雪夫)(\max(|dx|, |dy|))正方形扩展
欧氏(\sqrt{dx^2 + dy^2})各向同性
倒角整数近似欧氏(3-4、5-7-11)速度+质量折衷

9.7.3 计算算法#

串行两遍扫描(Rosenfeld)#

前向扫描 (从左上到右下):
D(x, y) = min( D(x, y) 原值,
D(x-1, y) + 1,
D(x, y-1) + 1,
D(x-1, y-1) + sqrt(2),
D(x+1, y-1) + sqrt(2) )
反向扫描 (从右下到左上):
类似,考虑反方向邻居

复杂度 (O(N)),线性时间。

Felzenszwalb-Huttenlocher 2004:严格欧氏 (O(N))#

基于抛物线下包络,现代标准。

dist = cv2.distanceTransform(binary, cv2.DIST_L2, 5)

9.7.4 应用#

骨架化#

距离变换后,局部极大值位置 ≈ 骨架(每个极大值是一个最大内切圆心)。

分水岭分割(第 10 章)#

以距离变换为”地形高度”,距离大的点作为 marker → 分水岭分割粘连物体。

形状分析#

  • 形状内切圆半径 = 最大距离值
  • 形状厚度分布直方图

9.8 顶帽与黑帽变换#

9.8.1 顶帽 (Top-Hat)#

[ \text{TH}(A) = A - (A \circ B) ]

直觉:原图 - 开运算。

  • 开运算去除了 比 SE 小的前景细节
  • 相减得到的就是那些细节

提取:比 SE 小、亮度高(在暗背景上)的结构。

9.8.2 黑帽 (Bottom-Hat / Black-Hat)#

[ \text{BH}(A) = (A \bullet B) - A ]

直觉:闭运算 - 原图。

  • 闭运算填充了 比 SE 小的暗细节 / 孔
  • 相减得到那些细节

提取:比 SE 小、亮度低(暗细节)的结构。

9.8.3 应用:非均匀光照校正#

经典场景:打印物体 + 不均匀光照 → OCR 困难。

做法(灰度形态学):

se = cv2.getStructuringElement(cv2.MORPH_RECT, (51, 51)) # 大 SE
background = cv2.morphologyEx(gray, cv2.MORPH_OPEN, se)
corrected = cv2.subtract(gray, background) # = top-hat
# 现在可以清晰二值化
_, binary = cv2.threshold(corrected, 0, 255, cv2.THRESH_OTSU)

原理

  • 大 SE 的开运算 ≈ 光照背景(因为它”滚”过细节,保留粗尺度趋势)
  • 原图 - 背景 = 前景(与光照无关)

这是形态学在文档处理的最经典应用。


9.9 灰度形态学与重建#

9.9.1 灰度 SE#

灰度形态学中 SE 也是灰度(可有高度)。基本运算扩展为极值运算(9.2.5)。

9.9.2 形态学重建#

标记图 (F) + 掩膜 (G): [ R_G(F) = \lim_{n \to \infty} (F \oplus B) \wedge G ] (反复膨胀 F,但每次都用 G 截断,直到收敛)

用途

  • 断开粘连的细胞:以距离变换局部极大为标记,重建
  • 提取特定形状的对象:标出想要的位置,重建即可
  • 顶帽重建(Opening by Reconstruction):比普通开运算更好地保留原形状

9.10 实战:形态学处理的设计思路#

9.10.1 常见问题清单#

问题用什么
去小噪点开运算
补小孔闭运算
连接字符闭运算(水平 SE)
断开粘连开运算(圆盘 SE)
提取粗尺度背景大 SE 的开运算
校正不均匀光照顶帽变换
提取边界(A - (A \ominus B))
骨架Zhang-Suen / 距离变换
最大内切圆距离变换的极大
形状匹配HMT
连通分量计数connectedComponents

9.10.2 SE 形状的选择#

SE保留什么
圆盘各向同性(无方向偏好)
水平线水平结构(线条、文字行)
垂直线垂直结构
方形简单 + 快(仅轻微方向偏向)
十字简单且稍少像素

经验:形状分析用圆盘;方向敏感检测用线段;通用场合用方形(最快)。

9.10.3 SE 大小#

SE 大小 = “要去除 / 保留的尺度”。

  • 去比 10 像素小的噪点 → 11×11 或更小
  • 连接间距 < 5 的字符 → 5×1 水平 SE 闭运算
  • 校正 100 像素尺度的光照 → 101×101 开运算

9.11 本章要点与面试考点#

✅ 必须掌握#

  • 腐蚀、膨胀的集合定义与直觉
  • 开 / 闭运算的公式、幂等性、去小物体/补小孔
  • 腐蚀与膨胀的对偶性
  • 击中-未击中变换
  • 边界提取、孔洞填充、连通分量
  • 骨架化的三种思路(形态学、HMT、距离变换)
  • 顶帽/黑帽及其在光照校正的应用
  • 灰度形态学 = 极值滤波

💡 高频面试题#

Q1. 开运算和闭运算分别能解决什么问题?

答:

  • 开 (Open) = 先腐蚀后膨胀 → 去除比 SE 小的前景(小噪点、细连接)
  • 闭 (Close) = 先膨胀后腐蚀 → 填充比 SE 小的孔、连接近邻物体
  • 两者都能平滑轮廓,但开磨凸出,闭填凹陷

Q2. 为什么顶帽变换能提取非均匀光照下的细节?

答:用大 SE 的开运算对灰度图处理,结果近似光照背景(大尺度缓变)。原图减去它 = 前景细节(高频信息),与光照无关。这就是”TopHat = 原图 - 开运算”。

Q3. 灰度形态学的腐蚀等价于什么滤波?

答:局部最小滤波。灰度腐蚀 ((A \ominus B)(x) = \min_{s \in B} A(x + s)),即邻域最小值。膨胀为最大值滤波。开运算 = min 后 max(低通+保边)。

Q4. 骨架化的几种方法有什么区别?

答:

  • 形态学骨架((S = \bigcup S_k)):严格、可重建原形,但骨架可能不连通
  • HMT 细化(Zhang-Suen):保证连通、1 像素宽,但对噪声敏感
  • 距离变换极大值:简单、快,但极大值可能不连续

工业上常用 Zhang-Suen(连通性好)。

Q5. 连通分量的 4-连通和 8-连通有何区别?

答:4-连通只考虑上下左右 4 邻居(产生菱形邻域),8-连通包括对角 8 邻居(方形邻域)。拓扑悖论:前景和背景若都用 4(或都用 8),可能出现连通性矛盾。标准做法:前景 8-连通 + 背景 4-连通

Q6. 腐蚀和膨胀的对偶性有何工程意义?

答:((A \ominus B)^c = A^c \oplus \hat{B}) 意味着:对前景做腐蚀 = 对背景做膨胀。实现时只需一个操作,另一个由取反得到。也解释了开/闭的对偶:开 ↔ 闭。

Q7. 击中-未击中与模板匹配的区别?

答:HMT 用两个 SE 分别匹配前景与背景模板,严格形状检测(二值);模板匹配(如 SAD/NCC)基于灰度相关,连续灰度图。HMT 对少量噪声脆弱;匹配对光照和噪声鲁棒但慢。

Q8. 为什么形态学操作能级联加速?

答:结合律 ((A \oplus B) \oplus C = A \oplus (B \oplus C))。一个大 SE 可分解为小 SE 的级联(如 9×9 = 3×3 + 3×3 + 3×3),每次只做 3×3 卷积,总复杂度 (O(9N)) << (O(81N))。圆盘 SE 的近似分解也常用。


9.12 延伸阅读#

  • Matheron, Random Sets and Integral Geometry(形态学创始文献)
  • Serra, Image Analysis and Mathematical Morphology(奠基教材)
  • Soille, Morphological Image Analysis: Principles and Applications(工程手册)
  • Zhang & Suen, “A Fast Parallel Algorithm for Thinning Digital Patterns”, 1984
  • Felzenszwalb & Huttenlocher, “Distance Transforms of Sampled Functions”, 2012
  • scikit-image morphology:https://scikit-image.org/docs/stable/api/skimage.morphology.html

下一章:我们把”形态学”拓展到”语义”——如何让算法自动理解”哪些像素属于同一个物体”?这就是图像分割

分享

如果這篇文章對你有幫助,歡迎分享給更多人!

形态学图像处理
https://lemusakuya.com/posts/study-notes/digital-image-processing/09_形态学图像处理/
作者
レム・咲く夜
發布於
2026-04-27
許可協議
CC BY-NC-SA 4.0

部分資訊可能已經過時

目錄