python opencv图片/线条细化(骨架提取)

骨架提取,也叫二值图像细化。这种算法能将一个连通区域细化成一个像素的宽度,用于特征提取和目标拓扑表示。骨架提取与分水岭算法也属于形态学处理范畴,都放在morphology子模块内。
morphology子模块提供了两个函数用于骨架提取,分别是skeletonize()函数和medial_axis()函数。
1)skeletonize()函数
在模块:skimage.morphology.skeletonize(binary_image)下:输入和输出都是二值图像。
安装地址:pip install scikit-image -i https://pypi.tuna.tsinghua.edu.cn/simple
单张图片骨架提取,代码如下:

import cv2
from skimage import morphology
import numpy as np

img = cv2.imread('a.png', 0)   # 读取图片
_,binary = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY_INV)  # 二值化处理
cv2.imwrite("binary.png", binary)   # 保存二值化图片

binary[binary==255] = 1
skeleton0 = morphology.skeletonize(binary)   # 骨架提取
skeleton = skeleton0.astype(np.uint8)*255
cv2.imwrite("skeleton.png", skeleton)        # 保存骨架提取后的图片

效果如下,上图是二值化图,下图是细化后图

多张图片批量骨架提取处理,代码如下:

import cv2
from skimage import morphology
import numpy as np
import glob
import os

imageList = glob.glob("imgs/*.png")    # 读取原始图片路径
img_file = "skeletonize_data/"         # 保存骨架化后的图片的路径
# 确认上述地址是否存在
if not os.path.exists(img_file):
    os.mkdir(img_file)

# 批量处理图片
for item in imageList:
    # print(item)           # imgs/293718492401.pdf10.png
    img = cv2.imread(item, 0)    # 读取图片
    _, binary = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY_INV)  # 二值化处理
    # cv2.imwrite("binary.png", binary)
    binary[binary==255] = 1
    skeleton0 = morphology.skeletonize(binary)     # 图片细化(骨架提取)
    skeleton = skeleton0.astype(np.uint8)*255
    cv2.imwrite(img_file + item[5:], skeleton)     # 此处skeleton就是你需要保存的图像文件

2)骨架提取函数 medial_axis()
medial_axis就是中轴的意思,利用中轴变换方法计算前景(1值)目标对象的宽度,格式为:
skimage.morphology.medial_axis(image, mask=None, return_distance=False)
mask: 掩模。默认为None, 如果给定一个掩模,则在掩模内的像素值才执行骨架算法。
return_distance: bool型值,默认为False. 如果为True, 则除了返回骨架,还将距离变换值也同时返回。这里的距离指的是中轴线上的所有点与背景点的距离。
单张图片骨架提取,代码如下:

# 图片细化(骨架提取)单张图片处理
import cv2
from skimage import morphology
import numpy as np

img = cv2.imread('a.png', 0)     # 导入图片
_, binary = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY_INV)   # 二值化处理
binary[binary==255] = 1
skel, distance =morphology.medial_axis(binary, return_distance=True)  # 图片细化(骨架提取)
dist_on_skel = distance * skel
dist_on_skel = dist_on_skel.astype(np.uint8)*255
cv2.imwrite("xihua.png", dist_on_skel)           # 保存骨架提取后的图片

效果如下:

多张图片批量骨架提取处理,代码如下: 

# 图片细化(骨架提取)多张图片批量处理
import cv2
from skimage import morphology
import numpy as np
import glob
import os

imageList = glob.glob("imgs/*.png")    # 读取原始图片
img_file = "data/"                     # 保存骨架化后的图片的地址
# 确认上述地址是否存在
if not os.path.exists(img_file):
    os.mkdir(img_file)

# 批量处理图片
for item in imageList:
    # print(item)           # imgs/293718492401.pdf10.png
    img = cv2.imread(item, 0)     # 导入图片
    _, binary = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY_INV)   # 二值化处理
    binary[binary==255] = 1
    skel, distance = morphology.medial_axis(binary, return_distance=True)    # 图片细化(骨架提取)
    dist_on_skel = distance * skel
    dist_on_skel = dist_on_skel.astype(np.uint8)*255
    cv2.imwrite(img_file + item[5:], dist_on_skel)   # 此处dist_on_skel就是你需要保存的图像文件