☰
基于YOLO的舌象诊断系统毕业设计:源码拆包与实战调优
2026/10/11 9:46:04 网站建设 项目流程

简介:这份资源是面向高校学生与深度学习入门者的舌象诊断系统完整项目包,基于Python与YOLO目标检测框架实现,可用于毕业设计、期末大作业或课程设计场景,帮助解决从零搭建中医舌象识别系统时缺少可运行代码与标注数据的问题。压缩包共184个文件,约42.7MB,包含54个Python源码文件、61张jpg舌象样本图、40个pyc编译文件,以及json配置、txt说明、ui界面文件、md文档与docx学习路线等,覆盖模型训练、推理与界面展示各环节。代码附有注释,新手也能理解整体流程,下载后按文档简单部署即可运行。目前已有638人学习关注。项目还配有详细说明文档与学习路线,便于梳理数据集组织方式、模型结构与调试思路,适合作为深度学习目标检测方向的实战参考。

1. 舌象诊断系统源码拆包:一份能跑通的 YOLO 毕业设计长什么样

舌象诊断这个方向,每年毕业季都有人问。原因不复杂:中医舌诊本身有明确的分类标准(舌质、舌苔、颜色、厚薄),天然适合套目标检测和图像分类;数据采集门槛也不算高,手机拍舌头就能凑样本。但真正动手做的时候,大部分人卡在三个地方——数据集从哪来、YOLO 怎么训、界面怎么串起来。这份基于 Python + YOLO 深度学习的舌象诊断系统源码,就是冲着这三个问题去的:它给了一套标注好的舌象数据集、一份能直接训练的 YOLO 训练脚本、一个带界面的推理程序,外加详细文档。适合正在做计算机毕业设计、想找一个「有数据、有模型、有界面」完整闭环的同学,也适合想快速验证 YOLO 在医学图像小样本场景下表现的从业者。下面我按拆包顺序,把这份资源从环境到训练到推理完整走一遍,中间该踩的坑一个不落。

2. 环境搭建与数据集结构:先让 YOLO 认识舌头

2.1 为什么选 YOLO 而不是纯分类网络

舌象诊断本质上要做两件事:定位舌头区域、判断舌质舌苔类别。如果只用 ResNet 这类分类网络,你得先手动裁出舌头,再送进分类器,中间多了一步预处理,实际部署时很别扭。YOLO 把检测和分类揉在一个头里,输入整张人脸照片,直接输出舌头框和类别,端到端省事。这份源码用的是 YOLOv5/v8 系列(具体版本以包内 requirements 为准),对小目标做了自适应锚框,舌头在整张图里占比不算大,这个特性刚好用得上。

另一个现实原因是毕业设计答辩。评委看到「目标检测 + 分类」的 pipeline,比单纯「图像分类」更容易讲清楚技术含量。源码里把检测和分类拆成两个可独立训练的模块,你可以只跑检测,也可以检测完再走一遍细分类,灵活度够。

2.2 目录结构与数据集格式

拿到压缩包先别急着跑 train.py,花五分钟把目录看一遍。典型结构是这样:

tongue_diagnosis/ ├── data/ │ ├── images/ # 原始舌象图片 │ ├── labels/ # YOLO 格式标注 txt │ ├── train.txt # 训练集图片路径列表 │ └── val.txt # 验证集图片路径列表 ├── models/ │ ├── yolov5s.pt # 预训练权重 │ └── best.pt # 训练后权重 ├── utils/ │ ├── datasets.py # 数据加载 │ └── general.py # 通用工具 ├── train.py ├── detect.py ├── requirements.txt └── README.md

标注文件是 YOLO 标准格式,每行class x_center y_center width height,坐标归一化到 0~1。这里有个高频翻车点:很多人拿 LabelImg 标完导出的是 VOC 的 xml,直接扔进 labels 文件夹,训练时报IndexError: list index out of range。源码文档里给了转换脚本,但如果你自己标数据,记得在 LabelImg 里把保存格式切成 YOLO。

2.3 依赖安装与版本对齐

环境这块,Python 建议 3.8~3.10,太新的 3.12 有些 torch 版本还没跟上。安装命令:

# 创建虚拟环境,避免污染全局 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装依赖,注意 torch 版本要和 CUDA 对齐 pip install torch==1.13.1 torchvision==0.14.1 --index-url https://download.pytorch.org/whl/cu117 pip install -r requirements.txt

逻辑说明:torch 单独装是因为 requirements.txt 里通常只写torch>=1.7,pip 会拉最新版,和你本机 CUDA 对不上就报CUDA error: no kernel image is available。参数上,cu117对应 CUDA 11.7,你本机是 11.8 就换cu118,是 CPU 训练就装 CPU 版。装完跑一句python -c "import torch; print(torch.cuda.is_available())",返回 True 才算环境通了。

提示:数据集里的图片如果分辨率差异很大(有的 500×500,有的 4000×3000),训练前统一 resize 到 640×640,否则 dataloader 会频繁报 shape mismatch。

