基于YOLOv5的舌象诊断系统:从数据标注到模型部署的完整实战指南
发布时间:2026/9/4 8:57:13来源:尧图网络
简介本资源是一套面向计算机专业本科生及中医信息化初学者的高分毕业设计项目聚焦于传统中医舌诊的智能化落地基于Python与YOLOv系列模型实现舌象区域检测与初步辨识。资源包含完整可运行系统含54个带详细注释的Python源码文件覆盖数据预处理、YOLO训练、GUI界面开发等核心模块、61张标注清晰的舌象JPEG/JPG样本、7个配置与结果JSON文件、2个PyQt设计UI界面及配套文档说明总文件数184个压缩包大小42.67MB。目前已有387人学习下载项目经严格调试支持一键部署与本地演示附《基于深度学习的舌象诊断系统学习路线》等指导性文档代码结构分层合理、模块职责明确特别适合毕设开题、课程设计与期末大作业参考。1. 项目缘起从“高分毕设”到实用工具的思考最近在整理硬盘时翻出了几年前做的一个老项目一个基于Python和YOLOv5的舌象诊断系统。当时为了毕业设计绞尽脑汁既要体现技术深度又要有实际应用价值最终选择了这个结合了传统中医与现代计算机视觉的课题。现在回头看虽然当时用的YOLOv5版本已经迭代了好几代但整个项目的设计思路、数据处理流程和遇到的坑对于想入门深度学习应用特别是医疗图像分析的朋友来说依然有很强的参考价值。这个项目之所以能拿高分关键在于它不是一个简单的“玩具”Demo而是从数据采集、标注、模型训练到部署推理形成了一个相对完整的闭环。今天我就把这个项目的核心实现、踩过的坑以及一些后续的优化思考系统地梳理出来希望能给正在做类似课题或者对AI医疗感兴趣的你提供一份可以直接“抄作业”的实战指南。舌诊是中医“望闻问切”中非常重要的一环医生通过观察舌头的颜色、形状、苔质等特征来推断人体的健康状况。传统方法依赖医生的经验主观性强且难以量化。我们这个项目的目标就是尝试用深度学习的方法让机器自动从舌象图片中识别出关键区域如舌体、舌苔并分析其特征为辅助诊断提供一个客观、可量化的参考工具。整个系统基于Python开发核心是YOLO目标检测算法配合OpenCV等库进行图像预处理和后处理。2. 核心任务拆解一个舌诊系统到底要做什么在动手写代码之前我们必须清晰地定义系统要完成的具体任务。这直接决定了我们数据集的构建方式、模型的选择以及后续的评价标准。一个完整的舌象诊断系统通常包含以下几个核心步骤我们可以将其视为一个流水线第一步舌体区域定位与分割。这是所有后续分析的基础。给定一张可能包含人脸、背景杂物的口腔照片系统必须能精准地框出舌头所在的区域。这本质上是一个目标检测任务。我们为什么选择YOLO而不是传统的图像分割方法如U-Net起步因为在初期我们更需要一个快速、准确的定位工具将舌头从复杂背景中“找出来”。YOLO的单阶段检测特性在速度和精度上取得了很好的平衡非常适合作为预处理模块。第二步舌象特征提取与分类。在精准定位到舌头后我们需要对舌体本身的特征进行分析。这包括舌质颜色分类如淡红、淡白、红、绛红、青紫等。舌苔颜色与质地分类如白苔、黄苔、灰黑苔以及薄苔、厚苔、腻苔、燥苔等。舌形判断如胖大、瘦薄、齿痕、裂纹等。这部分任务可以建模为图像分类问题但更精细的做法是在定位的基础上对舌体区域进行关键点检测或语义分割从而分区如舌尖、舌中、舌根分析不同特征。在我们的毕设版本中为了控制复杂度主要实现了舌体和舌苔区域的粗略分割与颜色统计。第三步诊断规则映射与报告生成。将第二步提取出的量化特征如RGB/HSV颜色空间的均值、方差纹理特征形状参数与中医诊断学中的经验规则进行映射。例如“舌质淡白舌苔白腻”可能对应“脾虚湿盛”的证型。最后系统需要生成一份结构化的诊断报告列出检测到的各项特征及其可能的临床意义。我们的项目重点攻克了第一步和第二步的基础部分即用YOLO实现高精度的舌体检测并在此基础上进行初步的颜色特征分析。第三步的诊断规则库是一个庞大的知识工程在毕设中我们仅实现了一个非常简单的示例性映射以展示系统闭环的可能性。3. 数据集项目的基石与最大挑战“巧妇难为无米之炊”在深度学习项目中数据的重要性甚至超过模型本身。对于舌象诊断这样一个垂直领域公开可用的、标注质量高的数据集非常稀少。当时我们主要通过以下几种方式构建自己的数据集3.1 数据采集与合规性考量我们通过与本地一所中医药大学合作在严格遵守伦理规范和知情同意的前提下采集了约1500张志愿者舌象照片。采集时注意了以下几点这些细节直接影响模型效果环境光标准化尽量在光线均匀的室内使用D65标准光源补光减少色偏。我们使用了便携式校色灯箱虽然成本不高但能极大提升数据一致性。拍摄规范要求志愿者自然伸舌充分暴露舌体。拍摄角度尽量正面避免过度拉伸或扭曲。使用同一款手机的后置摄像头固定对焦距离。背景简化要求志愿者站在纯色最好是白色或浅灰色背景前减少后续分割的干扰。注意任何涉及人体生物特征数据的项目都必须优先考虑隐私与伦理。我们所有数据均进行了脱敏处理抹去面部其他特征仅保留口唇和舌部区域并与参与者签署了数据用于科研的授权协议。这是项目能够合法进行的前提。3.2 数据标注精细活里的门道我们使用LabelImg工具进行标注。对于目标检测任务标注似乎就是画框但里面的讲究很多标注类别定义我们定义了三个主要类别tongue_body舌体、tongue_coating舌苔、mouth口腔区域用于辅助定位非必需。这里的一个关键决策是是否将舌苔单独标注如果只标舌体那么颜色分析会混合舌质和舌苔信息不纯。单独标注舌苔可以让模型学习区分两者为后续独立分析打下基础。框体精度框要紧贴舌体边缘特别是舌尖和舌根部分避免带入过多嘴唇或喉咙区域。我们要求标注人员经过简单培训并进行了多轮交叉校验确保标注一致性。数据增强策略由于样本量有限数据增强是必须的。我们采用了以下组合色彩空间扰动在HSV空间轻微调整色调(H)、饱和度(S)、明度(V)模拟不同光照和肤色下的舌象。几何变换随机水平翻转舌象通常左右对称翻转是安全的、小角度旋转±10度、随机缩放和裁剪。关键技巧对于医学图像谨慎使用过于激进的数据增强如大角度旋转、扭曲等可能会生成不符合解剖结构的“病态”图像误导模型。我们的原则是“模拟真实拍摄中可能出现的微小变化”。3.3 数据集划分与版本管理我们将1500张图片按7:2:1的比例划分为训练集1050张、验证集300张和测试集150张。这里容易踩的一个坑是务必确保划分是随机的且来自同一个志愿者的多次拍摄图片必须被划分到同一个集合训练、验证或测试中防止数据泄露。我们根据志愿者ID进行划分保证了模型的评估有效性。所有原始图片、标注文件YOLO格式的.txt文件包含类别索引和归一化后的框坐标、以及划分好的文件列表都用一个清晰的目录结构进行管理。我们当时用了简单的脚本和README文件来记录现在看如果用DVCData Version Control之类的工具会更专业。tongue_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── data.yaml # YOLO数据集配置文件 └── README.md # 数据说明data.yaml文件是YOLO模型读取数据的入口其内容大致如下# 数据集路径相对路径或绝对路径 path: ../tongue_dataset train: images/train val: images/val test: images/test # 类别数量与名称 nc: 3 names: [tongue_body, tongue_coating, mouth]4. 模型选型与YOLOv5实战调优当时YOLOv5正处在风口以其易用性和出色的性能著称。我们选择了YOLOv5s这个“小”模型作为起点因为它速度最快在当时的计算资源一台GTX 1060显卡的笔记本上也能快速迭代。4.1 环境搭建与依赖管理为了避免“配环境三天跑代码一分钟”的窘境强烈建议使用Conda创建独立的Python环境。# 创建环境 conda create -n tongue_yolo python3.8 conda activate tongue_yolo # 安装PyTorch (请根据你的CUDA版本去官网选择对应命令) pip install torch1.9.0cu111 torchvision0.10.0cu111 -f https://download.pytorch.org/whl/torch_stable.html # 克隆YOLOv5仓库并安装依赖 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt用requirements.txt管理依赖能确保在任何机器上复现完全相同的环境。4.2 训练过程与核心参数解析训练命令看起来简单但每个参数都值得推敲python train.py --img 640 --batch 16 --epochs 100 --data ../tongue_dataset/data.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --name tongue_det_v1 --cache--img 640: 输入图像尺寸。YOLOv5内部会缩放到这个尺寸。更大的尺寸如1280可能提升对小目标的检测精度但会显著增加显存消耗和训练时间。对于舌体这种中型目标640是一个不错的平衡点。--batch 16: 批量大小。受限于显存6GB的GTX 1060我们只能设到16。如果出现CUDA out of memory错误可以减小batch或--img。--epochs 100: 训练轮数。不是越多越好需要观察验证集损失曲线防止过拟合。--data: 指向我们刚才准备的data.yaml文件。--cfg: 模型配置文件。我们使用官方的ssmall结构。--weights yolov5s.pt: 加载预训练权重。这是提升小数据集性能的关键使用在COCO等大型通用数据集上预训练的权重可以让模型已经具备了提取通用视觉特征的能力我们只需要对其进行“微调”Fine-tuning使其适应舌体这个特定目标这比从零训练快得多效果好得多。--name: 给本次实验起个名字所有日志、模型权重都会保存在runs/train/目录下。--cache: 将图像缓存到内存或磁盘加速训练。如果数据集不大且内存足够建议开启。4.3 训练监控与调优实战训练开始后不要干等着。YOLOv5会自动启动TensorBoard我们可以在浏览器打开http://localhost:6006来监控关键指标损失曲线train/loss, val/loss关注训练损失是否平稳下降验证损失是否在后期开始上升过拟合迹象。性能指标metrics/mAP_0.5, metrics/mAP_0.5:0.95这是核心。mAP_0.5指IoU阈值为0.5时的平均精度mAP_0.5:0.95是在多个IoU阈值下的平均值后者更严格。我们的目标是让这两个值在验证集上尽可能高。标签分布labels查看训练集标注框的尺寸、位置分布确保覆盖了各种情况。在初次训练后我们发现了几个问题舌苔的检测精度mAP远低于舌体。分析原因舌苔与舌体质地颜色有时对比不明显且标注边界本身存在一定主观性。部分侧拍或光线很暗的图片漏检。针对性的调优策略针对问题1舌苔难检我们检查了标注质量对模糊边界进行了统一修订。同时在数据增强中适度增加了色彩对比度的扰动让模型学会在颜色对比弱的情况下也能区分边界。此外我们尝试了调整损失函数中的类别权重给tongue_coating类别稍微高一点的权重让模型在训练时更“关注”它。在YOLOv5中这可以通过修改data.yaml中的hyp.scratch.yaml配置文件里的cls_pw分类损失权重参数来实现但需要谨慎调整避免破坏平衡。针对问题2极端样本漏检我们将这些漏检的样本单独拿出来加入训练集进行重训练。同时在数据增强中增加了模拟暗光随机降低亮度和侧视角模拟仿射变换中的轻微错切的策略提升模型的鲁棒性。学习率调整初始我们使用默认的学习率。当验证集损失陷入平台期时我们尝试了余弦退火Cosine Annealing学习率调度策略让学习率随着训练过程周期性变化有助于模型跳出局部最优。经过几轮迭代我们的模型在测试集上的mAP_0.5达到了0.92以上mAP_0.5:0.95也超过了0.7对于毕设要求和实际辅助应用来说已经是一个相当可靠的结果。5. 从模型到系统推理部署与特征分析训练出一个好模型只是第一步如何将它集成到一个可用的系统中并提取出有诊断价值的特征是更见功力的部分。5.1 构建推理管道我们编写了一个inference.py脚本其核心流程如下import cv2 import torch import numpy as np from yolov5.utils.general import non_max_suppression, scale_boxes from yolov5.utils.torch_utils import select_device import yaml class TongueDetector: def __init__(self, weights_path, data_yaml_path, conf_thres0.5, iou_thres0.45): self.device select_device() self.model torch.load(weights_path, map_locationself.device)[model].float().eval() self.conf_thres conf_thres self.iou_thres iou_thres with open(data_yaml_path) as f: self.data_info yaml.safe_load(f) self.names self.data_info[names] def detect(self, image_path): # 1. 读取并预处理图像 img0 cv2.imread(image_path) img cv2.cvtColor(img0, cv2.COLOR_BGR2RGB) img letterbox(img, new_shape640)[0] # 保持长宽比的resize img img.transpose(2, 0, 1) # HWC to CHW img np.ascontiguousarray(img) img torch.from_numpy(img).to(self.device).float() img / 255.0 # 归一化 # 2. 推理 with torch.no_grad(): pred self.model(img[None])[0] # 增加batch维度 # 3. NMS后处理 pred non_max_suppression(pred, self.conf_thres, self.iou_thres) # 4. 解析结果将坐标映射回原图 detections [] for det in pred: if len(det): det[:, :4] scale_boxes(img.shape[1:], det[:, :4], img0.shape).round() for *xyxy, conf, cls in det: label self.names[int(cls)] detections.append({ bbox: [int(x) for x in xyxy], label: label, confidence: float(conf) }) return img0, detections这个类封装了加载模型、图像预处理、推理和后处理的全过程。其中letterbox函数是YOLO系列保持图像原始比例进行填充缩放的常用方法避免图像变形。5.2 舌象特征提取实战检测到舌体框后我们将其从原图中裁剪出来进行特征分析。def extract_tongue_features(tongue_roi): tongue_roi: 裁剪出的舌体区域图像 (BGR格式) features {} # 1. 颜色特征 - 转换到HSV空间分析更符合人眼感知 hsv cv2.cvtColor(tongue_roi, cv2.COLOR_BGR2HSV) # 计算舌体区域在HSV各通道的均值 features[h_mean], features[s_mean], features[v_mean] cv2.mean(hsv)[:3] # 计算颜色直方图 (以H通道为例) hist_h cv2.calcHist([hsv], [0], None, [180], [0, 180]) # H通道范围0-180 features[hist_h] hist_h.flatten() # 2. 纹理特征 - 使用灰度共生矩阵(GLCM)或LBP (这里以简单的标准差示例) gray cv2.cvtColor(tongue_roi, cv2.COLOR_BGR2GRAY) features[texture_std] np.std(gray) # 灰度图标准差反映纹理粗糙度 # 3. 形状特征 (需结合分割这里用检测框近似) height, width tongue_roi.shape[:2] features[aspect_ratio] width / height if height 0 else 0 return features对于舌苔我们同样在检测框内进行分析。更高级的做法是利用tongue_body和tongue_coating两个框的位置关系可以更精确地提取舌苔区域例如舌苔框在舌体框内部然后单独计算舌苔的颜色和面积占比等特征。5.3 简单的诊断规则映射示例基于提取的特征我们可以设定一些简单的阈值规则def simple_diagnosis(features): diagnosis [] # 示例规则根据舌质平均亮度(V通道)和饱和度(S通道)判断 if features[v_mean] 100 and features[s_mean] 50: diagnosis.append(舌质偏淡可能提示气血不足) elif features[v_mean] 180 and features[s_mean] 100: diagnosis.append(舌质红可能提示有热象) # 示例规则根据舌苔面积占比需要分割结果此处简化 # if coating_area_ratio 0.8: # diagnosis.append(苔厚) return diagnosis当然真正的中医诊断规则极其复杂涉及多特征组合和模糊逻辑。在毕设中我们实现这个简单的映射主要是为了演示系统流程的完整性。更严谨的做法是构建一个基于机器学习如SVM、随机森林或简单神经网络的分类器用大量已由中医专家标注的数据来学习特征与证型之间的映射关系。6. 项目总结、踩坑实录与未来展望回顾整个项目从选题、数据准备、模型训练到系统集成是一个完整的深度学习应用开发流程。在这个过程中我深刻体会到几个比模型本身更重要的东西6.1 数据质量是天花板模型性能的上限在数据标注时就决定了。我们花了近一半的时间在数据采集、清洗和标注上。初期因为标注不规范框体时松时紧导致模型定位精度波动很大。统一标注标准并进行交叉校验后效果立竿见影。对于专业领域如果条件允许最好由领域专家中医师参与或审核标注。6.2 实验记录与可复现性我们一开始没有系统记录每次训练的配置和结果导致调参过程混乱。后来强制要求每次实验都在train.py的命令后加上--project runs/exp --name lr0.01_augment这样的参数并在README里用表格记录每次实验的关键参数学习率、数据增强组合、mAP结果等效率大大提升。推荐使用Weights Biases或MLflow等专业工具。6.3 部署时的环境陷阱训练环境Cuda 11.1, PyTorch 1.9和部署环境可能是另一台机器或服务器的不一致是另一个大坑。我们曾遇到在训练机上精度很高的模型在另一台Cuda版本不同的机器上推理速度慢甚至报错。最终的解决方案是使用Docker将整个推理环境包括Python版本、库版本容器化确保了“一次构建到处运行”。6.4 性能与精度的权衡在最终部署时我们尝试了将PyTorch模型转换为ONNX格式并进一步用TensorRT进行加速。在保持精度损失小于1%的前提下推理速度提升了3-5倍。这对于未来开发实时或移动端应用至关重要。转换过程本身也有一些坑比如某些算子不支持需要调整模型结构或使用特定版本的转换工具。这个毕设项目只是一个起点。如果今天让我来迭代它我会从以下几个方向深入模型升级与多任务学习采用YOLOv8或更先进的YOLO版本并尝试将目标检测与语义分割结合在一个模型中如YOLO分割头一次性输出舌体的检测框和像素级分割掩膜为特征提取提供更精确的区域。引入更鲁棒的特征提取方法结合传统图像处理如颜色聚类、纹理滤波和深度学习特征如使用在ImageNet上预训练的CNN backbone提取舌象的深度特征构建更全面的特征向量。构建小型诊断知识库与中医专家合作将一些经典的、共识度高的舌象-证型对应关系数字化构建一个可查询、可推理的轻量级知识库让系统的输出更有解释性。设计友好的交互界面使用Gradio或Streamlit快速搭建一个Web界面让非技术人员如中医学生也能上传图片、查看检测结果和特征分析报告收集反馈形成迭代闭环。深度学习技术与传统领域的结合难点往往不在算法本身而在于对领域知识的深刻理解、高质量数据的获取以及工程化落地的细节处理。这个舌象诊断项目就像一座桥梁希望我的这些经验分享能帮你更稳当地走过这座桥去探索更广阔的AI应用天地。本文还有配套的精品资源点击获取
网站建设高端定制企业官网