如何提升使用medial_axis生成的图像骨架的质量
问题描述
尝试使用medial_axis函数提取图像骨架时输出结果杂乱,测试skeletonize函数生成的骨架效果更好,但仍不符合预期。
原始图像

原始代码
import matplotlib.pyplot as plt from skimage.io import imread from skimage.filters import threshold_otsu from skimage.morphology import medial_axis def Get_binary(image): thresh = threshold_otsu(image) binary = image > thresh return binary def Skeletonize_img(): im = Get_binary(imread('image_bin.png')) im_ax = medial_axis(im) fig, axes = plt.subplots(nrows=1, ncols=2, sharex=True, sharey=True, figsize=(8,8)) ax = axes.ravel() ax[0].imshow(im, cmap=plt.cm.gray) ax[0].set_title('binary image') ax[1].imshow(im_ax, cmap=plt.cm.gray) ax[1].set_title('medial axis') plt.tight_layout() plt.show() Skeletonize_img()
原始处理效果


优化方案
二值图预处理
原始二值图边缘存在细碎噪声、内部有微小空洞,这些都会导致骨架提取时生成大量异常分支。可以在二值化后先做形态学操作平滑边缘,用skimage.morphology里的binary_opening、binary_closing处理,或者直接用remove_small_objects、remove_small_holes过滤掉不需要的微小区域。
算法参数调整
medial_axis可以同步返回距离变换结果,可根据距离值过滤掉对应原图中过窄区域生成的无效骨架,避免噪声导致的杂线skeletonize支持两种算法:默认的Zhang-Suen算法,和method='lee'的Lee算法,后者生成的骨架连续性更强,更适合提取长条形目标的中心线
骨架后处理
提取完骨架后,直接调用skimage.morphology.remove_small_objects函数,设定合适的最小长度阈值,就能批量删除不符合长度要求的杂乱分支,大幅提升结果整洁度。
优化后示例代码
import matplotlib.pyplot as plt from skimage.io import imread from skimage.filters import threshold_otsu from skimage.morphology import medial_axis, skeletonize, remove_small_objects, binary_closing, disk def Get_binary(image): thresh = threshold_otsu(image) binary = image > thresh # 形态学平滑处理:半径2的圆盘结构元做闭运算,填补小孔、平滑边缘 binary = binary_closing(binary, footprint=disk(2)) # 移除小于30像素的微小噪点和内部空洞 binary = remove_small_objects(binary, min_size=30) binary = remove_small_objects(~binary, min_size=30) return ~binary def Skeletonize_img(): im = Get_binary(imread('image_bin.png')) # 选用Lee算法提取骨架,连续性更好 im_sk = skeletonize(im, method='lee') # 后处理:移除长度小于20像素的杂散小分支 im_sk_clean = remove_small_objects(im_sk, min_size=20) fig, axes = plt.subplots(nrows=1, ncols=3, sharex=True, sharey=True, figsize=(12,4)) ax = axes.ravel() ax[0].imshow(im, cmap=plt.cm.gray) ax[0].set_title('预处理后二值图') ax[1].imshow(im_sk, cmap=plt.cm.gray) ax[1].set_title('原始骨架结果') ax[2].imshow(im_sk_clean, cmap=plt.cm.gray) ax[2].set_title('后处理后干净骨架') plt.tight_layout() plt.show() Skeletonize_img()
代码中的disk半径、min_size数值可根据实际图像分辨率和需求调整,数值越大过滤强度越高。
内容的提问来源于stack exchange,提问作者just dude
相关产品推荐
相关产品推荐

