Zhang-Suen骨架提取算法

news2025/4/26 13:35:16

前言

本专栏针对的目标物体为物体裂缝量化,提取裂缝的骨架有助于裂缝长度的求解,故这一篇也是本专栏的开篇。

细化算法选择与分析

裂缝骨架的提取是十分有必要,如果我们能够得到裂缝的骨架图那么就很容易获得整条裂缝的长度。在当前经典的细化算法,比如Zhang并行细化算法、Hilditch细化算法,Rosenfeld细化算法等都有被广泛应用在骨架提取算法之中。

其中Zhang并行细化算法细化过程简单,也是应用最广的一种,且细化后骨架位于图像中心线上,但是其结果图像往往有较多突起点和毛刺产生。Hilditch是基于二值化图像的基础上进行的,利用串行与并行相结合的方式提取骨架,虽然其细化效果较好,但是该算法判定条件繁复而冗余,导致处理时间较长,考虑到这些因素,故不采用Hilditch。Rosenfeld是一种基于边界追踪的细化算法,与 Zhang-Suen 和 Hilditch 等算法相比,Rosenfeld算法也被广泛应用于骨架提取。它通常产生相对平滑的骨架,较少出现突起点和毛刺。

从效果上来说应当选择Rosenfeld算法,但手写实现与skimage集成的Zhang-Suen算法比较,Zhang-Suen更胜一筹。

环境搭建

从上到下依次安装即可,如果报错没有这个包,就进行安装即可。

安装skimage

pip install scikit-image -i https://pypi.tuna.tsinghua.edu.cn/simple

安装opencv

​pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple 

​pip install opencv-contrib-python -i https://pypi.tuna.tsinghua.edu.cn/simple

安装matplotlib

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple matplotlib==3.5.2 

安装pyzjr

pip install pyzjr -i https://pypi.tuna.tsinghua.edu.cn/simple 

裂缝数据集

我们针对的是适用于voc数据集的8位png彩图,从网上可以找到开源数据集进行测试,我这里采用的是裂缝森林的数据集,你可以从Kaggle上找到crackforest | Kaggle。如果你下载的数据集是mat后缀的,可以使用下面这个脚本进行转换。

# Mat2png.py

from os.path import isdir
from scipy import io
import os, sys
import numpy as np
from PIL import Image

if __name__ == '__main__':
    file_path = './groundTruth/'
    png_img_dir = './groundTruthPngImg/'
    if not isdir(png_img_dir):
        os.makedirs(png_img_dir)
    image_path_lists = os.listdir(file_path)
    images_path = []
    for index in range(len(image_path_lists)):
        image_file = os.path.join(file_path, image_path_lists[index])
        # print(image_file)#./CrackForest-dataset-master/groundTruth/001.mat
        images_path.append(image_file)
        image_mat = io.loadmat(image_file)
        segmentation_image = image_mat['groundTruth']['Segmentation'][0]
        segmentation_image_array = np.array(segmentation_image[0])
        image = Image.fromarray((segmentation_image_array - 1) * 255)
        png_image_path = os.path.join(png_img_dir, "%s.png" % image_path_lists[index][0:3])
        image.save(png_image_path)

如果你下载的时候就是这样的标签图最好不过了:

但请注意,如果不是自己标注的数据集,就最好要检查它的像素是否正确。

 远看没有任何的问题,如果你使用图片查看器或ps放大查看就会看到下面的情况:

这种图片是有问题的,所以必须要进行二值化操作。

裂缝骨架提取

Zhang-Suen我曾经使用过手写版本的,不是超时就是运行报错,而在skimage里面的skeletionize函数就能轻易的实现骨架化,这里调用multifile模式,即可进行文件夹的遍历,将骨架化后的图像保存到另一个文件夹当中。

import numpy as np
from skimage.filters import threshold_otsu,median
from skimage.morphology import skeletonize,dilation,disk
import os
import cv2
from skimage import io, morphology
 
