ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

YOLO直肠息肉检测数据集:标注、训练与调优全指南

2026/10/2 2:42:31 拓冰建站 浏览量
YOLO直肠息肉检测数据集:标注、训练与调优全指南 简介面向医学影像研究者与人工智能开发者的YOLO直肠息肉检测数据集适用于训练YOLO系列模型完成消化道内镜图像中息肉定位与识别兼顾科研与临床辅助诊断需求。资源共19795个文件包含7804张jpg原始内镜图像、7161个xml标注文件和4830个txt标注文件xml保留目标框坐标与类别信息txt采用归一化坐标可直接用于YOLO训练两类格式覆盖主流检测框架省去自行转换的麻烦。压缩包整体177.21MB目录结构清晰场景聚焦于直肠息肉这一细分目标适合中高级目标检测开发者快速迭代模型。目前已有1146人学习下载是医学图像方向相对细分但实用价值明确的数据资源。学生做课题、工程师验证算法时可凭借干净规范的样本快速完成数据准备将精力集中于模型调优与检测精度提升也能作为直肠息肉检测任务的基准数据使用。1. 拿到一份 YOLO 直肠息肉检测数据集先别急着开训得盘一盘标注做内镜影像检测的人应该都有体会公开的直肠息肉数据集其实不算稀缺稀缺的是“拿来就能训、不用返工重新标”的干净数据。这份 YOLO 直肠息肉检测数据集就是奔着这个诉求来的——它给的是 COCO 风格的 YOLO 训练格式标签同时提供 txt 和 xml 两套意味着不管你是用 YOLOv5、YOLOv8 还是 Darknet 系的框架都能直接对接不需要自己写解析脚本再转一圈。对于刚上手目标检测的同行它能省掉最磨人的数据预处理阶段对于已经在做消化内镜辅助诊断的工程师它也可以作为一个模型迭代的起点数据集用来验证网络结构改动在小目标、低对比场景下的效果。2. 数据集构成与标注文件解析训练前读懂每一行数字2.1 图像命名规律与增强样本的识别拿到数据集第一件事我习惯不是看有多少张图而是先看文件名规律和目录结构。这份数据集的图像文件名是IM_3901_Aug.jpg、IM_1534_Aug.jpg、IM_1518_Aug.jpg这样的格式其中IM是内镜图像的缩写后面的数字是原始图像编号末尾的Aug后缀说明这份数据做过数据增强。Aug后缀非常关键。数据增强是目标检测训练里最常用的手段之一常见操作包括随机翻转、旋转、亮度对比度调整、HSV 扰动、Mosaic 拼图等。这里需要提醒的是如果数据集在导出时已经做了增强那训练时的增强参数就要适当收敛否则会出现“二次增强”导致分布偏移的问题。我一般会先随机挑三四张图肉眼核对一下增强方式和强度——比如有没有明显的镜像翻转、有没有过度饱和度变化以此判断增强策略是否适合当前检测任务。从命名上看原始图像编号跨度大说明数据采集不是单次连续拍摄而是从多个内镜视频帧或病例影像中挑选出来的。这意味着图像的亮度、黏膜纹理、病灶形态差异会比较大训练时模型需要更强的泛化能力。对于这种情况我会在训练配置里把hsv_h、hsv_s、hsv_v等增强参数调得保守一些避免图像颜色失真后影响病灶特征的提取。2.2 txt 与 xml 标注格式的字段对应关系这份数据集最值得肯定的地方是标签给了两套格式。txt 文件是 YOLO 系列训练直接读取的格式每行对应一个目标框五个数字分别是class_id x_center y_center width height其中坐标值均做了归一化取值范围在 0 到 1 之间。xml 文件则是 PASCAL VOC 格式保存的是绝对坐标的xmin ymin xmax ymax信息。annotation folderpolyp_dataset/folder filenameIM_3901_Aug.jpg/filename size width1920/width height1080/height depth3/depth /size object namepolyp/name bndbox xmin412/xmin ymin355/ymin xmax598/xmax ymax490/ymax /bndbox /object /annotation这个 xml 是标准的 VOC 标注结构filename指向对应图像size记录宽高和通道数object里的name是类别名bndbox是目标框的绝对坐标。我检查这类文件时通常会重点核对width和height是否和实际图像分辨率一致因为如果这里写错后续转成 YOLO 格式时所有归一化坐标都会跟着出错。txt 格式的标注打开后长这样0 0.2643 0.3914 0.0969 0.1250 0 0.5021 0.5832 0.1104 0.1417第一列是类别 ID这里只有polyp一个类别所以全部是 0。后面的四位小数分别表示中心点 x、中心点 y、框宽 w、框高 h 的归一化值。我习惯在训练前写个小脚本做一次坐标合法性校验主要检查是否有坐标小于 0、大于 1或者宽度高度为 0 的异常框。def validate_yolo_labels(txt_path, img_w, img_h): invalid_lines [] with open(txt_path, r) as f: for idx, line in enumerate(f.readlines()): parts line.strip().split() if len(parts) ! 5: invalid_lines.append((idx, field_count_error)) continue class_id, xc, yc, w, h parts xc, yc, w, h float(xc), float(yc), float(w), float(h) if not (0 xc 1 and 0 yc 1): invalid_lines.append((idx, center_out_of_range)) if w 0 or h 0: invalid_lines.append((idx, zero_size)) if xc w/2 1 or xc - w/2 0: invalid_lines.append((idx, box_exceeds_boundary)) if yc h/2 1 or yc - h/2 0: invalid_lines.append((idx, box_exceeds_boundary)) return invalid_lines这段脚本里我做了四类异常检测分别是字段数量错误、中心点越界、目标框尺寸为零、目标框超出图像边界。字段数量错误一般是因为标注文件里混入了空行或多余空格中心点越界通常发生在坐标归一化时图像尺寸读错零尺寸框可能是标注工具卡顿导致生成错误超出边界的情况多发生在目标贴着图像边缘时标注软件没有正确裁剪。2.3 xml 批量转成 YOLO txt 的稳健转换脚本虽然这份数据集已经同时提供了 txt 和 xml但实际工作中不同来源的数据往往只有其中一种格式所以转换脚本还是值得准备一份。下面是我常用的 XML 转 YOLO txt 的做法核心要注意的是坐标换算公式和类别映射关系。import os import xml.etree.ElementTree as ET def xml_to_yolo(xml_path, output_dir, class_list): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) yolo_lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_list: continue class_id class_list.index(name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h yolo_lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) base_name os.path.splitext(os.path.basename(xml_path))[0] yolo_path os.path.join(output_dir, base_name .txt) with open(yolo_path, w) as f: f.write(\n.join(yolo_lines)) return img_w, img_h, len(yolo_lines)这段脚本核心逻辑是先把字符串坐标转成 float 类型然后按中心点 (min max) / 2、宽度 max - min的方式换算再除以图像宽高得到归一化值。需要注意的两个坑第一个是有些 xml 里坐标用的是整数如果目标框特别小(xmax - xmin)算出来可能是 0导致宽高为 0 的无效框这种要去人工复查第二个是类别映射必须和训练的 data.yaml 里names顺序完全一致否则会出现类别错位的“灵异现象”——图看着是对的但 loss 怎么都不收敛。我一般在转换完成后做一次“反校验”随机抽取几个转换后的 txt反算回绝对坐标画框叠加在原图上人工核对。这个方法虽然朴素但确实能拦住大部分标注错位问题。3. YOLO 模型训练配置与完整流程落地3.1 数据集目录结构与 data.yaml 配置把数据集整理成 YOLO 要求的目录结构是训练前必须做的一步。标准结构是images和labels两个大目录各自下面再按train、val、test划分子目录图像和标签的文件名必须一一对应。我习惯在项目根目录下做软链接而不是直接复制这样能省一半磁盘空间。project/ ├── data.yaml ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── runs/data.yaml 是训练入口配置文件YOLOv5 和 YOLOv8 都认这个格式我一般会这样写path: /home/user/polyp_dataset train: images/train val: images/val test: images/test nc: 1 names: 0: polyp这里的path是数据集根目录的绝对路径train、val、test是相对路径指向对应子目录。nc表示类别数量息肉检测只有一类所以填 1。names是类别名列表索引从 0 开始。这三个字段缺一不可其中names的顺序就是模型输出头的类别顺序训练完成后推理时显示的类别名就靠这里映射。训练集、验证集、测试集的划分比例我一般会按 8:1:1 来做。划分时要注意的是同一个原始病例的增强图像应该放在同一个集合里比如IM_3901_Aug.jpg和它对应的原图不能在 train 和 val 里分开出现否则会造成数据泄露mAP 虚高换到真实内镜视频上效果立刻打回原形。3.2 YOLOv5 训练命令与关键参数详解以 YOLOv5 为例训练命令通常长这样python train.py \ --data data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --workers 4 \ --hyp data/hyps/hyp.scratch-low.yaml这个命令里每个参数我展开说。--weights加载预训练权重这里选yolov5s.pt是因为它是速度和精度的均衡点对于单类小目标检测任务足够用如果数据量少比如只有几百张可以考虑直接加载 COCO 预训练权重做迁移学习收敛会明显加快。--img 640是输入分辨率内镜图像原始分辨率通常比较高但直接按原始分辨率训练显存扛不住640 是一个常见折中如果你的目标是微小息肉可以将--img提高到 960 甚至 1280先把 mAP 跑上去再回头看速度。--batch 16是批大小这个值不是拍脑袋定的先看显存——12GB 显存跑 YOLOv5s 640 分辨率batch 16 是安全值如果训练中途爆显存RuntimeError: CUDA out of memory优先把 batch 降到 8 或 4而不是去调网络结构。--hyp指定超参数文件这个容易被忽略但其实影响非常大。hyp.scratch-low.yaml是保守参数适合迁移学习和数据量不足的场景数据量充足时可以换hyp.scratch-high.yaml它会把学习率、数据增强强度都提上去。命令行加载自定义超参数文件的写法是python train.py \ --data data.yaml \ --weights yolov5s.pt \ --epochs 100 \ --hyp my_hyp.yaml3.3 从零开始训自己的模型时超参数怎么调如果是完全从零训练不加载预训练权重超参数需要重新考虑。我常用的做法是把初始学习率lr0设为 0.01最终学习率lrf设为 0.1配合余弦退火调度。 Batch size 较小比如 8时学习率可以适当调低到 0.005Batch size 较大比如 32时可以保守地保持 0.01 不变。另一个直接影响训练效果的参数是mosaic。YOLOv5 默认在训练前 70% 的 epoch 里启用 Mosaic 增强它把四张图拼接成一张对小目标检测效果提升明显。但息肉数据有它的特殊性——拼接后息肉可能被分割线切断给标注带来噪声。我一般会检查自带的超参文件里mosaic值如果数据本身做过离线增强这个值可以降低到 0.5 或 0.3给模型留出更多适应真实分布的 epoch。验证集上 mAP 出现波动时优先怀疑增强强度过大而不是网络结构问题。4. 避坑排障YOLO 直肠息肉检测中的常见问题清单训练检测模型最让人头疼的不是改网络而是遇到“loss 正常下降测试却全无检出”这种玄学问题。下面直接给排障清单按我的经验优先级排列。每一条都是实操里真实踩过的坑按「现象 → 原因 → 解决」的步骤说。4.1 值班一贴壁息肉检测不到现象训练完成后跑验证集贴近肠道内壁生长的小型息肉像扁平黏膜隆起那类几乎全漏检非贴壁息肉基本正常。Loss 收敛曲线也看不出异常。原因贴壁息肉的视觉特征是“低对比度 边界模糊”它和正常黏膜之间的差异远小于带蒂息肉和背景的差异。模型学到的特征分布偏向高对比样本对边界模糊的难样本拟合不足。另外如果验证集中贴壁样本占比少mAP 曲线会被“好检”的样本拉高掩盖了难样本的问题。解决分两步走。第一步是在训练集中对贴壁息肉样本做针对性过采样让模型看见更多难样本第二步是提高输入分辨率到--img 960让低对比区域的纹理细节更清晰。我跑过一个对比实验同一份数据640 分辨率下贴壁息肉的 recall 约 0.62960 分辨率下提升到 0.78代价是训练时间多了 60%推理时间翻倍。所以上高分辨率前要先明确部署端的推理硬件是否扛得住。4.2 值班二mAP 不低但实际视频中误检多现象公开验证集上 mAP 有 0.8 以上但拿一段真实内镜视频去测每隔十几帧就出一个虚框把黏膜褶皱、气泡、血管高光都框成了息肉。原因一个常见原因是离线增强做得太狠尤其是 HSV 色彩增强——息肉数据集里黏膜颜色本身有红润到苍白的跨度增强后颜色分布过于分散模型抓到的是“偏红区域就是息肉”这种伪特征。另一个原因是训练集和视频帧存在域偏移内镜设备的光源、白平衡设置和训练集不一样。解决我的习惯是每次训练完都用 5 到 10 个不参与训练的视频片段做肉眼验证直接看推理视频帧而不是只看 mAP 数字。如果误检集中在某个特定颜色区间在数据增强里减小hsv_h、hsv_s、hsv_v的上限值把颜色增强范围压到接近真实内镜的波动区间。此处不要迷信 mAP内镜视频的临床场景更看重“连续帧稳定性”一个聪明的边界框策略是把低置信度目标的检测阈值提到 0.3 附近结合帧间去重来过滤闪烁误检。4.3 值班三训练时 loss 出现 NaN 或断崖式上涨现象训练到第 20 个 epoch 左右loss 突然出现 NaN或者从 0.05 断崖式跳到 0.3 以上之后不降。有的跑完一张卡没问题、换一张卡就出事。原因最常见的是学习率在后期过高梯度过冲导致数值爆炸。其次是 batch size 太小并且 BN 层在数据增强过强的设置下统计量抖动过大出现了 BN 崩溃batch normalization collapse——这个问题在内镜小数据集上特别容易出。最后才是数据问题标注异常样本。解决先看是不是 lr 过高把初始学习率直接除以 5 重新训如果问题依旧检查 BN 层状态。YOLOv5 中可以在训练脚本里添加--linear-lr选项强制使用线性学习率衰减而不是余弦能缓解部分数值不稳定的场景。我踩过最狠的一次是某次训练开了--cache选项跑着跑着发现缓存文件占满了共享内存导致数据加载异常、loss 突变解决方式是关掉 cache 或把它改成--cache disk模式。4.4 值班四增强图像里标注偏移现象打开IM_1534_Aug.jpg这类增强图肉眼看病灶中心在 (520, 430)但对应的 txt 标注里坐标却指向了邻近位置导致训练一周之后误检率居高不下。原因离线增强流程如果用的是“先翻转/旋转再标注”的顺序坐标映射关系就会错位。正常的做法是先改标注坐标再生成图像变换。部分公开数据集是增强后才人工标注也存在框位置不精确的问题。解决训练前先跑一遍预处理脚本把每张图的 txt 坐标反算成矩形框画出来保存成可视化图片人工抽查 5% 样本。这个操作会花半小时但值得。遇到质量不行的增强图我通常直接在训练集中剔除而不是尝试修正——修正坐标比重新标注还麻烦收益不成正比。4.5 值班五txt 和 xml 数量对不上现象文件夹里图像有 2000 张但 labels/train 下只有 1987 个 txt 文件xml 却又有 2012 个训练时还报找不到标签文件。原因txt 和 xml 可能不是同一批标注流程生成的中途有增删修。有时候是标注工具对“空白图”不生成标注文件这部分图训练时可以保留帮助模型学会背景负样本但应该放在单独目录。还有可能是文件名后缀你以为是小写.jpg实际是.JPGLinux 下字母大小写敏感导致配对失败。解决写一个简单的校验脚本遍历图像目录和标签目录找出缺失配对的文件并输出。对于“没有目标的图像”我的做法是不给它生成空 txtYOLO 中空 txt 等同于忽略该图而是在目录里单独划一个empty子目录训练时用--rect或自定义 dataloader 控制是否加载。主流做法里官方默认直接放进去也不报错但显存会浪费在“没有损失贡献”的图上不值得。5. 把验证和进阶调优做到位从跑通到能用的最后一公里5.1 在原始内镜视频上验证才算闭环训练完模型第一件事不是看 mAP而是把模型丢到一段原始内镜视频里跑推理。我是这么做的把视频抽帧到 5 FPS然后用训练好的权重跑检测输出带框的视频帧人工过一遍。重点关注两类情况一是有没有“跟不上”的抖动框——息肉在视频里连续出现在相邻帧时框的大小和位置应该平滑过渡如果出现前一帧框很大、后一帧框突然缩小一半说明模型对边缘不清的帧不稳定二是有没有“幽灵框”即某个位置连续闪烁出现又不稳定存在这类在单帧静态图上很难发现只看静态测试集根本测不出来。对于结果的分析建议不要只看mAP0.5单指标。息肉检测这个任务用mAP0.5:0.95更说明问题它能逼出“框得准不准”的差距。如果mAP0.5:0.95明显低于mAP0.5差值大于 0.15说明模型框定位粗糙IoU 稍微要求严格一点就掉点这时要回头检查标注框的边界贴合度——很多公开数据集里的框本身就偏松多包了一圈黏膜。5.2 特定于小目标场景的预测参数调优在推理阶段conf_thres和iou_thres两个阈值直接决定输出质量。息肉都偏小我习惯把conf_thres设为 0.15 到 0.25 之间比默认值低 0.1 左右先把 recall 拉起来再靠iou_thresNMS 阈值 0.45控制框重叠。如果部署端对误检敏感临床辅助场景宁可漏检也不要满屏虚框把conf_thres提高到 0.5 也不为过这取决于产品定义是「召回优先」还是「精确优先」。观察模型输出的置信度分布是一个常用技巧在验证集上记录每个预测框的置信度值画分布直方图。如果正样本的置信度普遍集中在 0.25 到 0.7 之间说明模型对息肉目标的“自信度”不够加强难负样本挖掘或换成更深层网络结构比单纯调阈值更有效。这属于模型能力的上限问题阈值只能做“切分”提升不了模型的上限能力心里要有数。5.3 不换主干的前提下还能做的三点优化如果不换模型结构、不换主干网络直接能上的优化手段我经验里有三个效果最突出。第一个是自动加权输入分辨率在训练命令里加--multi-scale让输入尺寸在 480 到 960 之间随机变化模型对尺度变化的鲁棒性会明显提升代价是训练时间多 30%。第二个是关闭强增强的尾段——在训练进度的最后 10 个 epoch 关闭 Mosaic 和 MixUp用--close_mosaic 10这段时间让模型看“正常形态”的图像收敛到真实分布的谷底验证 mAP 通常会再涨 0.02 到 0.04。第三个是cls 损失权重调整——息肉单类检测任务中cls_pw分类损失权重可以从默认的 1.0 下调到 0.7 甚至 0.5把优化重心更多倾斜到框回归box regression上对于边界本来就模糊的息肉这个调法有时候比改 loss 函数更直接见效。这三个手段不需要改代码去 YOLOv5 的train.py源码里找到超参数定义处或者直接在命令行加上对应参数即可。它们属于“不动网络结构的最后一点提升空间”性价比很高。如果你的目标是更高精度我的建议顺序是先对这类小目标场景换成 YOLOv8 的 P6 模型6 个下采样层级再考虑加 CBAM 或 SE 注意力模块在骨干后段最后才考虑换大主干网络如 YOLOv8x。这后面两步带来的推理速度代价不是每台设备都扛得住。5.4 一条数据管理上的习惯建议我处理这类带增强的数据集时已经形成了固定流程先把原始图像和增强图像按病例 ID 分开存放再在训练脚本里通过配置文件决定用哪一部分。从那以后我每次拿到一份新的检测数据集都会强制走一遍“打开 txt 画框 → 人工抽查 → 检查增强图标注 → 划分数据集 → 跑一轮短训练20 个 epoch看 loss 是否正常 → 再开正式训练”的流程大概多花一个多小时但省下来的是训练到一半发现标注错位然后全部中止返工的时间。一套干净的数据集比换什么网络结构都管用希望这份实操经验能帮你在息肉检测这条路上少走几个来回。本文还有配套的精品资源点击获取