简介:本资源是一套基于PyQt5与深度学习实现的骨龄识别检测Python项目源码,面向具备一定Python基础、希望将目标检测模型落地为桌面应用的开发者与学习者。项目以YOLOv5为核心检测框架,配套图形化界面,可用于医学影像场景下的骨龄评估实践。压缩包共200个文件,包含69个py源码、53个yaml配置、18个pth模型权重,以及yml、md、sh、ipynb等辅助文件,整体约717MB,模型文件与训练配置齐备。资源内含项目使用说明,并给出数据集预处理流程,涉及图片标注、VOC转YOLO格式及mydata.yaml路径配置等关键环节,便于读者复现训练与推理。目前已有728人学习下载,适合需要完整检测方案、GUI集成示例与排错参考的读者参考使用。
1. 骨龄识别这套 PyQt5 源码,为什么值得先跑通再谈优化
骨龄评估在儿科内分泌和运动医学里是个高频刚需,但真正落到工程侧,难点从来不是模型结构本身,而是从数据集标注、YOLO 格式转换、训练权重加载到 GUI 推理这一整条链路能不能串起来。这份基于 PyQt5 深度学习实现的骨龄识别检测 Python 源码,把 GUI 界面、项目使用说明和模型文件打包在一起,省掉了自己搭界面的时间。它适合两类人:一类是想快速验证骨龄识别效果、拿现成界面做 demo 的开发者;另一类是想借这个项目练手 YOLOv5 数据预处理和 PyQt5 界面联调的 Python 学习者。数据集来自百度飞桨 AI Studio,9 个大类,预处理脚本和训练配置都留在包里,不是那种只给权重不给流程的“黑匣子”资源。下面按我实际拆包复现的顺序,把每一步的参数和坑讲清楚。
2. 拆包先看结构:从 tfevents 到 Dockerfile 的工程线索
2.1 目录里藏着哪些关键文件
拿到压缩包解压后,根目录里能看到events.out.tfevents.1686040397.HY-DKIFFGATEUML.18096.0、CITATION.cff、setup.cfg、Dockerfile、Dockerfile-arm64、Dockerfile-cpu、.dockerignore、.gitattributes、.gitignore这些文件。别被这一堆配置吓到,它们其实透露了项目的工程成熟度:有 tfevents 说明训练过程被 TensorBoard 记录过,有 CITATION.cff 说明作者考虑过引用规范,有多个 Dockerfile 说明部署环境做过区分。真正要动手改的是yolov5_master目录下的预处理脚本和data/mydata.yaml。
我一般会先确认三件事:Python 版本、PyQt5 是否装好、模型文件在不在。项目使用说明里如果写了依赖版本,优先按它来,别自己升到最新版,PyQt5 和某些 torch 版本之间有兼容玄学。
2.2 环境准备与依赖安装
先建虚拟环境,避免污染系统 Python。这一步新手容易跳过,后面出问题很难排查。
python -m venv boneage_env # Windows 激活 boneage_env\Scripts\activate # Linux / macOS 激活 source boneage_env/bin/activate pip install pyqt5 opencv-python numpy torch torchvision pip install -r requirements.txt # 如果包里有的话逻辑说明:虚拟环境把项目依赖和系统隔离,pyqt5负责 GUI,opencv-python负责图像读取和预处理,torch系列负责模型推理。参数说明:如果requirements.txt里锁定了 torch 版本,比如torch==1.13.1,就按它装,不要手动改成 2.x,YOLOv5 某些算子在新版本里行为会变。装完后用python -c "import PyQt5; print('ok')"验证一下,能打印 ok 再往下走。
提示:如果 pip 安装 torch 特别慢,常见做法是换国内镜像源,比如
-i https://pypi.tuna.tsinghua.edu.cn/simple,这不是必须的,但能省不少等待时间。
3. 数据预处理三步走:images_tag、voc_to_yolo 与 mydata.yaml
3.1 先跑 images_tag.py 并改图片路径
数据集从飞桨 AI Studio 下载后,第一件事是运行yolov5_master/images_tag.py。这个脚本的作用是给图片打标签或者做初步筛选,具体行为取决于作者实现,但核心是它需要知道图片放在哪。
# yolov5_master/images_tag.py 开头部分 import os # 修改为你解压后的图片目录 image_dir = r"D:\boneage_dataset\images" # 或者 Linux 下 # image_dir = "/home/user/boneage_dataset/images" for filename in os.listdir(image_dir): if filename.endswith(".jpg") or filename.endswith(".png"): # 这里执行打标签或重命名逻辑 pass逻辑说明:image_dir必须指向你实际存放骨龄图片的文件夹,路径里不要有中文和空格,Windows 下尤其注意。参数说明:如果脚本里还有output_dir或label_dir之类的变量,一并改成你的目标路径。跑之前先备份原始图片,这类脚本有时候会原地修改文件名,翻车了没有后悔药。
3.2 voc_to_yolo.py 的类别参数怎么改
yolov5_master/voc_to_yolo.py负责把 VOC 格式的标注转成 YOLO 格式。作者在这个文件里做了修改,不建议直接参考原始 YOLOv5 的写法,重点是把classes改成这个项目的 9 个类别。
# yolov5_master/voc_to_yolo.py 开头 classes = [ "class1", "class2", "class3", "class4", "class5", "class6", "class7", "class8", "class9" ] # 注意:这里的类别名要和数据集链接里的定义一致 # 路径也要改 voc_annotations = r"D:\boneage_dataset\annotations" yolo_labels = r"D:\boneage_dataset\labels"逻辑说明:classes列表的顺序决定了 YOLO 标签里类别索引的映射关系,顺序错了模型训练时会把类别搞混。参数说明:voc_annotations是 VOC 格式 XML 文件所在目录,yolo_labels是转换后 txt 文件的输出目录。转换完成后,每个图片对应一个同名 txt,里面每行是class_id x_center y_center width height,坐标都归一化到 0 到 1 之间。
注意:如果转换后发现某些图片没有对应 txt,先检查 XML 里是不是没有 object 节点,空标注图片在 YOLO 里通常直接跳过。
3.3 mydata.yaml 里的 path 与类别数
数据转好后,改yolov5_master/data/mydata.yaml。这个文件告诉 YOLOv5 去哪里找训练集和验证集。
# yolov5_master/data/mydata.yaml path: D:/boneage_dataset # 数据集根目录 train: images/train val: images/val nc: 9 # 类别数,和 classes 长度一致 names: ['class1', 'class2', 'class3', 'class4', 'class5', 'class6', 'class7', 'class8', 'class9']逻辑说明:path是根路径,train和val是相对路径,YOLOv5 会拼成path/train去找图片。参数说明:nc必须等于names的长度,也等于classes的长度,三者不一致训练会直接报错。Windows 下路径用正斜杠/或者双反斜杠\\,单反斜杠会被 YAML 解析成转义字符。
4. 训练与 GUI 联调:模型文件怎么接进 PyQt5 界面
4.1 确认模型文件与推理入口
包里带了模型文件,通常是.pt格式的 YOLOv5 权重。GUI 界面会调用这个权重做推理。先找到主程序入口,一般是main.py或者app.py,里面会加载 PyQt5 的窗口类。
# 常见的模型加载方式 import torch model_path = "weights/best.pt" model = torch.hub.load('ultralytics/yolov5', 'custom', path=model_path) model.conf = 0.25 # 置信度阈值 model.iou = 0.45 # NMS IoU 阈值逻辑说明:torch.hub.load加载本地权重,conf和iou是两个关键推理参数。参数说明:conf调低会检出更多目标但误检增加,骨龄识别场景建议从 0.25 起步;iou控制重叠框合并,0.45 是通用默认值。如果加载时报缺少ultralytics包,按提示安装即可。
4.2 PyQt5 界面与推理线程的配合
GUI 里点“检测”按钮后,如果直接在按钮回调里跑模型推理,界面会卡死。常见做法是把推理放到QThread里,通过信号槽把结果传回界面。
from PyQt5.QtCore import QThread, pyqtSignal class InferenceThread(QThread): result_ready = pyqtSignal(object) def __init__(self, image_path, model): super().__init__() self.image_path = image_path self.model = model def run(self): results = self.model(self.image_path) self.result_ready.emit(results)逻辑说明:run方法里执行耗时推理,完成后用result_ready信号把结果发出去,主线程接收后更新界面。参数说明:image_path是用户选择的图片路径,model是加载好的 YOLOv5 模型。这样改完,界面在推理时不会假死,用户体验正常。
提示:如果界面还是卡,检查是不是在
run里直接操作了 UI 控件,QThread 里不能直接改界面,必须走信号槽。
5. 避坑与排查:骨龄识别项目里最容易翻车的五件事
5.1 路径含中文导致 OpenCV 读图失败
现象:cv2.imread返回 None,后面推理报错。原因:OpenCV 在 Windows 下对中文路径支持不好。解决:把数据集和项目都放到纯英文路径下,或者用cv2.imdecode(np.fromfile(path, dtype=np.uint8), -1)替代imread。
5.2 类别数不一致导致训练启动即报错
现象:训练一开始就提示nc和names长度不匹配。原因:mydata.yaml里nc写了 9,但names只列了 8 个,或者voc_to_yolo.py里classes数量对不上。解决:三处逐一核对,确保都是 9。
5.3 PyQt5 与 torch 版本冲突导致界面闪退
现象:界面能打开,一点检测就闪退,控制台没有明显报错。原因:某些 PyQt5 版本和 torch 的 DLL 加载顺序冲突。解决:先import torch再from PyQt5 import QtWidgets,或者把 PyQt5 降到 5.15.4 这类稳定版本。
5.4 模型文件缺失或路径写死
现象:运行时报FileNotFoundError找不到.pt文件。原因:代码里权重路径写成了作者本机的绝对路径。解决:全局搜索.pt字符串,改成相对路径或者从配置文件读取。
5.5 转换后的标签坐标越界
现象:训练时提示Label class x y w h超出 0 到 1 范围。原因:VOC 转 YOLO 时没有做归一化,或者图片尺寸和 XML 里记录的尺寸不一致。解决:检查voc_to_yolo.py里是否除以了width和height,并确认 XML 的size节点和实际图片一致。
6. 进阶技巧:用 Dockerfile-cpu 做无 GPU 环境验证
6.1 为什么先跑 CPU 版 Dockerfile
包里给了Dockerfile-cpu,这个文件的价值在于:当你手头没有 GPU 机器,或者想先验证推理流程通不通时,用 CPU 版镜像跑一遍,能排除掉 CUDA 相关的干扰因素。我一般会先用 CPU 版把 GUI 和推理链路跑通,再换 GPU 环境做批量测试。
# 构建 CPU 版镜像 docker build -f Dockerfile-cpu -t boneage-cpu . # 运行容器,注意把项目目录挂进去 docker run -it --rm -v $(pwd):/app boneage-cpu bash逻辑说明:-f Dockerfile-cpu指定用 CPU 版构建,-v把当前目录挂载到容器/app,这样改代码不用重新构建镜像。参数说明:如果 Dockerfile 里基础镜像拉取慢,可以换成国内可访问的镜像源,但不要改基础镜像的 Python 版本,否则依赖可能装不上。
6.2 验证推理结果是否合理
跑通之后,拿几张测试图看输出。骨龄识别本质上是分类或者检测任务,输出应该是类别和置信度。如果所有图片都输出同一个类别,大概率是权重没加载对,或者预处理时归一化参数和训练时不一致。
# 快速验证脚本 import torch model = torch.hub.load('ultralytics/yolov5', 'custom', path='weights/best.pt') results = model('test.jpg') print(results.pandas().xyxy[0]) # 打印检测框和类别逻辑说明:results.pandas().xyxy[0]把检测结果转成 DataFrame,能看到每个框的坐标、置信度和类别。参数说明:如果输出为空,调低model.conf再试;如果类别明显不对,回头检查mydata.yaml里的names顺序和训练时是否一致。
6.3 一个我踩过的坑
有一次我图省事,直接把作者提供的权重拿来跑,结果所有骨龄图片都识别成同一个类别。排查了半天才发现,训练时的names顺序和我本地mydata.yaml里的顺序不一样,模型输出的索引映射错了。从那以后我每次加载权重前,都强制走一遍“核对 names 顺序”的流程,确认无误再跑推理。希望帮到你。
本文还有配套的精品资源,点击获取