
简介这份资源面向医学影像分析人员、机器学习开发者及疾病筛查研发工程师提供一套基于YOLOv5的直肠息肉检测系统完整实现方案用于辅助医疗专家进行息肉的自动检测与早期筛查。内容覆盖环境搭建、数据集创建与配置文件编写、模型训练、ONNX格式导出、性能评估与指标可视化以及Tkinter图形界面搭建和代码整合等环节并探讨多类别检测、数据增强、集成学习与云部署等后续升级方向。资源包共1个docx文档约41KB以文字说明形式系统梳理项目介绍、特点、详细实现步骤与注意事项目录结构清晰便于按模块查阅。已有120人学习关注。读者可据此掌握从数据准备到GUI落地的完整流程理解精确度、召回率、F1分数等评估指标的运用并获得可扩展的工程思路与排错参考适合具备一定深度学习基础、希望切入医疗图像检测方向的开发者研读实践。1. 直肠息肉检测为什么值得用 YOLOv5 做一遍肠镜室里最耗神的不是操作本身而是医生盯着屏幕一帧一帧找息肉的那几分钟。一枚直径 5mm 以下的扁平息肉在 1080p 画面里可能只占几十个像素加上肠道蠕动、反光、气泡干扰漏检率一直下不来。基于 YOLOv5 的直肠息肉检测系统本质上就是把这件「人眼容易疲劳、标准难以统一」的事交给一个能在 30FPS 以上实时跑的单阶段检测器。它解决的不是「能不能检出」的学术问题而是「在普通显卡甚至边缘设备上能不能稳定跑起来、能不能复现」的工程问题。这套方案适合三类人一是手里有肠镜图像或视频、想快速搭一个可演示原型的算法工程师二是要做医学图像课程设计、需要完整程序和数据集的学生三是想验证 YOLOv5 在真实医疗场景下量化部署可行性的嵌入式开发者。标题里说的「详细的完整的程序和数据」落到实操上就是一份可训练的 YOLOv5 工程、一份标注好的息肉数据集、一套从训练到推理再到量化的脚本。下面按「数据怎么准备 → 模型怎么训 → 指标怎么看 → 坑在哪 → 怎么部署」的顺序把这条链路走通。2. 数据集准备与 YOLOv5 格式转换从原始肠镜图到可训练标签2.1 直肠息肉数据集的来源与标注策略公开的直肠息肉数据集常见做法是拿 Kvasir-SEG、CVC-ClinicDB 这类分割数据集改造成检测数据集。它们原本给的是像素级掩码你需要把掩码转成边界框。我一般会先用 OpenCV 找掩码的外接矩形再按 YOLO 的归一化格式写标签。标注时有两个原则一是边界框要紧贴息肉边缘不要为了「保险」往外扩太多否则 NMS 阶段容易把相邻息肉合并二是对于遮挡超过 50% 的息肉宁可标成困难样本单独放一个子集也不要强行标全否则训练时回归损失会被带偏。数据量方面Kvasir-SEG 大约 1000 张CVC-ClinicDB 约 612 张合并去重后能到 1400 张左右。这个量级对 YOLOv5s 来说偏少所以数据增强必须开足。常见做法是 HSV 色调扰动、随机缩放、马赛克增强但医学图像要慎用上下翻转——肠道解剖结构有方向性翻转后可能引入不存在的伪影。左右翻转相对安全可以保留。2.2 把掩码转成 YOLO 标签的脚本与四个边界坑下面这段脚本做两件事读掩码图找轮廓生成 YOLO 格式的 txt 标签。假设目录结构是images/和masks/一一对应。import cv2 import os import numpy as np # 输入输出路径 img_dir dataset/images mask_dir dataset/masks label_dir dataset/labels os.makedirs(label_dir, exist_okTrue) for name in os.listdir(mask_dir): mask_path os.path.join(mask_dir, name) mask cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE) if mask is None: continue # 二值化掩码里息肉区域通常为白色 _, binary cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY) contours, _ cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) h, w mask.shape lines [] for cnt in contours: # 过滤掉面积过小的噪点阈值按图像分辨率调整 if cv2.contourArea(cnt) 30: continue x, y, bw, bh cv2.boundingRect(cnt) # YOLO 格式类别 cx cy bw bh全部归一化到 0-1 cx (x bw / 2.0) / w cy (y bh / 2.0) / h nw bw / float(w) nh bh / float(h) lines.append(f0 {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}) txt_name os.path.splitext(name)[0] .txt with open(os.path.join(label_dir, txt_name), w) as f: f.write(\n.join(lines))逻辑说明cv2.findContours用RETR_EXTERNAL只取最外层轮廓避免掩码内部空洞产生多余框。面积阈值 30 是经验值1080p 图像下对应约 5×6 像素再小基本是噪声。归一化时注意cx和cy是中心点坐标不是左上角这是新手最容易写错的地方。四个边界坑第一掩码如果是 0/255 但息肉是黑色、背景白色阈值判断要反过来第二轮廓可能贴边boundingRect返回的框会超出图像边界训练时 YOLOv5 会做裁剪但最好自己先 clamp第三一张图可能有多个息肉脚本里已经用循环处理但类别号要确认是否都是 0第四文件名必须和图像严格对应YOLOv5 是按文件名找标签的差一个后缀就整张图被当负样本。2.3 数据集划分与 data.yaml 配置转换完成后按 8:1:1 划分训练、验证、测试。YOLOv5 不强制要求测试集但医学场景我建议单独留一份测试集因为验证集会被用来调超参指标会偏乐观。目录结构建议dataset/ images/train/ images/val/ images/test/ labels/train/ labels/val/ labels/test/对应的polyp.yamlpath: ./dataset train: images/train val: images/val test: images/test nc: 1 names: [polyp]nc是类别数直肠息肉检测通常只分「息肉」一类不要自作聪明去分大小或位置数据量不够时多分类只会让 mAP 掉得更快。names的顺序必须和标签里的类别号一致写反了训练能跑但结果全错。3. YOLOv5 训练配置与超参数调优让 mAP 从 0.6 爬到 0.853.1 模型选型s/m/l 在息肉检测上的取舍YOLOv5 提供 n/s/m/l/x 五个尺度。直肠息肉检测我一般从 s 起步原因是数据量小、目标尺度相对集中大模型容易过拟合。如果你有 5000 张以上标注数据可以上 m 或 l。下面是一组在 1400 张数据集上的对比输入 640×640batch 16训练 100 epoch模型参数量mAP0.5单帧推理RTX 3060显存占用yolov5n1.9M0.724ms2.1Gyolov5s7.2M0.837ms3.4Gyolov5m21.2M0.8514ms5.8Gyolov5l46.5M0.8424ms9.2G可以看到 m 相比 s 只涨了 2 个点但推理时间翻倍。如果最终要部署到树莓派 4B 或 RK3568 这类边缘设备s 甚至 n 才是现实选择。选型时先问自己推理硬件是什么如果答案是 Jetson 或带独显的工控机s 足够如果是纯 CPU 或 NPU直接考虑 n 加量化。3.2 训练命令与关键超参数含义python train.py \ --data polyp.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --hyp data/hyps/hyp.scratch-low.yaml \ --optimizer SGD \ --lr0 0.01 \ --lrf 0.01 \ --cos-lr \ --cache逐项说明--weights yolov5s.pt用 COCO 预训练权重医学数据量小时这是涨点最明显的一步从头训基本没戏。--img 640是输入分辨率息肉小目标多的话可以提到 1024但显存和速度要重新权衡。--hyp选 low 增强配置因为医学图像颜色和纹理敏感强增强反而有害。--lr0 0.01是初始学习率SGD 下这个值比较稳Adam 的话要降到 0.001。--lrf 0.01是最终学习率系数配合--cos-lr做余弦退火。--cache把图像缓存到内存小数据集能明显加快 epoch 速度。训练过程中重点看三个指标box_loss是否稳定下降、obj_loss有没有震荡、mAP0.5在第几个 epoch 开始 plateau。如果obj_loss一直不降大概率是标签格式错了或者正负样本划分有问题。3.3 超参数调优从 hyp.scratch-low 改哪几个值YOLOv5 的超参数文件里对息肉检测影响最大的是这几个mosaic: 1.0马赛克增强概率。小数据集建议保持 1.0但最后 10 个 epoch 可以关掉让模型适应真实分布。scale: 0.5随机缩放幅度。息肉尺度变化不大时可以降到 0.3避免小息肉被缩到看不见。hsv_h: 0.015色调扰动。肠镜图像偏红色调扰动太大会让模型学到不存在的颜色特征建议降到 0.01。flipud: 0.0上下翻转。前面说过医学图像不要开。fliplr: 0.5左右翻转。可以保留肠道左右结构相对对称。我一般会先跑 20 epoch 看 loss 曲线如果box_loss下降太慢把lr0提到 0.02如果mAP波动大把batch从 16 降到 8同时lr0减半。这些调整没有银弹但方向是明确的小数据 预训练权重学习率宁小勿大增强宁弱勿强。4. 指标解读与推理验证mAP 高不代表临床可用4.1 看懂 YOLOv5 输出的混淆矩阵和 PR 曲线训练结束后runs/train/exp下会生成confusion_matrix.png和PR_curve.png。混淆矩阵里重点看背景被误判成息肉的 FP 数量。临床场景下假阳性太多会让医生频繁确认体验极差假阴性则是漏检后果更严重。所以调阈值时宁可稍微牺牲一点精确率也要把召回率拉上去。PR 曲线上看mAP0.5对应的 recall 值如果 recall 低于 0.8说明还有不少息肉没检出来需要检查标注质量或提高输入分辨率。4.2 用测试集跑推理并可视化结果python detect.py \ --weights runs/train/exp/weights/best.pt \ --source dataset/images/test \ --img 640 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --save-txt \ --save-conf--conf-thres 0.25是置信度阈值医学场景建议从 0.25 起步不要用默认的 0.25 以上否则小息肉容易被滤掉。--iou-thres 0.45是 NMS 的 IoU 阈值如果同一区域出现多个重叠框可以降到 0.4。--save-txt会把检测结果写成 YOLO 格式方便后续做定量统计。跑完后重点看两类图漏检的真实标签有但预测没有和误检的预测有但真实标签没有。漏检多就查标注是否漏标误检多就查背景里有没有类似息肉的纹理。4.3 量化前的精度基线别急着上 RK3568很多人一上来就想把模型量化到 RK3568 上跑结果精度掉得没法看。正确顺序是先在 GPU 上把 FP32 的 mAP 跑到满意再导出 ONNX再做 INT8 量化每步都记录精度。如果 FP32 的 mAP 只有 0.7量化后掉到 0.5 是正常的问题不在量化在模型本身就没训好。我一般要求 FP32 的 mAP0.5 至少 0.85量化后不低于 0.80才认为这套方案有部署价值。5. 避坑与排查直肠息肉检测里最容易翻车的五件事5.1 现象训练 loss 正常但 mAP 始终为 0原因标签类别号或names配置不匹配。YOLOv5 在计算 mAP 时会按类别匹配如果标签里写的是0但names里只有一个polyp理论上没问题但如果标签里出现了1而nc是 1这类标签会被忽略导致部分图像没有有效标签。解决用脚本统计所有标签文件里的类别号确认最大值小于nc。5.2 现象验证集 mAP 很高测试集一跑就崩原因数据划分时没有按患者或视频来源分层。同一患者的肠镜帧之间高度相似如果随机划分验证集里可能有和训练集同一患者的图像指标虚高。解决按患者 ID 或视频 ID 划分确保同一来源的图像只出现在一个集合里。这个坑在医学图像里非常普遍血泪经验。5.3 现象推理时小息肉全部漏检原因输入分辨率不够或conf-thres太高。640 输入下5mm 息肉可能只有 10 个像素YOLOv5 的 P3 特征图下采样 8 倍后只剩 1 个像素很难激活。解决把--img提到 1024或者用--conf-thres 0.1先看召回再逐步调高。如果硬件不允许提高分辨率考虑用切片推理把大图切成小块分别检测。5.4 现象量化后模型输出全乱原因RK3568 的 INT8 量化对激活值范围敏感而 YOLOv5 的 SiLU 激活函数在量化时容易溢出。解决导出 ONNX 时把 SiLU 换成 ReLU或者用量化感知训练QAT代替训练后量化PTQ。PTQ 快但精度损失大QAT 慢但可控。如果只是做演示PTQ 加 500 张校准图通常能接受如果要上临床QAT 是必须的。5.5 现象树莓派 4B 上推理只有 2FPS原因树莓派 4B 的 CPU 跑 YOLOv5s 本身就很吃力没有 NPU 加速。解决换 yolov5n输入降到 320用 ONNX Runtime 的 ARM 优化版本或者外接 Google Coral USB 加速棒。如果这些都不行说明硬件选型错了不是模型的问题。部署前先确认目标硬件的算力别等训完模型才发现跑不动。6. 从 PyTorch 到 RK3568量化部署的实操细节6.1 导出 ONNX 与 RKNN 模型转换先在 PC 上导出 ONNXpython export.py \ --weights runs/train/exp/weights/best.pt \ --include onnx \ --img 640 \ --batch 1 \ --opset 12--opset 12是 RKNN 工具链比较稳定的版本不要用太新的 opset。--batch 1是因为边缘设备通常单帧推理。导出后用onnxsim简化一下去掉多余的算子。然后在 RK3568 的 SDK 里用rknn-toolkit2转换from rknn.api import RKNN rknn RKNN() rknn.config( mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3568, quantized_dtypeasymmetric_quantized-8 ) rknn.load_onnx(modelbest.onnx) rknn.build(do_quantizationTrue, datasetcalib_list.txt) rknn.export_rknn(best.rknn)mean_values和std_values要和训练时的归一化一致YOLOv5 默认是 0-1 归一化所以这里用 0 和 255。calib_list.txt里放 200-500 张训练集图像路径校准集要覆盖不同光照和息肉形态否则量化误差会集中在某些场景。6.2 量化精度验证与回退策略转换完成后在 RK3568 上跑一遍测试集和 PC 上的 FP32 结果对比。如果 mAP 掉超过 5 个点先检查校准集是否代表性不足再检查quantized_dtype是否用了asymmetric_quantized-8。如果还是不行回退到混合量化对敏感层保持 FP16。RKNN 支持hybrid_quantization虽然速度会慢一点但精度能拉回来。6.3 一个具体技巧用切片推理提升小息肉召回如果最终部署的输入分辨率受限比如 RK3568 上只能跑 640但小息肉漏检严重可以在推理前把图像切成 2×2 的四块每块缩放到 640 分别检测再合并结果。代价是推理时间变成 4 倍但小目标召回能提升 10-15 个点。这个技巧在工业缺陷检测里很常见直肠息肉同样适用。合并时注意 NMS 的 IoU 阈值要调低到 0.3避免切片边界的重复框。我自己的习惯是每次训完模型先不急着导出而是把测试集里漏检的图单独挑出来看一遍确认是标注问题还是模型问题。这个动作花不了十分钟但能省下后面几天的瞎调参。希望帮到你。本文还有配套的精品资源点击获取