def sketion(mode='multifile', input_folder='num', output_folder='output', single_pic='num/001.png'):
    """
    :param mode: 检测模式——single_pic检测单张图片并保存,multifile检测多张图片并保存
    :param input_folder: 目标文件夹
    :param output_folder: 输出文件夹
    :param single_pic: 用于检测单张图片的路径
    :return: 返回输出文件夹的路径的骨架图
    """
    if mode == 'single':
        image = io.imread(single_pic, as_gray=True)
        # 使用Otsu阈值方法进行二值化处理
        thresh = threshold_otsu(image)
        binary = image > thresh
        skeleton = skeletonize(binary)
        io.imshow(skeleton)
        io.imsave('output.png', skeleton)
        io.show()
 
 
    elif mode == 'multifile':
        if not os.path.exists(output_folder):
            os.makedirs(output_folder)  # 如果输出文件夹不存在,就创建它
 
        for filename in os.listdir(input_folder):
            if filename.endswith('.jpg') or filename.endswith('.png'):
                image = io.imread(os.path.join(input_folder, filename), as_gray=True)
 
                thresh = threshold_otsu(image)
                binary = image > thresh
                binary = dilation(binary, disk(3))
                binary = median(binary, selem=morphology.disk(5))
                # 效果不错
                binary = dilation(binary, disk(2))
                binary = median(binary, selem=morphology.disk(5))
                # 添加闭运算
                selem = morphology.disk(3)
                binary = morphology.closing(binary, selem)
 
                skeleton = skeletonize(binary)
                output_filename = os.path.join(output_folder, filename)
                io.imsave(output_filename, skeleton)
 
        return output_folder

这里先进行一个简单的测试。读取对应文件夹下的图片,看效果如下: 

import cv2
import pyzjr as pz
from matplotlib import pyplot as plt
img1=cv2.imread("./num/001.png")
img2=cv2.imread("./output/001.png")
stackedimg=pz.Stackedtorch([img1,img2],1,2,["原图","骨架图"])
plt.show()

注意 

这里的中值滤波median是我经过多种滤波测试后获得的较好的结果,你应当在自己的数据集上进行测试,包括膨胀与闭运算的操作,找到适用于自己的数据集上组合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/842962.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习深度学习——序列模型(NLP启动!)

👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——卷积神经网络(LeNet) 📚订阅专栏:机器学习&&深度…

地理信息系统空间分析实验教程 第三版 第八章示例与练习 学校选址

学校选址 背景 合理的学校空间位置布局有利于学生的上课与生活。学校的选址问题需要考虑地理 E八位置、学生娱乐场所配套设施、与现有学校的距离等因素,从总体上把握这些国素能够确定出适宜性比较好的学校选址区 目的 通过练习,熟悉 ArcGIS 栅格数据…

无涯教程-Perl - endnetent函数

描述 此功能告诉系统您不再希望使用getnetent从网络列表中读取条目。 语法 以下是此函数的简单语法- endnetent返回值 此函数不返回任何值。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perluse Socket;while ( ($name, $aliases, $addrtype, $net) getnetent() )…

VUE框架:vue2转vue3全面细节总结(3)路由组件传参

大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页: lqj_本人_python人工智能视觉(opencv)从入门到实战,前端,微信小程序-CSDN博客 最新的uniapp毕业设计专栏也放在下方了: https://blog.csdn.net/lbcy…

element表格+表单+表单验证结合运用

目录​​​​​​​ 一、结果展示 二、实现代码 一、结果展示 1、图片 2、描述 table中放form表单,放输入框或下拉框或多选框等; 点击添加按钮,首先验证表单,如果存在没填的就验证提醒,都填了就向下添加一行表单表…

Redis中BigKey、HotKey的发现与处理

Redis中BigKey、HotKey的发现与处理 内容详情: 阿里云开发者社区(点击跳转) 参考自: https://developer.aliyun.com/article/788271?utm_contentm_1000291945#slide-1

【数据结构OJ题】删除有序数组中的重复项

原题链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 用双指针算法,定义两个变量src和dst,一开始让src和dst指向num[ ]数组的第一个元素&a…

Cadence学习

