简介:面向消化道内镜影像目标检测任务的标注数据集,涵盖直肠息肉、血液、气泡、食管炎、手术器械及mis等6个类别,总计10725张JPEG图像、20580个标注框,并同时提供Pascal VOC与YOLO两种标签格式,可直接接入主流目标检测框架训练与评估,尤其适合医学影像AI研究者、算法工程师及学生用于病灶检测和临床辅助诊断研究。资源包为7z格式,共2000个文件,以1999个VOC格式XML标注文件和1个txt使用说明为主,包体约440MB,配合说明文件可快速了解标注规范与目录结构。已有320人学习下载,可作为消化道疾病智能识别与内镜影像分析项目的数据基础。 做医学影像目标检测的同行,应该都有过这种体验:公开可用的医疗数据本来就少,带类别标注的更是稀缺资源。直肠息肉病变检测数据集(VOC+YOLO格式,10725张,6类别)这个压缩包我拿到手第一反应是赶紧解压,然后核对标注质量和目录结构。这套数据规模不算小,又同时给了两种标注格式,无论你习惯用YOLO直接训练,还是想先基于VOC格式做可视化核对,都能省掉一大段格式转换的苦工。这篇文章我从头到尾讲一遍实际操作流程,包括怎么解压、怎么检查标注、怎么组织目录训练YOLOv8、以及医学图像训练里容易踩的坑,给想要拿这套数据跑实验的兄弟一个完整参考。
1. 数据集基本盘盘点:10725张图能干什么
1.1 数据规模与质量评估
10725张图像,放在通用目标检测数据集里不算起眼,但放在医学内镜影像领域,这个量级已经相当能打了。要知道很多科研论文里用的息肉检测数据,撑死一两千张,有些甚至是从视频里抽帧抽出来的模糊图像,标注质量还得打问号。这套数据能做到一万张以上,说明收集方至少经过了多个病例的筛选和整理,不是随便拿个内镜视频一顿切帧就完事。
当然,规模大不等于质量好,拿到手之后有三件事我必须提醒你先做。第一,看类别分布,六类样本是不是均衡,如果有的类别只有几百张,训练的时候就要小心。第二,抽查标注框,看看有没有标注偏移、框过大过小、或者误标漏标的情况。第三,检查图像尺寸和格式,内镜图像的分辨率差异很大,有些可能带黑边,有些可能是不同内镜设备采集的,这会影响后面统一resize的效果。
1.2 六种类别到底怎么分的
这个数据集标了6个类别,虽然单看名字大概率能猜到是不同形态的息肉或者病变类型,但具体是哪六类,最好解压后直接打开类别文件确认。我在实际项目中遇到过一次教训,类别文件里写的是数字ID,当时没仔细核对,直接按猜测的类别顺序去训练,结果推理出来框的位置对,但类别标签全乱了。
医学数据集里6个类别,常见的是按息肉的形态学分型或者病理严重程度去划分,比如无蒂、有蒂、平坦型这种,也可以是增生性、腺瘤性、管状腺瘤之类。不管哪种划分方式,你先花十分钟查看类别文件,再随机抽几张图配合标注可视化看一眼,比后面训练完了才发现问题要省事得多。这一步花不了多少时间,但能帮你避掉最大的坑。
2. VOC和YOLO双格式解析:为什么这种组合吃香
2.1 VOC格式怎么组织
Pascal VOC是最经典的目标检测标注格式之一,目录结构通常是三个文件夹:JPEGImages放原始图片,Annotations放XML标注文件,ImageSets/Main放训练集和验证集的划分文件。XML文件里记录了图片文件名、尺寸、通道数,以及每个目标的类别名称、边界框坐标,坐标格式是左上角和右下角的绝对像素值。
这套数据集把VOC格式放出来,最大的意义在于方便做标注可视化检查。因为XML是纯文本,可以直接解析,配合OpenCV或者PIL在图像上画框,一眼就能看出标注对不对。而且很多老牌的检测框架和可视化工具都支持VOC格式,不需要额外适配。
2.2 YOLO格式怎么组织
YOLO格式的目录结构更精简,一般就是images和labels两个文件夹,每个图片对应一个同名txt文件。txt里每一行代表一个目标,格式为class x_center y_center width height,注意这里的坐标全部是归一化后的值,计算方式是目标中心点的x、y坐标除以图片宽度和高度,框的宽高同样除以图片宽度和高度,因此取值都在0到1之间。
这个归一化设计我当年刚接触的时候还犯过迷糊,拿绝对像素坐标直接训练,结果loss完全不对劲。实际上YOLO这样设计是为了适配不同分辨率的输入图,模型训练时会把图片统一resize到固定尺寸,如果用绝对坐标就全乱了。所以拿到数据集后,随便打开一个txt文件,看到每行五个数字都是小数,说明格式没毛病。
2.3 双格式并存到底方便在哪
很多开源数据集只给一种格式,遇到要用另一种格式的情况就得写脚本自己转,中间一旦坐标转换公式写错,或者类别映射对不上,训练出来的模型就废了。这套数据同时给VOC和YOLO,等于帮你把转换这一步省掉了。
我的做法是:用VOC格式做数据体检,用YOLO格式直接训练。VOC的XML方便读,画框校验、统计类别分布、检查边界框大小这些操作都很顺手;YOLO格式则可以直接喂给YOLOv5、YOLOv8、YOLOv9这些主流框架。如果后续你想转成COCO格式做对比实验,也可以拿XML作为数据源去转换,因为COCO格式里需要的bbox是绝对坐标,从XML转过去逻辑上更直接,不容易出错。
3. 拿到.7z压缩包的第一件事:解压与校验
3.1 不同系统下怎么解压7z
.7z比ZIP压缩率更高,但默认解压工具不一定支持。Windows用户装个7-Zip或者Bandizip,右键直接解压就行;macOS虽然访达能解压部分7z,但遇到加密或者分卷压缩包容易出问题,建议装个The Unarchiver;Linux服务器上用命令行更效率,安装p7zip后执行:
# Debian/Ubuntu sudo apt install p7zip-full # CentOS/RHEL sudo yum install p7zip p7zip-plugins # 解压命令 7z x 直肠息肉病变检测数据集VOC+YOLO格式10725张6类别.7z解压的时候我习惯加个-o参数指定输出目录,避免文件直接散落在当前目录里。如果服务器上没有p7zip,也可以用7zr命令,功能更精简但解压标准7z文件完全够用。
3.2 解压后目录结构长什么样
解压完成后,建议先看一眼整体目录结构。正常情况应该类似这样:
dataset/ ├── VOC/ │ ├── JPEGImages/ │ │ ├── 000001.jpg │ │ ├── 000002.jpg │ │ └── ... │ ├── Annotations/ │ │ ├── 000001.xml │ │ ├── 000002.xml │ │ └── ... │ └── ImageSets/ │ └── Main/ │ ├── train.txt │ ├── val.txt │ └── test.txt(可选) └── YOLO/ ├── images/ │ ├── train/ │ ├── val/ │ └── ... └── labels/ ├── train/ ├── val/ └── ...如果发现图片文件和标注文件数量对不上,别提训练,后面全是坑。我一般会快速跑个脚本核对:
ls VOC/JPEGImages/ | wc -l ls VOC/Annotations/ | wc -l ls YOLO/images/train/ | wc -l ls YOLO/labels/train/ | wc -l四个数字能对上,才继续往下走。如果哪一步对不上,先检查解压是否有报错,再考虑是不是数据集本身有问题。
3.3 画个框检查标注质量
数量对上了,不等于质量没问题。我在拿到任何数据集后都会做一个可视化抽查,这个习惯救过我很多次。核心逻辑很简单,遍历标注文件,在图片上画出目标框,把结果截图保存下来,然后人工翻看。
YOLO格式是归一化坐标,直接读取txt画框的话需要做换算。我自己写过一个Python小脚本,逻辑不算复杂:读取图片尺寸,然后把归一化坐标乘以宽高转成像素坐标,最后用OpenCV的rectangle函数画框。
import cv2 import os img_dir = 'YOLO/images/' label_dir = 'YOLO/labels/' save_dir = 'check/' os.makedirs(save_dir, exist_ok=True) for filename in os.listdir(img_dir): # 如果label不存在就跳过 label_path = os.path.join(label_dir, filename.replace('.jpg', '.txt')) if not os.path.exists(label_path): continue img = cv2.imread(os.path.join(img_dir, filename)) h, w = img.shape[:2] with open(label_path, 'r') as f: for line in f: parts = line.strip().split() class_id, x_c, y_c, bw, bh = parts x_c, y_c, bw, bh = map(float, (x_c, y_c, bw, bh)) x1 = int((x_c - bw / 2) * w) y1 = int((y_c - bh / 2) * h) x2 = int((x_c + bw / 2) * w) y2 = int((y_c + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, class_id, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) cv2.imwrite(os.path.join(save_dir, filename), img) # 控制下检查数量,先抽50张看看 if len(os.listdir(save_dir)) >= 50: break这个脚本的核心经验是:先随机抽50到100张看一遍再决定要不要全面跑。如果抽查的图片里框的位置都正常,类别ID和实际目标能对上,那就可以放心训练了。但如果你看出有框明显偏移、框住的是背景不是目标、同一张图里多个目标只标了一个,那就要考虑是先用这个数据做预实验,还是想办法清洗一遍,别头铁直接拿去训练。
4. 我用YOLOv8训练这套数据的完整流程
4.1 数据集目录组装
虽然数据集已经给了YOLO格式,但YOLOv8训练前还需要你把images和labels按train和val分开组织。部分数据集的YOLO目录可能只分了train和val,但图片路径里写在了同一层,这时候需要手动整理一下。
建议的最终目录结构是这样:
dataset/ ├── images/ │ ├── train/ │ ├── val/ ├── labels/ │ ├── train/ │ ├── val/整理的时候可以写一个脚本,按照已有的train.txt和val.txt里的文件名去做归类,把图片和对应的txt拷贝到对应文件夹,比手动拖着移动稳妥得多。
4.2 编写data.yaml
YOLOv8训练需要一份data.yaml配置文件,内容主要包括三部分:训练集和验证集的图片路径、类别数量、类别名称列表。注意类别名称的顺序一定要和标注文件里的数字ID对应上,不然模型训练和推理会张冠李戴。
举个例子:
# dataset.yaml path: /home/user/直肠息肉数据集 train: images/train val: images/val nc: 6 names: 0: 'adenoma' 1: 'hyperplastic' 2: 'sessile' 3: 'pedunculated' 4: 'flat' 5: 'other'这里面类别名称举个格式例子,实际训练时以你数据集里的真实类别为准。强烈建议先从类别文件里查清楚每个数字ID对应的具体类别名,再填到yaml里。YOLOv8在读数据时会用它来生成类别映射,如果这里填错,后面一切白搭。
4.3 启动训练与参数设置
训练命令我用的是YOLOv8标准写法,核心参数区别在于imgsz和batch这两个。直肠息肉在内镜图像里通常属于小目标,占整图比例很小,所以imgsz不建议设得太小。我实测下来640的效果比416好了不少,如果你显存够用,甚至可以试试960。
yolo train model=yolov8m.pt data=dataset.yaml epochs=100 imgsz=640 batch=16 device=0模型选择上,我用的是yolov8m,因为医学图像数据量相对小,模型太大容易过拟合,模型太小又难以拟合细粒度特征。yolov8m算是一个比较均衡的选择。如果你机器显存充裕,比如3080或者V100这样的卡,可以直接yolov8l起步,精度会上一个台阶。如果只是自己笔记本上的GTX 1660这种,yolov8s也够用,可以后续再加数据。
训练过程中我比较在意的两个东西:一个是train/box_loss和train/cls_loss曲线,另一个是验证集上的mAP50变化。loss曲线如果稳步下降,mAP50逐步提升,说明训练正常;如果loss下降但mAP50卡着不动,大概率是数据问题或者超参数不对。
4.4 训练后怎么评估和验证
训练结束后,runs/detect/train/weights/best.pt就是效果最好的权重。在验证集上跑一下自带的评估命令,把每个类别的精确率、召回率、mAP50和mAP50-95都打印出来。
yolo detect val model=runs/detect/train/weights/best.pt data=dataset.yaml重点关注每个类别的单独汇报,而不是只看整体的mAP。我见过一个数据集整体mAP不错,但某个小类别几乎没检测出来,因为样本量太少,贡献被其他大类稀释了。如果发现这种情况,需要针对性地做数据增强,或者用类别权重调整损失函数。另外,最好自己写个推理脚本,挑几张验证集图片实际跑一遍,保存检测结果图片,直观看一下模型对内镜图像里的息肉定位和分类到底怎么样,比单看指标更踏实。
5. 医学检测数据集训练的几个坑,句句都是真实经验
5.1 类别不平衡问题
医学数据集的类别不平衡几乎是标配。这个六类数据集,大概率有的类别样本多,有的类别样本少,甚至可能少数类只有几百张。如果直接硬着头皮训练,大的类别会把loss主导掉,小的类别基本学不好。
我实测下来的处理方式是:第一次训练先不做过多干预,用原始类别分布硬跑一遍,看看baseline怎么个水平,哪几个类别掉队;第二次再针对性处理。处理方法有三种,第一种是给少数类加过采样,把这类样本在训练集里重复放几遍;第二种是loss里加类别权重,让模型对少数类更敏感;第三种是做一些针对性的数据增强,比如翻转、小角度旋转、颜色扰动这些,让少数类的样本量在效果上扩起来。三种方法里最简单有效的是第二种,改动很少,效果立竿见影。
5.2 内镜图像的特殊性
直肠内镜图像和自然图像差别挺大,最明显的就是高光反射和色彩分布。内镜光源打在湿润的肠道内壁上,会产生强反光区域,如果把这个高光区域误当成息肉区域,模型就会学歪。另外,不同内镜设备之间的色差很大,同一台设备在不同照明条件下,息肉和正常黏膜的颜色对比也会变化。
所以做数据增强的时候,别只套用Imagenet时代的默认增强策略。颜色增强是必须的,但别加得太猛,色调偏移过大反而会让模型学到错误的色彩关联。随机仿射变换、缩放扰动是相对安全的选择。CUDA版本的随机擦除或者Cutout对内镜图像效果也不错,因为能模拟目标被遮挡的情况。
5.3 数据泄露与划分不合理的隐患
这个坑最容易被人忽略,但后果最严重。内镜图像数据集往往是同一患者的很多帧画面,如果做数据集划分时只按文件随机切分,同一个人的图像很可能同时出现在训练集和验证集里。这样的话验证集看起来mAP很高,但一到真实新患者的检测上就露馅,泛化能力差得离谱。
最合理的做法是按患者ID来划分数据集。同一个患者的图全放进训练集或者全放进验证集,绝不允许既在训练集又在验证集。不过这套数据集文件名如果不带患者ID信息,就没法直接按患者划分,那也要尽量保证切分时是按视频片段或内镜序列分段切,而不是逐张乱切。如果数据来源本身就比较单一,比如只来自几个医院的内镜中心,那做外部验证时更要谨慎。
5.4 显存不足和训练速度问题
这个数据集一万多张图,训练YOLOv8并不算小任务。如果显卡只有8G显存,又用了640以上的输入尺寸,batch要适当调小。AMD的RX 580能不能跑YOLOv8这个问题我被人问过很多次,结论是能跑但很勉强,最麻烦的是PyTorch的ROCm支持在RX 580上效果一般,折腾环境的时间比重建模型还久。如果你手头只有显卡但显存紧张,建议用yolov8n或者yolov8s,把batch降到8甚至4,先用小配置验证整个流程跑通再说。
6. 常见问题速查表
有些小问题我在不同数据集上都遇到过,直接整理成速查表供大家参考。
| 问题 | 常见原因 | 解决方案 |
|---|---|---|
训练时报错No labels found in ... | 训练集目录下label文件缺失,或者txt文件为空 | 检查labels/train和images/train的文件名是否一一对应,删除空txt |
| 类别ID和名称对不上 | data.yaml里的顺序和训练时类名顺序不匹配 | 打开类别文件,逐个核对数字ID和类别名的映射关系 |
| 验证集mAP很高但在新图上效果差 | 数据划分不合理,同一患者图同时存在于训练和验证集 | 按患者或内镜序列维度重新划分数据,保证无跨集重叠 |
| 训练loss下降但mAP不涨 | 类别不平衡严重,或者部分类样本过少 | 加类别权重或在少数类上做针对性增强 |
| 小尺寸息肉检测不到 | imgsz太小,或者模型上下采样太深丢细节 | 增大imgsz到640或以上,换用带小目标检测头的模型版本 |
| 内镜高光区域被误检成息肉 | 数据增强不足,模型把高光特征跟目标特征混淆 | 增加色彩扰动的增强,甚至可以加光照模拟的数据增强 |
| 7z解压文件损坏 | 下载不完全,或者压缩包本身分卷缺失 | 校验文件哈希值,重新下载完整包 |
这个数据集的另一个扩展方向,是很多人会问能不能跟KITTI之类的自动驾驶数据集一起用。其实没必要硬融,内镜图像和车载摄像头拍摄的场景差距太大,域迁移问题严重,强行混合训练反而会对两边都有副作用。更适合的路径是先用这套数据训一个baseline,然后用自收集的真实内镜图像做增量训练,效果会比混用多个数据集好得多。
最后谈一点个人看法
医学图像目标检测这几年被关注度越来越高,尤其在辅助诊断和早癌筛查场景下价值很直接。但这套数据集的真实效果,取决于你对数据质量的把控和对特殊问题的处理能力。我拿到数据集的习惯是:先花一两个小时做可视化检查,别急着训练;训练第一遍只求跑通流程记录baseline;第二遍开始针对问题做优化。这么一套流程走下来,哪怕数据本身有瑕疵,你的实验结果也会比盲目直接训要靠谱得多。
本文还有配套的精品资源,点击获取