一、简介
在数字图像处理中,二值图像的骨架提取操作非常常用。骨架(skeleton)提取也称为细化(thinning), 它被用来获取区域中2个(或多个)边界的像素中心线,使该区域的表达更加简洁、更方便处理。
骨架提供了非常好的形状描述,便于物体形状结构、拓扑描述和特征提取,如长度、分叉等。
二、常用方法介绍
骨架细化常用方法分为两大类:
OpenCV中实现的两种方法分别是Zhang-Suen和Guo-Hall方法,代码如下:
opencv细化算法github.com/opencv/opencv_contrib/blob/master/modules/ximgproc/src/thinning.cpp
功能实现的独立性非常好,直接拷贝移植就可以放在自己的C++工程中使用。
ZS 算法实现原理:
ZS算法是1984年提出的非常流行和有良好证明的细化方法。它是一种基于3x3模板的迭代平行细化算法。
算法过程有两个子迭代过程,在两个过程里分别删除满足一定模板结构的点。
GH算法实现原理:
在ZS算法上修改迭代条件细节。完善了ZS算法的缺点。
下面图像展示了不同的细化效果。
如果你认为此刻就可以安心使用细化算法的话,那就错了。这两个算法都有其本身原理缺陷,具体选择哪个方法还需要依据二值图像特征来判断。
ZS算法的表现:
ZS算法非常简单高效。但是不能准准确细化2x2矩形像素和2个像素宽的倾斜线(无论从左到右还是从右到左方向)。
GH算法的表现:
GH算法是在ZS算法上改进的两个子阶段的并行细化算法。它可以处理ZS算法的2个像素宽线无法细化的缺陷,获取结果的迭代次数比ZS算法也要少。
但对分支点保留不一定有很好的效果,如小鸡手办胸前饰品的细化效果。
两种细化算法对图像边界的区域细化效果如下,实际开发中可以根据项目需求去除贴近边界的前景像素。
三、应用举例
1. 拓扑分支之端点交叉点提取, 见下一篇 [二值图像处理] 骨架线提取、骨架端点、交叉点提取-优快云博客
2. 提取线条曲线的宽度
如果我们想获取弯曲线条各个区域的像素宽度该怎么处理呢,查找边缘斜率然后用垂线测量?这个方法显然比较复杂,而且对边缘粗糙的区域处理效果并不理想。 这里可以使用距离变换图 + 骨架的方法来计算宽度,具体步骤如下:
- 获取骨架图
- 获取距离变换图
- 遍历骨架,读取距离变换图对应位置数值再乘以2,即可得到该处的像素宽度。
参考
https://imagemagick.org/Usage/morphology/#thinning
[J] A Survey of Thinning Techniques on Two Dimensional Binary Images
[J] T. Y. Zhang and C. Y. Suen, “A Fast Parallel Algorithm for Thinning Digital Patterns”
[J] Z. Guo and R. Hall, “Parallel thinning with two-sub iteration algorithms”