Cadence学习 Cadence内容涵盖Cadence主要功能Cadence功能模块Allegro Design Entry CIS 和 OrCAD Capture CIS 的区别Cadence 公司简介Allegro Design Entry CISOrCAD Capture CIS OrCAD中part和database part区别OrCAD中不同页面的连接关系应该怎么处理(1&#xff…

Matlab之利用MarkerFaceColor来填充marker

matlab画图在加一些marker的时候, 有实心的圆圈, 比如: plot(x,y,.r,MarkerSize,20)但是如果想要一个很大的marker, 就需要把这个markersize调得很大, 比如MarkerSize20 但是也可以用空心的圆圈然后把中间涂上颜色, 这样调整起来更方便. 比如: plot(x,y,or,MarkerSize,5,Mar…

拆分PDBQT文件并将其转换为PDB格式

拆分PDBQT文件转为PDB格式 1. vina_split拆分PDBQT文件 假设你用AutoDock Vina做了对接,那么所有预测的结合构象都被放入一个多构象 PDBQT 文件中,如果需要拆分后进行可视化分析,那么Vina官方自带了vina_split来进行拆分。下面是vina_split…

TS协议之PES(ES数据包)

TS协议之PAT(节目关联表)TS协议之PMT(节目映射表)TS协议之PES(ES数据包) 该文档已上传:下载地址 1. 概要 1.1 TS数据包(PES)协议数据组成 TSTS头PES头ES。TS&#xf…

在 Ubuntu 上安装 Docker 桌面

Ubuntu 22.04 (LTS) 安装 Docker 桌面 要成功安装 Docker Desktop,您必须: 满足系统要求拥有 64 位版本的 Ubuntu Jammy Jellyfish 22.04 (LTS) 或 Ubuntu Impish Indri 21.10。对于非 Gnome 桌面环境,必须安装 gnome-terminal:…

springsecurity初稿

springsecurity 课程 课程目标 权限管理简介【了解】权限管理解决方案【掌握】初识Spring Security【了解】Spring Security 认证配置【掌握】Spring Security 鉴权配置【掌握】Spring Security 底层原理【掌握】Spring Security 退出操作【重点】Spring Security整合JWT【重…

参考RabbitMQ实现一个消息队列

文章目录 前言小小消息管家1.项目介绍2. 需求分析2.1 API2.2 消息应答2.3 网络通信协议设计 3. 开发环境4. 项目结构介绍4.1 配置信息 5. 项目演示 前言 消息队列的本质就是阻塞队列,它的最大用途就是用来实现生产者消费者模型,从而实现解耦合以及削峰填…

有什么好用的PNG素材网站吗?看看这6个

高品质PNG素材无疑能提升网站的质量,给用户带来更美好的使用体验,今天本文会与大家分享6个好用的PNG素材网站,一起来看看吧! 1、即时设计资源广场 即时设计资源广场集成了多种大厂素材,不只是PNG素材,还有…

试用AI生成代码工具Fauxpilot,详细安装过程

设置服务 预先说明 需要预先安装支持NVIDIA的docker,docker compose > 1.28不能再容器里运行,否则出现以下报错: rootc536ca0dbd64:/test/fauxpilot-main# ./setup.sh Checking for curl ... /usr/bin/curl Checking for zstd ... /opt/conda/bin…

Java-认识String

目录 一、String概念及创建 1.1 String概念 1.2 String的创建 二、String常用方法 2.1 String对象的比较 2.2 字符串查找 2.3 转化 2.4 字符串替换 2.5 字符串拆分 2.6字符串的截取 2.7 其他操作方法 2.8 字符串修改 三、面试题 一、String概念及创建 1.1 String概念 Java中…

PVE虚拟化平台之安装openKylin开源操作系统

PVE虚拟化平台之安装openKylin开源操作系统 一、openKylin介绍1.1 openKylin简介1.2 openKylin特性 二、下载openKylin系统镜像2.1 官方网址2.2 下载openKylin系统镜像 三、上传镜像到PVE存储3.1 检查PVE环境3.2 上传镜像 四、创建虚拟机4.1 设置虚拟机名称4.2 操作系统设置4.3…

【六袆 - 国际化】SpringBoot国际化Message

模拟场景校验请求参数 private void checkParam(List<ReqAppAdminDTO> req) {// 校验管理员如果已存在&#xff0c;则抛出已存在异常req.forEach(item -> {AppAdminDO appAdminDO appAdminMapper.selectByAppIdAndAdminNo(item.getAppId(), item.getAdminNo());if (O…

ubuntu上回环设备/dev/loop0占用100%清理

查看磁盘占用情况时&#xff1a; df -h/dev/loopn这些设备在Linux下被称为回环设备。 终端输入&#xff1a; sudo apt autoremove --purge snapd再次查看&#xff1a;