首页 > 其他分享 >基于深度学习的骨龄检测识别系统(PyTorch+Pyside6+YOLOv5模型)

基于深度学习的骨龄检测识别系统(PyTorch+Pyside6+YOLOv5模型)

时间:2024-09-11 16:24:32浏览次数:12  
标签:YOLOv5 img data self Pyside6 train path os 骨龄

骨龄是骨骼年龄的简称,需要借助于骨骼在X光摄像中的特定图像来确定。通常要拍摄左手手腕部位的X 光片,医生通过X光片观察来确定骨龄。

在2006年,《中华-05》骨龄标准被编入《中华人民共和国行业标准》,成为中国目前唯一的行业骨龄标准。而在《中华-05》中作者一般推荐使用RUS-CHN计分法。

图中黄色高亮的地方,每个高亮都是需要医生看的关节,医生做骨龄的时候,需要对每个关节,根据骨 骺的发育情况。判断对应的等级。再查表,计算13个关节的等级分数之和,到【RUS-CHN骨成熟百分位 数标准曲线】中,找到分数对应的年龄。

骨龄评估是衡量生长发育的重要方法,但传统方法繁琐耗时,依赖医生经验。

我们项目利用深度学习算法,训练模型自动识别分析X光片中的骨骼图像,实现骨龄评估的自动化与智能化。自动化评估提高工作效率,减轻医生负担,增加关注其他病情的时间。同时,提高评估准确性和客观性,避免人为误差和偏见。

此外,自动化评估有助于优化医疗资源配置,高效处理大量骨龄评估任务,释放资源关注更紧急病情,提高医疗服务质量和及时援助。

骨龄评估自动化与智能化提高效率和准确性,优化医疗资源配置,对未来医疗科技发展有重要作用,为人类健康事业贡献力量。


目录

1.数据处理

2.模型研发

3.关节筛选

4.小模型训练 

5.pyside6部署

 6.特殊功能设计

7.成果展示


1.数据处理

通过对下载的数据集进行观察,可以得到,数据集是存在明显瑕疵的:数据模糊不清晰,数据量小(注意数据量虽然少,但是不增样。如果增样的化,就需要重新标注数据)。

OpenCV 直方图均衡化

