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

基于skimage提取纤维图像骨架出现多余环路的优化咨询

纤维图像骨架提取冗余环路问题优化

问题描述

我是图像处理领域的初学者,目前正开展纤维图像处理相关工作,调用skimage库的形态学函数生成图像骨架,但生成的骨架周边存在大量不必要的小型环路/圆圈,需要为图像中的每一根纤维生成单独的中轴线路径(即骨架)。
当前使用的骨架生成代码如下:

import cv2
import numpy as np
from skimage import morphology

img = cv2.imread('img.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 膨胀和阈值处理
kernel = np.ones((2, 2), np.uint8)
dilated = cv2.dilate(gray, kernel, iterations=1)
ret, thresh = cv2.threshold(dilated, 215, 255, cv2.THRESH_BINARY_INV)
cv2.imwrite('Binary.jpg',thresh)

# 骨架提取
skeleton = morphology.skeletonize(thresh, method='lee')
skeleton = morphology.remove_small_objects(skeleton.astype(bool), 100, connectivity=2)
cv2.imwrite('Skeleton.jpg',skeleton*255)

参考效果示意图:
参考示意图

优化方案

生成的骨架带大量小环路,核心原因是二值化后的纤维边缘存在大量细小毛刺、凹坑,以及边缘围合形成的微型孔洞,这些不规则结构在骨架提取时会被直接保留形成环路。原代码仅做了单次2x2核膨胀就直接提取骨架,完全没有处理这些边缘缺陷,按以下步骤调整即可得到无冗余环路的单根纤维中轴线:

  • 二值化前增加轻度高斯模糊,压制图像噪点,避免阈值分割后出现孤立噪点和边缘锯齿
  • 二值化后增加形态学开闭运算:开运算去除纤维边缘向外凸起的细小毛刺,闭运算填补边缘向内凹陷的小缺口,先将纤维轮廓打磨平滑
  • 调用remove_small_holes过滤二值图中所有面积小于阈值的微型孔洞,从根源消除环路生成的可能,阈值可根据图像中纤维粗细调整,一般在50-200像素区间测试即可
  • 骨架提取后增加剪枝操作,清理连在主骨架上的极短分支;remove_small_objects仅能清除孤立噪块,无法清除和主骨架相连的短分支
  • 如果lee方法生成的骨架仍有瑕疵,可切换为medial_axis方法测试,该方法对边缘小缺陷的容忍度更高,生成的中轴线更贴合纤维中心位置。

优化后的完整可运行代码:

import cv2
import numpy as np
from skimage import morphology, measure

img = cv2.imread('img.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 加高斯模糊压制噪点,减少边缘锯齿
blur = cv2.GaussianBlur(gray, (3,3), 0)
ret, thresh = cv2.threshold(blur, 215, 255, cv2.THRESH_BINARY_INV)

# 形态学预处理:开运算去毛刺、闭运算填凹坑
kernel = np.ones((3,3), np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1)

# 清除小型孔洞,从根源消除环路
thresh_bool = thresh.astype(bool)
thresh_clean = morphology.remove_small_holes(thresh_bool, area_threshold=100, connectivity=2)
thresh_clean = (thresh_clean * 255).astype(np.uint8)
cv2.imwrite('Binary_clean.jpg', thresh_clean)

# 骨架提取,可根据效果切换method为'medial_axis'测试
skeleton = morphology.skeletonize(thresh_clean, method='lee')
# 移除孤立小噪块
skeleton = morphology.remove_small_objects(skeleton, min_size=50, connectivity=2)

# 骨架剪枝:先做轻度thin平滑,再通过连通域分析删除长度小于30像素的短分支
skeleton_pruned = morphology.thin(skeleton, max_num_iter=5)
labeled_skeleton = measure.label(skeleton_pruned, connectivity=2)
for region in measure.regionprops(labeled_skeleton):
    if region.area < 30:
        skeleton_pruned[labeled_skeleton == region.label] = 0

cv2.imwrite('Skeleton_clean.jpg', skeleton_pruned.astype(np.uint8)*255)

代码中的形态学核大小、孔洞面积阈值、短分支长度阈值都可以根据实际图像的纤维粗细调整:如果纤维直径较粗,可适当调大核尺寸和面积阈值;如果纤维较细则调低对应阈值,避免误删正常纤维结构。

内容的提问来源于stack exchange,提问作者Sushil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:03:22