基于YOLO的皮肤烧伤检测实战与模型部署全流程解析

发布时间:2026/9/28 16:28:43
基于YOLO的皮肤烧伤检测实战与模型部署全流程解析
简介这是一套基于深度学习的皮肤烧伤检测算法实战项目面向医疗AI研发人员、科研工作者及高校学生聚焦烧伤范围、深度与愈合情况的自动化识别提供从数据准备到模型部署的完整链路。资源共168个文件压缩包41.69MB主要文件类型包括43个Python脚本、38个YAML配置、16个Jupyter Notebook教程、13张JPG与11张PNG图片样本以及6个CSV指标记录文件其中py与ipynb可支撑核心模型复现与调参yaml用于训练环境与超参数配置csv可查看YOLOv5/YOLOv7等多次实验的评估结果另有Dockerfile便于容器化部署。已有105人学习下载。项目覆盖图像标准化、归一化、增强等预处理以及模型设计、损失函数与优化器选择、测试验证等关键环节并配有详细流程教程与清晰的目录结构便于按步骤操作。适合希望系统掌握医学图像识别落地实践并快速跑通烧伤检测模型的中高级开发者。1. 皮肤烧伤检测一份能跑起来的深度学习实战资源而不是 PPT先说结论这是一份以 YOLO 系目标检测为主线的皮肤烧伤检测工程包包含源码、训练结果 CSV、超参进化记录和 Dockerfile不是那种只给几个 Notebook 的教学演示。我从文件清单里看到yolov5_runs.csv、yolov7_runs.csv、evolve.csv、optimized_network_results.csv这些产物说明作者是真正跑过对比实验、做过超参搜索的这一点比“号称完整”的源码包靠谱得多。皮肤烧伤检测是医疗 AI 里少有的“能落地验证”的方向烧伤面积估算、深度分级、愈合阶段判断本质都是图像识别任务而且公开可获取的烧伤图像比很多医疗影像更容易组织成训练集。对想入门深度学习 医疗图像的人来说这个项目最大的价值在于它是一条完整的工程链路数据怎么组织、模型怎么选、训练参数怎么设、结果怎么看、模型怎么部署全部串起来了。适合两类人一是要做课程设计或毕设的学生二是想快速跑通一个医疗检测 Demo 的从业者。2. 任务建模与数据处理先搞清楚模型要学什么2.1 为什么是目标检测而不是图像分类烧伤检测和“这是不是烧伤”是两回事。分类模型只能回答“有没有”而临床需要的往往是“哪里烧了、烧到多深、面积多大”。目标检测天然适合这个场景它输出的是边界框坐标、类别和置信度框出来的区域可以直接估算烧伤面积占比多类别输出可以对应 I 度、II 度、III 度的分级。这个项目采用 YOLO 而不是 Faster R-CNN核心原因是速度YOLO 的单阶段结构把区域建议和分类合并成一次前向传播在 GPU 上能跑到实时帧率后续部署到诊断辅助系统时更容易满足“拍完立刻出结果”的体验要求。从文件清单看项目沿用了 YOLO 生态的标准流程这意味着数据集应该是按images/和labels/分开组织的标注文件是 YOLO 格式的 txt。很多初学者直接在网上下载别人整理好的 VOC 格式数据再回头转 YOLO整个过程里最容易出问题的是坐标归一化——VOC 的坐标是绝对像素值YOLO 要的是相对宽高的比例转换脚本写错一个除法训练出来的模型就会在推理时预测出一堆超出图像边界的框。2.2 数据目录组织与格式转换脚本我按常规 YOLO 项目结构重建一下数据目录这是复现的第一步。原项目里大概率有类似脚本如果没有按下面的方式组织也完全兼容。import os import random import shutil from PIL import Image def prepare_yolo_dataset(src_img_dir, src_xml_dir, dst_root, val_ratio0.2): 把 VOC 风格的图像 XML 标注转换为 YOLO 风格目录 train_img_dir os.path.join(dst_root, images, train) val_img_dir os.path.join(dst_root, images, val) train_lbl_dir os.path.join(dst_root, labels, train) val_lbl_dir os.path.join(dst_root, labels, val) for d in [train_img_dir, val_img_dir, train_lbl_dir, val_lbl_dir]: os.makedirs(d, exist_okTrue) img_files [f for f in os.listdir(src_img_dir) if f.endswith(.jpg)] random.shuffle(img_files) val_count int(len(img_files) * val_ratio) for idx, img_name in enumerate(img_files): xml_name img_name.replace(.jpg, .xml) xml_path os.path.join(src_xml_dir, xml_name) if not os.path.exists(xml_path): continue img Image.open(os.path.join(src_img_dir, img_name)) w, h img.size boxes parse_voc_xml(xml_path, w, h) if idx val_count: img_dst, lbl_dst val_img_dir, val_lbl_dir else: img_dst, lbl_dst train_img_dir, train_lbl_dir shutil.copy(os.path.join(src_img_dir, img_name), img_dst) with open(os.path.join(lbl_dst, img_name.replace(.jpg, .txt)), w) as f: for cls_id, cx, cy, bw, bh in boxes: f.write(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}\n)这里parse_voc_xml是你自己写的 XML 解析函数返回值是[类别ID, 中心点x, 中心点y, 宽度, 高度]的列表全部除以图像宽高做归一化。转换完成后我一般会随机抽 20 张图把标签画回图上检查一遍确认框和烧伤区域对齐再进入训练环节。这一步花十分钟能省掉后面排查“模型什么都检测不到”的两小时。3. 模型训练与效果验证跑通 YOLOv5 的实际训练闭环3.1 数据配置与训练命令YOLOv5 的训练入口是train.py但数据集的路径和类别定义要先写进一个 yaml 文件训练脚本通过它找到数据。烧伤检测项目里常见的类别有burn_degree_1、burn_degree_2、burn_degree_3等具体以你手上的标签文件为准。# burn.yaml train: ./dataset/images/train val: ./dataset/images/val nc: 3 names: [first_degree, second_degree, third_degree]训练命令我一般这么起python train.py \ --data burn.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --project runs/burn_train--img 640是输入分辨率。医疗图像不像自然图像那样有大尺寸目标烧伤区域的边界往往靠纹理细节区分如果显存允许我建议把--img提到 768 甚至 896能明显提升小区域烧伤的召回率。--batch 16看显存调整如果你是 8G 显存的卡batch 8 更稳妥否则会在前向传播时报 CUDA out of memory。训练过程里要盯住两个指标mAP0.5和val loss。如果mAP0.5在前 20 个 epoch 一直低于 0.3大概率不是训练轮次不够而是标注数据有问题或类别分布严重不平衡这时候继续跑下去没有意义。3.2 结果 CSV 里哪些指标值得看项目里有yolov5_runs.csv和yolov7_runs.csv这两个文件记录的是每次训练运行的评估指标。我打开过很多次这种 CSV列名一般是epoch、train_loss、val_loss、mAP0.5、mAP0.5:0.95、precision、recall。对于烧伤检测我优先看三列指标关注原因合理范围参考mAP0.5框的位置准确度IoU 阈值放宽到 0.5反映“大致框对”的能力0.7 以上算可用mAP0.5:0.95严格指标要求框的位置非常精确0.4 以上算合格recall烧伤区域漏检率医疗场景漏检比误检更危险越高越好建议 0.85 以上注意yolov5_runs.csv和yolov7_runs.csv的对比逻辑同样是 100 个 epochYOLOv7 通常收敛更快但模型体积和推理耗时也更大。如果项目最终要部署到没有独立显卡的环境YOLOv5s 的权重只有 14MB 左右比 YOLOv7 的 70MB 更适合。4. 超参进化实验从 evolve.csv 里解读参数优化的意义4.1 YOLOv5 的遗传进化超参搜索是什么evolve.csv和evolve-checkpoint.csv这两个文件是 YOLOv5 的超参进化机制写出来的。原理不复杂每一代训练时脚本会随机修改一批超参数学习率、权重衰减、锚框缩放系数、数据增强概率等然后在这些超参数组合下训练少量轮次用验证集上的 mAP 作为适应度评分。表现好的超参数组合会被保留下来并作为下一代变异的基础。这个过程类似遗传算法跑 300 代之后留下来的参数组合基本就是针对当前数据集做过适配的最优解。启动进化训练的命令是python train.py \ --data burn.yaml \ --weights yolov5s.pt \ --epochs 50 \ --evolve 100 \ --cache \ --device 0--evolve 100表示跑 100 代进化每一代都会重新启动一次训练任务所以总耗时约等于 100 × 50 个 epoch。--cache参数把图像预加载进内存进化阶段每次迭代都要反复读取数据缓存能减少磁盘 IO 的等待时间。跑完以后evolve.csv里每一行是一代的最优参数组合evolve-checkpoint.csv是中间断点方便随时暂停恢复。4.2 优化后的超参数怎么用optimized_network_results.csv是这套改进参数组合跑完整训练之后的结果汇总。在进化完成后脚本会在runs/evolve目录下生成一个hyp_evolved.yaml训练的时候把它拿来替换默认的超参文件python train.py \ --data burn.yaml \ --weights yolov5s.pt \ --hyp runs/evolve/hyp_evolved.yaml \ --epochs 200 \ --batch 32 \ --device 0我从进化前后的对比经验里总结一个规律进化搜索过的超参组合在相同 epoch 数下通常能把 mAP0.5 提升 3 到 8 个百分点尤其是针对小目标较多的烧伤图像锚框的缩放系数从默认的 0.5~2.0 调整为更小的范围后小面积烧伤的检测召回率提升尤其明显。代价是训练时间翻倍所以如果你只是验证流程直接跑默认超参即可如果要追求最终精度进化是值得投资的。5. 复现避坑烧伤检测项目里最常见的五个翻车现场5.1 训练正常但推理结果全为空现象detect.py跑完输出图片上没有任何标注框。原因训练时 yaml 里的类别顺序和数据集标签不一致。比如你标注文件里类别 1 是second_degree但 yaml 的names列表里第二个位置写的是first_degree模型学到的是一个错乱的类别映射推理时就无法正确匹配目标。解决查看labels/train里任意一个 txt 文件第一列数字是什么在 yaml 的names列表里对应位置就放什么类别名。我会写一个 10 行的脚本统一检查所有标注文件的类别 ID 是否在0 ~ nc-1范围内跑一次就能发现越界标签。5.2 烧伤边缘区域误检率高现象检测框把正常皮肤和烧伤区域的交界处也框了进去置信度还不低。原因烧伤创面的边缘往往伴随红肿和渗液在 RGB 图像上和正常皮肤纹理差异大模型学到的是“纹理剧烈变化”这个特征而不是“烧伤”本身。另外训练样本里边缘特写图占比过高放大了这个偏差。解决在预处理阶段对烧伤区域做了高斯边缘平滑模拟或者调整标签框让标注框稍微向内收缩 5 到 10 个像素把模糊交界排除在正样本之外。等模型收敛后再去测试集上检查误检率是否下降。5.3 loss 一直下降但 mAP 不涨现象训练日志里train_loss从 0.08 降到 0.02但mAP0.5停留在 0.5 左右不动。原因烧伤图像里背景区域占比极大模型只需要预测“背景”就能把 loss 降到很低但真正有价值的烧伤区域召回率没上来。本质是正负样本比例失衡。解决启用 YOLOv5 的 mosaic 增强概率默认 1.0 已经开了另外在数据层面增加更多包含小面积烧伤的图像或者用--multi-scale参数让输入尺度随机变化。5.4 训练中途显存溢出现象大概跑到第 30 个 epoch报CUDA out of memory。原因设置了--cache或输入尺寸过大同时 batch 偏高。缓存图像占用了显存模型前向传播时没有足够空间。解决按显存容量做减法——8G 显存用--img 640 --batch 8不用--cache12G 显存可以尝试--img 768 --batch 8。注意清理runs/下旧实验的缓存文件我遇到过 SSD 满了但日志提示显存不足的情况。5.5 部署到 CPU 时推理极慢现象一张 640×640 图像在 CPU 上跑 800ms现场完全无法使用。原因YOLOv7 模型参数量大且代码默认使用 FP32 精度推理CPU 上没有任何硬件加速。解决换成 YOLOv5s 权重并做 INT8 量化导出CPU 推理能压到 200ms 左右烧伤场景的实时性基本够用。6. 部署路径用 Docker 和 ONNX 把模型封装成可用服务6.1 Dockerfile 的构建思路与参数说明项目带了一个 Dockerfile这是把训练好的模型部署出去的最后一步。我常用的写法是在基础镜像里预装 ONNX Runtime因为它在 CPU 上的推理速度比 PyTorch 原生的 eager mode 快 2 到 3 倍而且不要求 GPU。FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt onnxruntime1.16.0 COPY weights/best.onnx ./weights/ COPY app.py . EXPOSE 8080 CMD [python, app.py]这里把模型权重、推理脚本和依赖一起打进了镜像运行时只需要一条docker run -p 8080:8080就能启动推理服务。注意onnxruntime1.16.0是一个锁定版本不同版本的算子支持有差异锁定它能避免部署环境重新下载带来的“在我电脑上明明好的”问题。6.2 导出 ONNX 与检查输入输出一致性导出 ONNX 是部署的最后一个技术细节。用 YOLOv5 自带的导出脚本最省事python export.py --weights runs/burn_train/exp/weights/best.pt --include onnx --opset 11导出完成后一定要检查输入输出的尺寸。YOLOv5 原始导出结果的输出是1 × 25200 × 85的三维张量其中 25200 是三个尺度特征图上的预测框总数85 是 4 个坐标 1 个置信度 80 个类别概率。但烧伤检测项目的类别数往往是 3 或 4 类导出后的输出维度不再是 85而是5 nc。如果你直接用通用推理代码会拿到一串没意义的概率值。我通常会在导出后写一段 20 行的校验脚本随机取一张验证集图像分别跑 ONNX 和 PyTorch 模型比较输出张量的绝对误差超过 1e-4 就说明导出参数有问题这种“先验后部署”的做法成功率最高。从那以后我每次做模型交付都会强制走一遍 ONNX 一致性校验哪怕只是改一个输入尺寸也不会跳过这一步。希望帮到你。本文还有配套的精品资源点击获取