什么是直方图均衡化? 是一种提高图像对比度的方法,拉伸图像灰度值范围。 简单来说, 一般情况,可以看到像素主要集中在中间的一些强度值上。 直方图均衡化要做的就是拉伸这个范围,就是像素主要几种区间。 像素分布率较低像素值,对其应用均衡化后(将像素分布较高的区间拉伸,得到 了新的直方图。

因为直方图均衡化处理之后,原来比较少像素的灰度会被分配到别的灰度去,像素相对集中, 处理后 灰度范围变大,对比度变大,清晰度变大,所以能有效增强图像。

而在直方图均衡化的对比度明显提高时,也同时提高了噪声的对比度。

通过自适应直方图均衡化,我们将输入图像划分为M × N网格。然后我们对网格中的每个单元进行均衡处理,从而获得更高质量的输出图像。

缺点是,自适应直方图均衡化的计算复杂度更高

import os
import cv2
from tqdm import tqdm

path = r"data/voc/VOCdevkit/VOC2007/JPEGImages"
if __name__ == '__main__':
    for name in tqdm(os.listdir(path)):
        img_path = os.path.join(path,name)


        img=cv2.imread(img_path,0)
        clahe=cv2.createCLAHE(tileGridSize=(3,3))
        dst =clahe.apply(img)

通过循环遍历,对收集到的手掌X光片图片文件进行直方图均衡化处理,以提高图像对比度,拉伸图像灰度值范围。处理后,图像灰度范围变大,对比度变大,清晰度变大,有效增强图像质量。 直方图均衡化的作用包括:

* 增强图像对比度:扩展灰度级范围,使图像细节更清晰可见。

* 增强图像细节:使纹理、边缘等细微特征更明显。

* 提升图像质量:改善视觉效果,使图像更鲜明、生动。

* 应用于图像增强和预处理:改善视觉效果,提升后续算法性能。

而以下代码旨在从 Pascal VOC 格式的 XML 注释文件中提取所有独特的目标类别名称。通过遍历指定目录下的 XML 文件,并解析每个文件中的目标标签,代码将收集并输出所有出现过的类别。此过程有助于构建数据集中目标类别的全面列表,为后续的模型训练和数据分析提供支持。

import os
from tqdm import tqdm
import xml.etree.ElementTree as ET

path="data/voc/VOCdevkit/VOC2007/Annotations"
if __name__ == '__main__':
    list_cls = []
    for name in tqdm(os.listdir(path)):
        xml_path = os.path.join(path,name)
        tree=ET.parse(xml_path)
        root=tree.getroot()



        list_cls=[]
        for obj in root.iter('object'):
            cls=obj.findtext('name')
            if cls not in list_cls:
                    list_cls.append(cls)
    print(list_cls)

Data_getclasses:遍历指定路径下的XML标签文件,提取出所有不重复的目标类别,并将其保存在一个列表中。这对于后期数据集的统计分析、模型训练和评估等任务都很有用。 

'''
拆分数据集: 训练集:验证集:测试集 = 7:2:1
'''
import os
import random
train_val_percent = 0.9
train_percent = 0.9 #这里的 train_percent 是指占 train_val_percent 中的
# xml 标签文件
base_path='data/voc/VOCdevkit/VOC2007'
xml_file_path =base_path+ r'\Annotations'
txt_save_path =base_path+r'\ImageSets'
# 判断txt_save_path文件夹路径如果不存在,就创建出来
if not os.path.exists(txt_save_path):
    os.makedirs(txt_save_path)
# 统计标签文件xml的总数
total_xml = os.listdir(xml_file_path)
num = len(total_xml)
list_index = range(num) # 获取随机0 到 num-1的数字,作为索引值
# 计算训练集和验证集的数据量
train_val_num = int(num * train_val_percent)
# 计算训练集的数据量
train_num = int(train_val_num * train_percent)
# 获取列表 list_index 中 指定长度的随机数
train_val_indexs = random.sample(list_index, train_val_num)
train_indexs = random.sample(train_val_indexs, train_num)
# 打开四个文件 trainval.txt、test.txt、train.txt、val.txt 用来保存分出来的数据名称
file_train_val = open(os.path.join(txt_save_path, 'trainval.txt'), 'w')
file_train = open(os.path.join(txt_save_path, 'train.txt'), 'w')
file_test = open(os.path.join(txt_save_path, 'test.txt'), 'w')
file_val = open(os.path.join(txt_save_path, 'val.txt'), 'w')
for i in list_index:
# 获取到xml的文件名称,不要后缀
    name = total_xml[i][:-4] + '\n'
# 判断当前的索引值i是在哪部分
    if i in train_val_indexs:
# 在训练集或者验证集中
        file_train_val.write(name)
        if i in train_indexs:
# 在训练集中
            file_train.write(name)
        else:
# 在验证集中
            file_val.write(name)
    else:
    # 在测试集中
        file_test.write(name)
# 关闭资源
file_train_val.close()
file_train.close()
file_test.close()
file_val.close()

data_split:把数据集拆分成为:训练集、验证集、测试集 ,且拆分比例为7:2:1。将数据集拆分为训练集、验证集和测试集可以用于模型的训练和评估。训练集用于训练模型,验证集用于调整模型的超参数和防止过拟合,测试集用于最终评估模型的性能。拆分数据集可以有效地帮助训练和评估机器学习模型,提高模型的泛化能力,并确保模型在真实场景中的可靠性和效果。

import os
import shutil
import xml.etree.ElementTree as ET
from tqdm import tqdm

sets = ['train', 'test', 'val']
classes = ['Radius', 'Ulna', 'MCPFirst', 'MCP', 'ProximalPhalanx', 'DistalPhalanx', 'MiddlePhalanx']


def voc2yolo(image_id):
    in_file = open(annotations_path % image_id, encoding='utf-8')
    out_file = open(labels_path + r'\%s.txt' % image_id, 'w', encoding='utf-8')
    tree = ET.parse(in_file)
    root = tree.getroot()

    size = root.find('size')
    img_w = int(size.findtext('width'))
    img_h = int(size.findtext('height'))

    for obj in root.iter('object'):
        cls = obj.findtext('name')
        difficult = obj.findtext('difficult')

        if cls not in classes or int(difficult) == 1:
            continue

        cls_id = classes.index(cls)
        bndbox = obj.find('bndbox')
        xmin = int(bndbox.findtext('xmin'))
        ymin = int(bndbox.findtext('ymin'))
        xmax = int(bndbox.findtext('xmax'))
        ymax = int(bndbox.findtext('ymax'))

        if xmax > img_w:
            xmax = img_w
        if ymax > img_h:
            ymax = img_h

        w = xmax - xmin
        h = ymax - ymin
        cx = xmin + w / 2
        cy = ymin + h / 2

        w = round(w / img_w, 6)
        h = round(h / img_h, 6)
        cx = round(cx / img_w, 6)
        cy = round(cy / img_h, 6)

        out_file.write(f"{cls_id} {cx} {cy} {w} {h}\n")

    out_file.close()


def read_files():
    for img_set in sets:
        img_path = imageSets_path % (img_set)
        with open(img_path, 'r', encoding='utf-8') as file:
            image_ids = [item.strip() for item in file.readlines()]

        list_file = open(os.path.join(base_path, f'{img_set}.txt'), 'w')

        for image_id in tqdm(image_ids):
            voc2yolo(image_id)
            list_file.write(os.path.join(images_path, f'{image_id}.png\n'))

        list_file.close()


base_path = 'data/voc/VOCdevkit/VOC2007'
imageSets_path = os.path.join(base_path, r'ImageSets\%s.txt')
annotations_path = os.path.join(base_path, r'Annotations\%s.xml')
labels_path = os.path.join(base_path, 'labels')
images_path = os.path.join(base_path, 'images')
JPEGImages_path = os.path.join(base_path, 'JPEGImages')

if __name__ == '__main__':
    print("数据处理 开始")

    if not os.path.exists(labels_path):
        os.makedirs(labels_path)

    if os.path.exists(images_path):
        shutil.rmtree(images_path)

    shutil.copytree(JPEGImages_path, images_path)
    read_files()

    print("数据处理 完成")

 将VOC格式的数据集转换为YOLO格式,为后续目标检测模型训练做准备。将VOC格式的数据集转换为YOLO格式能够与YOLO算法和相关模型兼容,以便进行目标检测模型的训练和使用。

import cv2
img = cv2.imread('images/1841.png', flags=0)# 直方图均衡化
dst = cv2.equalizeHist(img)#cv2.imshow('dst', dst)
# cv2.waitKey(0)
cv2.imwrite("images/dst.png",dst)
# 自适应直方图均衡化
chahe =cv2.createCLAHE(tileGridSize=(3,3))
dst2 = chahe.apply(img)
cv2.imwrite('images/dst2.png',dst2)

对输入的灰度图像进行直方图均衡化和自适应直方图均衡化处理,并将处理后的图像保存到指定的文件中,以增强图像对比度和细节。

import os.path

import torch

import common
import numpy as np
from PIL import Image
from torch.utils.data import Dataset,DataLoader
from torchvision.transforms import Compose, ToTensor, Resize, ToPILImage, InterpolationMode


data_transforms = Compose([Resize(size=(224, 224), interpolation=InterpolationMode.NEAREST),
                           ToTensor()])
class My_dataset(Dataset):
    def __init__(self, file_path, mode):
        super().__init__()
        self.data_list = []
        if mode == 'train':
            file_path = os.path.join(file_path, 'train.txt')
        elif mode == 'test':
            file_path = os.path.join(file_path, 'test.txt')
        else:
            print('mode 不正确')
            return

        with open(file_path, 'r') as f:
            lines = f.readlines()
            for line in lines:
                # D:\myfiles\datasets\arthrosis3\arthrosis\DIP\5\DIP_1306251.png 4
                info = line.strip().split()
                img_path, label = info[0], info[1]
                self.data_list.append([img_path, int(label)])

    def __getitem__(self, idx):
        img_path, label = self.data_list[idx]
        img = Image.open(img_path)
        img = common.trans_square(img)  # 正方形
        img = img.convert('L') # 灰度图
        img = data_transforms(img)  # CHW
        label = torch.tensor([label]).squeeze()
        return img, label

    def __len__(self):
        return len(self.data_list)


if __name__ == '__main__':
    data = My_dataset("data/arthrosis/DIP", 'train')
    train_loader = DataLoader(data, batch_size=10, shuffle=True)
    for x,y in train_loader:
        print(x.shape)
        print(y.shape)
        break

自定义一个数据集类,用于加载图像数据集并准备成可以用于 PyTorch 模型训练的数据格式,为模型训练提供了数据准备和加载的基础功能。

import os
import random
import glob
import cv2
from PIL import Image

def opt_img(img_path):
    '''
    数据预处理:自适应直方图均衡化
    '''
    # 自适应直方图均衡化
    img = cv2.imread(img_path, 0)
    clahe = cv2.createCLAHE(tileGridSize=(3, 3), clipLimit=2.0)
    dst = clahe.apply(img)
    cv2.imwrite(img_path, dst)

# img_path = 'DIP_58532.png'
def img_rotate(img_path, flag=5):
    '''
    数据增样:左右15度内选择
    '''
    img = Image.open(img_path)
    for i in range(flag):
        rota = random.randint(-15, 15)
        dst = img.rotate(rota)
        # img_path = 'DIP_58532{i}.png'
        file_path_name, _ = img_path.split(".")
        dst.save(file_path_name + f"{i}.png")


def data_img(path):
    '''
    图像处理
    '''
    # path = r'D:\myfiles\datasets\arthrosis2\arthrosis\MCP'
    for folder in os.listdir(path):
        folder_path = os.path.join(path, folder)
        if os.path.isfile(folder_path):
            continue
        print(folder_path)
        list_img_name = glob.glob(folder_path + '/*')
        count = len(list_img_name)
        print("增样前:" + str(count))

        # print(folder_path)
        for img_name in os.listdir(folder_path):
            img_path = os.path.join(folder_path, img_name)
            # print(img_path)
            # 自适应直方图均衡化(去雾操作)
            opt_img(img_path)

            # 数据增样
            img_rotate(img_path)

        # 获取图片数据的数量
        list_img_name = glob.glob(folder_path+'/*')
        count = len(list_img_name)
        # 当前等级下数量不足1000就增样
        if count < 1000:
            # 数据增样
            img_rotate(img_path, flag=1000-count)

        list_img_name = glob.glob(folder_path + '/*')
        count = len(list_img_name)
        print("增样后:" + str(count))


def data_split(path):
    '''
    数据拆分:训练集train和验证集test
    '''
    # path = r'D:\myfiles\datasets\arthrosis2\arthrosis\MCP'
    train_ratio = 0.9
    train_list = []
    test_list = []
    for folder in os.listdir(path):
        folder_path = os.path.join(path, folder)
        if os.path.isfile(folder_path):
            continue
        img_names = os.listdir(folder_path)
        train_num = len(img_names) * train_ratio
        random.shuffle(img_names)
        for index, img_name in enumerate(img_names):
            if index < train_num:
                train_list.append(os.path.join(folder_path, img_name) + " " + str(int(folder) - 1) + '\n')
            else:
                test_list.append(os.path.join(folder_path, img_name) + " " + str(int(folder) - 1) + '\n')

    random.shuffle(train_list)
    random.shuffle(test_list)

    with open(os.path.join(path, "train.txt"), 'w') as f:
        f.writelines(train_list)
    with open(os.path.join(path, "test.txt"), 'w') as f:
        f.writelines(test_list)



if __name__ == '__main__':
    path = 'data/arthrosis'
    for cat in os.listdir(path):
        cat_path = os.path.join(path, cat)

        data_img(cat_path)
        data_split(cat_path)

首先进行自适应直方图均衡化去雾,再进行数据增样,随机旋转生成多角度图像,并保存。接着遍历指定文件夹下图像进行同样处理,数量不足1000的类别进行更多增样。最后,将处理后的数据拆分为训练集和验证集,并写入对应文件。对医学影像数据进行预处理、增强和拆分,以便进行后续的机器学习模型训练和验证。

2.模型研发

我们使用的模型是yolov5。

在文件夹yolov5-master\data\coco128.yaml, 文件也可以保存在其他路径

# Classes
names:
  0: Radius
  1: Ulna
  2: MCPFirst
  3: MCP
  4: ProximalPhalanx
  5: DistalPhalanx
  6: MiddlePhalanx

修改:yolov5-master\models\yolov5s.yaml

# YOLOv5 

标签:YOLOv5,img,data,self,Pyside6,train,path,os,骨龄
From: https://blog.csdn.net/NatsuD/article/details/142055922

相关文章

  • 渣土车密闭运输识别系统 YOLOv5
    渣土车密闭运输识别系统通过在工地出入口及周边安装摄像头,渣土车密闭运输识别系统对渣土车的密闭运输情况进行实时监测,渣土车密闭运输识别系统利用图像识别技术,对渣土车的密闭状态进行识别和分析。渣土车密闭运输识别系统检测到有未密闭的渣土车进入工地区域时,将自动发出警报提示现......
  • 易百纳ss928开发板移植自训练模型跑通yolov5算法
    ss928平台移植官方yolov5s算法参考文章:https://www.ebaina.com/articles/140000017418,这位大佬也开源了代码,gitee链接:https://gitee.com/apchy_ll/ss928_yolov5s本文在参考上述文章的基础上,将官方yolov5s模型跑通,验证推理图片正确,然后移植自训练的推理模型,在移植过程中遇到了一些......
  • YOLO 自动标注工具autolabelimg(适用yolov5 v6.1)
    一、获取自定义数据集的YOLOv5.pt权重  首先,手动标注一部分数据集,训练YOLOV5模型,得到best.pt。二、下载和安装autolabelimg   (1)github链接:  https://github.com/wufan-tb/AutoLabelImg.git  手动下载.zip ,也可以clone:gitclonehttps://github.com/w......
  • PyQt6/PySide6:账本项目前端制作【附完整项目地址】
    0.前言最近在家里闲着没事,正好又看到朋友@studentWheat发了篇用Tkinter做的账本,于是决定跟他一起改进这个程序。屏幕截图:1.后端后端主要是朋友做的,在这里就不多说了,放个代码:src/api.pyfromcollectionsimportdefaultdictclassApiError(RuntimeError):passd......
  • YOLOv5: 从0开始搭建环境进行模型训练
    ​视频链接:YOLOv5:从0开始搭建环境进行模型训练_哔哩哔哩_bilibili《YOLOv5:从0开始搭建环境进行模型训练》课程致力于帮助学生实战YOLOv5目标检测算法。常心老师将手把手带领大家从0开始搭建YOLOv5环境,带领大家排坑、避坑、填坑。本课程将进行数据集打标、格式转化、模型......
  • yolov5单目测距+速度测量+目标跟踪
    要在YOLOv5中添加测距和测速功能,您需要了解以下两个部分的原理:单目测距算法单目测距是使用单个摄像头来估计场景中物体的距离。常见的单目测距算法包括基于视差的方法(如立体匹配)和基于深度学习的方法(如神经网络)。基于深度学习的方法通常使用卷积神经网络(CNN)来学习从图像......
  • 非煤矿山电子封条视频监控系统 YOLOv5
    非煤矿山电子封条视频监控系统采用现场摄像头和图像分析终端等设备,通过对煤矿关键地点进行实时监测和数据分析。当有异常情况发生时,非煤矿山电子封条视频监控系统可以通过人工智能算法将自动识别异常情况并记录信息,及时通知现场管理人员进行处理。非煤矿山电子封条视频监控系统24小......
  • YOLOv5 结合切片辅助超推理算法 | 这才叫让小目标无处遁形!
    引言YOLOv5作为一种高效的目标检测算法,在许多领域得到了广泛应用。然而,在处理小目标检测任务时,YOLOv5仍然面临一些挑战。切片辅助超推理算法则为解决这一问题提供了一种有效的思路。本文将深入探讨YOLOv5与切片辅助超推理算法结合的原理、实现细节、以及在小目标检测方面的优......
  • YOLOv5改进 | NMS | 将NMS修改为soft-NMS【完整代码】
    秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转......
  • Yolov5入门介绍(官网文档学习笔记)
    一、yolov5是什么yolov5是yolo的第五次迭代,旨在提供高速、高精度的目标检测模型官方文档:ComprehensiveGuidetoUltralyticsYOLOv5-UltralyticsYOLODocs二、yolov5的优点1、高速、高精度 (例如R-CNN目标检测有两部:先生成候选框再分类)2、基于pytorch搭建,使用于各......