3. 训练脚本与参数调优:把 mAP 从 0.4 拉到 0.8

3.1 训练命令与关键参数含义

源码的 train.py 基本沿用了 YOLO 官方风格,核心命令:

python train.py \ --img 640 \ --batch 16 \ --epochs 200 \ --data data/tongue.yaml \ --weights models/yolov5s.pt \ --cfg models/yolov5s.yaml \ --name tongue_exp

逐参数说:--img 640是输入尺寸,舌象细节多,640 是精度和显存的平衡点,显存够可以上 800;--batch 16批大小,8G 显存跑 640 大概能到 16,爆显存就降到 8;--epochs 200是上限,实际看早停;--data指向数据配置文件,里面写 train/val 路径和类别名;--weights加载预训练权重,这是小样本能训起来的关键,从头训基本没戏;--name是输出目录名,跑完结果在runs/train/tongue_exp/。

数据配置文件tongue.yaml长这样:

train: data/train.txt val: data/val.txt nc: 4 names: ['hongshe', 'baishe', 'huangtai', 'baitai']

nc是类别数,names顺序必须和标注文件里的 class id 一一对应,错一个位置整个训练就废了。

3.2 数据增强与过拟合判断

舌象数据集普遍偏小,几百到几千张。源码里开了 mosaic、HSV 抖动、随机翻转。mosaic 把四张图拼一张,等效增大 batch,对小数据集很管用。但舌象有个特殊性:颜色是核心特征,HSV 的 h 通道抖动幅度别开太大,否则红舌被抖成紫舌,模型学出来的颜色边界就糊了。我一般把hsv_h从默认 0.015 降到 0.008。

判断过拟合看两个信号:训练 loss 一直降,验证 mAP 在某个 epoch 后不升反降;或者验证集精度远低于训练集。这时候先别急着加数据,把--epochs砍到 100,加--dropout,或者把学习率--lr0从 0.01 降到 0.001 试试。源码文档里给了一组推荐参数,但那是作者机器上的,你显存和数据集规模不一样,得自己微调。

3.3 训练过程监控与断点续训

训练启动后,终端会打印每 epoch 的 box_loss、obj_loss、cls_loss 和 mAP@0.5。重点盯 mAP@0.5,前 20 个 epoch 涨得快,后面趋缓。如果 50 epoch 了 mAP 还在 0.1 附近晃,八成是数据或配置有问题,别硬等。

断点续训用--resume:

python train.py --resume runs/train/tongue_exp/weights/last.pt

last.pt是最近一次保存的权重,best.pt是验证集最优。续训会接着上次的 epoch 和优化器状态跑,不用重头来。注意--resume后面跟的是权重路径,不是目录,写错了会新建一个实验从头训。

注意:训练中途改tongue.yaml的类别数,必须删掉runs/train/tongue_exp重新训,否则模型头对不上,报size mismatch。

4. 推理与界面集成:从 detect.py 到可演示系统

4.1 单图推理与结果解析

训练完拿best.pt跑推理:

python detect.py \ --weights runs/train/tongue_exp/weights/best.pt \ --source data/test_images/ \ --conf 0.4 \ --iou 0.45 \ --save-txt

--conf 0.4是置信度阈值,低于这个的框不输出;--iou 0.45是 NMS 的 IoU 阈值,控制重叠框合并。舌象检测里舌头通常只有一个,--iou可以调低到 0.3,避免同一个舌头出两个框。--save-txt把检测结果存成 txt,方便后续接诊断逻辑。

输出结果里每个框带类别和置信度,比如hongshe 0.87。源码在 detect.py 后面接了一个简单的规则映射:检测到红舌 + 黄苔,输出「湿热」;白舌 + 白苔,输出「寒湿」。这个映射表在utils/diagnosis.py里,你可以按中医教材改。

4.2 界面串接与实时推理

源码带了一个基于 PyQt5 或 Gradio 的界面(以包内实际为准)。PyQt5 版本是本地窗口,选图片、点检测、显示结果框和诊断文字;Gradio 版本是网页版,适合远程演示。核心逻辑一样:读图 → 预处理 → 模型推理 → 画框 → 输出诊断。

如果自己接界面,注意两点:一是模型加载只做一次,别每次点检测都torch.load,慢且占显存;二是推理放在子线程,否则界面会卡死。源码里用QThread包了一层,你可以直接抄。

# 模型只加载一次,放在类初始化里 class Detector: def __init__(self, weights): self.model = torch.load(weights, map_location='cpu')['model'] self.model.eval() def predict(self, img): # 预处理:resize、归一化、转 tensor img = cv2.resize(img, (640, 640)) img = img[:, :, ::-1].transpose(2, 0, 1) # BGR->RGB, HWC->CHW img = np.ascontiguousarray(img) img = torch.from_numpy(img).float() / 255.0 img = img.unsqueeze(0) with torch.no_grad(): pred = self.model(img)[0] return pred

