第12篇:骨架化算法 — 将晶粒边界细化为单像素线条

📅 2026/7/9 17:26:45
第12篇:骨架化算法 — 将晶粒边界细化为单像素线条
第12篇:骨架化算法 — 将晶粒边界细化为单像素线条一、为什么需要骨架化?1.1 问题的提出深度学习模型输出的分割结果中,晶粒边界往往是有一定宽度的"粗线"。这是因为:模型预测的不确定性:边界区域的像素概率是渐变的,阈值化后会形成有宽度的区域真实边界的复杂性:实际晶粒边界本身就有一定厚度标注误差:训练数据的人工标注也不可能达到单像素精度但在后续的截线法测量中,我们需要精确知道"边界在哪里"。如果边界是粗的,检测线与边界的交点就会是一个线段而非一个点,这会给交点检测带来困难。1.2 骨架化的核心思想骨架化(Skeletonization),也叫图像细化,是形态学图像处理中的经典操作。它的目标是:将一个连通区域"抽成"单像素宽度的"骨架",同时保持原区域的连通性和拓扑结构。形象地说,就像把一根粗树枝"削"成细木棍,但木棍的长度和分叉结构不变。对于晶粒边界检测来说,骨架化的价值在于:精确性:将粗边界细化为单像素线,交点位置更准确一致性:无论原始边界多粗,处理后都是单像素,测量标准统一拓扑保持:保持边界的连通性,不会出现断裂二、scikit-image 的 skeletonize 算法原理2.1 算法本质:中轴变换骨架化的数学基础是中轴变换(Medial Axis Transform, MAT)。中轴可以理解为:区域内所有与边界至少有两个最近点的点的集合。想象一下,在区域内部同时从所有边界点向内"燃烧",火焰相遇的地方就是中轴(骨架)。2.2 scikit-image 的实现方式scikit-image 的skeletonize函数采用的是张-孙快速并行细化算法(Zhang-Suen thinning algorithm)。这是一种迭代式的形态学算法。算法步骤Zhang-Suen算法通过两次子迭代重复进行,直到没有像素可以被删除:第一次子迭代:标记满足以下所有条件的像素P1进行删除:像素P1是前景(值为1)P1不是端点(8邻域中至少有2个前景像素)P1是简单点(删除后不改变连通性)P2、P4、P6至少有一个是背景P4、P6、P8至少有一个是背景第二次子迭代:类似,但条件4和5改为:4. P2、P4、P8至少有一个是背景5. P2、P6、P8至少有一个是背景其中P2-P8是P1的8邻域像素,按顺时针排列。算法特点并行性:每轮迭代中,所有满足条件的像素同时被标记,然后一起删除收敛性:经过有限次迭代后,不再有像素可删除,算法终止8连通性:保持8邻域连通性三、二值化预处理在进行骨架化之前,需要先对图像进行二值化处理。这是因为骨架化算法要求输入是二值图像(只有0和1两种值)。3.1 为什么需要反相二值化?在GrainServer中,使用的是THRESH_BINARY_INV(反向二值化):_,binary=cv2.threshold(img,128,255,cv2.THRESH_BINARY_INV)代码位置:ImgProcessor/ImgUtils.py:40原因是:模型输出:晶粒边界是白色(255),背景是黑色(0)骨架化约定:scikit-image的skeletonize函数默认处理"前景"区域,即值为1的区域我们的目标:对晶粒边界进行骨架化,所以需要边界是"前景"等等,这里似乎有矛盾。让我们仔细理一理:模型输出中,边界是白色(255),内部是黑色(0)。如果直接做骨架化,应该对白色区域(边界)进行骨架化才对。但为什么用了THRESH_BINARY_INV呢?让我们看完整的代码流程:_,binary=cv2.threshold(img,128,255,cv2.THRESH_BINARY_INV)skeleton=skeletonize