如何使用Python提取二值图像已有轮廓的中心线
二值图像轮廓中心线提取Python实现
依赖安装
首先安装所需第三方库:pip install opencv-python numpy scikit-image
实现方法
方法一:骨架化算法(推荐用于边缘连续的封闭/半封闭轮廓)
原理为逐层剥离前景区域的边缘像素,最终保留单像素宽度的中轴作为中心线,实现逻辑简单,适配大部分场景:
import cv2 import numpy as np from skimage.morphology import skeletonize # 读取二值图像,参数0表示以灰度模式读取 binary = cv2.imread("输入二值图路径.png", 0) # 强制二值化,确保只有0和255两个像素值 _, binary = cv2.threshold(binary, 127, 255, cv2.THRESH_BINARY) # 转为0-1值域适配骨架化接口 binary_norm = binary // 255 # 提取中心线 skeleton = skeletonize(binary_norm) # 转回0-255值域用于保存 result = (skeleton * 255).astype(np.uint8) cv2.imwrite("中心线结果.png", result)
方法二:距离变换+峰值筛选(推荐用于轮廓粗细不均的场景)
通过计算每个前景像素到最近背景像素的距离,距离峰值区域即为中心线位置,可灵活调整阈值适配不同粗细的轮廓:
import cv2 import numpy as np from skimage.morphology import skeletonize binary = cv2.imread("输入二值图路径.png", 0) _, binary = cv2.threshold(binary, 127, 255, cv2.THRESH_BINARY) # 计算距离变换,DIST_L2表示用欧氏距离 dist = cv2.distanceTransform(binary, cv2.DIST_L2, 5) # 归一化距离结果到0-1区间 cv2.normalize(dist, dist, 0, 1, cv2.NORM_MINMAX) # 筛选距离大于最大距离20%的区域作为中心线候选,阈值可自行调整 _, center_candidate = cv2.threshold(dist, 0.2 * dist.max(), 255, cv2.THRESH_BINARY) center_candidate = center_candidate.astype(np.uint8) # 细化得到单像素中心线 result = (skeletonize(center_candidate//255) * 255).astype(np.uint8) cv2.imwrite("中心线结果.png", result)
注意事项
- 输入二值图需保证轮廓区域为白色(255),背景为黑色(0),如果颜色相反可调用
cv2.bitwise_not(binary)翻转后再处理 - 若已经提前提取到轮廓坐标,可先创建空白画布将轮廓填充为白色前景,再调用上述方法,结果更稳定
- 阈值参数可根据实际图像的轮廓粗细调整,轮廓越粗阈值可适当调高,避免中心线出现多余分支
内容的提问来源于stack exchange,提问作者Qimin Chen
相关产品推荐
相关产品推荐