逻辑说明:map_location='cpu'保证没 GPU 也能加载;eval()关掉 dropout 和 BN 的训练行为;预处理顺序不能乱,BGR 转 RGB 和归一化顺序反了,检测框会飘。参数上,640要和训练时的--img一致,不一致精度掉得厉害。

4.3 诊断逻辑与类别映射

检测输出的是舌质和舌苔的类别,诊断结论需要组合。源码里用了一个字典:

DIAGNOSIS_MAP = { ('hongshe', 'huangtai'): '湿热内蕴', ('hongshe', 'baitai'): '阴虚火旺', ('baishe', 'baitai'): '寒湿困脾', ('baishe', 'huangtai'): '脾虚湿热', }

这个映射是简化版,真实中医诊断还要看舌形、润燥、裂纹等。但毕业设计演示够用了。你可以把映射表抽成 JSON,方便不改代码就调整。

5. 避坑与常见问题排查:那些文档没写的翻车现场

5.1 训练 loss 为 nan

现象:第一个 epoch 跑几百步后 box_loss 变成 nan,之后全 nan。原因:学习率太大,或者数据里有标注框宽高为 0 的脏数据。解决:先把--lr0降到 0.001 试;不行就写脚本扫一遍 labels,把width==0 or height==0的行删掉。舌象数据集里偶尔有标注时手抖画成一条线的框,肉眼看不出来,脚本一扫就现形。

5.2 验证集 mAP 始终为 0

现象:训练 loss 正常降,但验证 mAP 一直是 0。原因:val.txt里的路径和实际图片对不上,或者tongue.yaml的names顺序和标注 class id 错位。解决:先cat val.txt | head看路径,再ls确认文件存在;然后随便抽一张图,用detect.py单张推理,看输出的类别名是不是你预期的。路径问题最常见的是 Windows 下反斜杠和 Linux 正斜杠混用,统一用正斜杠。

5.3 显存溢出 CUDA out of memory

现象:训练到一半报 OOM。原因:batch 太大,或者图片分辨率不统一导致某些 batch 特别大。解决:--batch减半,--img从 640 降到 416;再不行开--rect矩形训练,减少 padding。另外,训练前用脚本把所有图片 resize 到统一尺寸,能避免 dataloader 里动态 resize 带来的显存波动。

5.4 推理框位置偏移

现象:检测框能出,但框偏了,或者框住的是嘴唇不是舌头。原因:推理时的预处理和训练时不一致,最常见的是归一化方式不同(训练用/255,推理忘了除),或者 resize 时没保持长宽比。解决:把训练脚本里的预处理函数抽出来,推理时直接调用同一个函数,别手写第二套。

5.5 界面卡死无响应

现象:点检测按钮后界面转圈,几秒后无响应。原因:推理在主线程跑,阻塞了 UI 事件循环。解决:把推理逻辑放进QThread或threading.Thread,通过信号槽回传结果。源码里已经处理了,但如果你自己改界面,记得别在按钮回调里直接调model()。

6. 进阶技巧:用 TTA 和模型集成把 mAP 再提 5 个点

训练完别急着交差,还有两个不花钱的提点手段。第一个是 TTA(Test Time Augmentation),推理时对同一张图做翻转、多尺度,把结果融合。YOLO 官方推理脚本里带--augment参数,加上就行:

python detect.py --weights best.pt --source test/ --augment --conf 0.35

原理是模型对翻转后的图预测应该一致,融合能压掉一些抖动框。代价是推理慢 2~3 倍,演示时如果卡,可以关掉。

第二个是模型集成。把 YOLOv5s 和 YOLOv8s 各训一版,推理时两个模型都跑,用 WBF(Weighted Boxes Fusion)合并结果。WBF 比 NMS 温和,不会把两个模型都认可的框删掉。源码里没带 WBF,但ensemble-boxes这个库 pip 就能装:

from ensemble_boxes import weighted_boxes_fusion # boxes_list: 每个模型的框列表,归一化坐标 # scores_list: 对应置信度 # labels_list: 对应类别 boxes, scores, labels = weighted_boxes_fusion( boxes_list, scores_list, labels_list, iou_thr=0.5, skip_box_thr=0.3 )

参数上,iou_thr=0.5是融合阈值,两个模型框 IoU 超过 0.5 就认为是同一个目标;skip_box_thr=0.3过滤低置信框。集成后 mAP 一般能涨 3~5 个点,代价是推理时间翻倍。毕业设计答辩时如果评委问「怎么保证鲁棒性」,这就是现成的答案。

最后一个习惯:每次改完参数重新训,都在runs/train/下留一份results.csv,用 pandas 画个 mAP 曲线对比。我见过太多人改了三版参数,最后分不清哪版是哪版,只能重跑。从那以后我每次训完都强制把results.csv复制到experiments/目录,文件名带上日期和关键参数,再也没乱过。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询