You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提升使用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()

原始处理效果

处理结果1
处理结果2

优化方案
  • 二值图预处理

原始二值图边缘存在细碎噪声、内部有微小空洞,这些都会导致骨架提取时生成大量异常分支。可以在二值化后先做形态学操作平滑边缘,用skimage.morphology里的binary_opening、binary_closing处理,或者直接用remove_small_objects、remove_small_holes过滤掉不需要的微小区域。

  • 算法参数调整

  1. medial_axis可以同步返回距离变换结果,可根据距离值过滤掉对应原图中过窄区域生成的无效骨架,避免噪声导致的杂线
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 09:36:04