直肠息肉病变检测数据集VOC+YOLO格式解析与YOLO训练实战
2026/9/8 22:35:21 网站建设 项目流程

简介:直肠息肉病变检测数据集包含10725张内镜图像,并提供Pascal VOC与YOLO两种格式的标注文件,覆盖息肉、出血、气泡、食管炎、器械和误检6个临床常见类别的目标框,总标注框数达20580个。数据已按标准目录整理,可直接用于目标检测模型训练、验证与微调,适合医学影像AI、内镜辅助诊断等方向的研究者与算法工程师。压缩包共2000个文件,以xml标注文件与txt格式标签为主,内含对应jpg图片,整体大小440.12MB,使用labelImg工具完成标注;各类别框数从2801到4608不等,有利于深入分析多类别均衡性及困难样本挖掘。目前已有320人学习。该数据集类别设置贴近真实内镜场景,正负样本分布清晰,可用于消化道病变检测实验、模型效果对比、迁移学习及论文复现,能帮助使用者节省数据采集与清洗时间,快速搭建起自己的检测流程与评估体系。

1. 这个数据集到底是什么,为什么值得关注

拿到“直肠息肉病变检测数据集VOC+YOLO格式10725张6类别.7z”这个压缩包,第一反应是:这不是普通的目标检测demo数据,而是一份面向消化道内镜影像的医疗AI基础资产。它包含了10725张真实内镜图像,标注了6个与直肠息肉病变相关的类别,同时提供VOC和YOLO两种目标检测标注格式,整体打包为7z压缩文件。

先说清楚它解决什么问题。做医疗影像目标检测,最卡脖子的往往不是模型结构,而是数据。公开可用的息肉检测数据集数量少、类别单一、标注格式各异,很多团队为了一份干净数据要花几周做清洗和格式转换。这份数据集把“分类—标注—格式”一次补齐:10725张图解决了“量”的问题,6个类别覆盖了常见病变类型,VOC和YOLO双格式则省去了最枯燥的标注转换环节。适合动手搞检测模型的学生、刚入场医疗AI的工程师、以及需要快速验证算法的研究组。

再说6个类别。标题没有展开说明具体哪6类,但结合临床常见分类推测,大概率覆盖了增生性息肉、腺瘤性息肉(可能细分为管状腺瘤、绒毛状腺瘤等)、锯齿状病变、炎症性息肉以及腺癌等典型类型。注意,这只是背景知识的合理推测,解压后第一时间打开classes.txt或data.yaml,以里面的实际标注为准。医疗数据最忌讳先入为主,类别名称对不上会让你后面整个训练流程白跑。

关于规模,10725张在医疗影像AI领域属于什么水平?横向对比一下:很多公开的医学检测数据集集中在几千张的量级,上万张且带6类精细标注的并不多。这个体量足够训练一个可以跑通验证流程的YOLO模型,作为预训练基础或学术论文实验也够用。但要清楚一点,医疗场景的规模,重点从来不是“绝对数量”,而是“病变多样性”和“标注一致性”。同一类息肉在不同内镜设备、不同光照条件、不同医生操作习惯下,视觉差异非常大。所以拿到数据后先别急着训练,花时间做统计分析才是正经事。

2. 数据集结构和格式深度拆解

2.1 目录结构与文件组织

7z压缩包解压后,目录通常是这类结构:

rectal_polyp_dataset/ ├── images/ │ ├── train/ │ │ ├── 000001.jpg │ │ ├── 000002.jpg │ │ └── ... │ ├── val/ │ └── test/ ├── annotations/ │ ├── voc/ │ │ ├── 000001.xml │ │ ├── 000002.xml │ │ └── ... │ └── yolo/ │ ├── 000001.txt │ ├── 000002.txt │ └── ... ├── classes.txt └── data.yaml

当然,实际命名可能有差异,有的数据会把VOC的xml和YOLO的txt分开放,也有的把images和annotations混在一起。拿到手先跑一条tree命令把结构梳理清楚,别急着写代码。

这里有个容易踩的坑:YOLO格式的训练通常要求“图像和同名txt标注文件放在同一个目录,或者通过data.yaml里的路径字段分别指定”。如果你发现images目录下面没有对应的txt文件,那就需要自己在yaml配置里分别指向images和labels两个根目录,ultralytics支持这种写法:

path: /path/to/rectal_polyp_dataset train: images/train val: images/val nc: 6 names: ['class0', 'class1', 'class2', 'class3', 'class4', 'class5']

names列表的顺序非常关键。YOLO格式的txt文件里每一行开头的数字是类别索引,这个索引直接对应names数组的位置。如果数据集自带的classes.txt顺序和你写的names不一致,那整个训练就是白忙。

2.2 VOC标注格式解析

PASCAL VOC格式是目标检测领域最经典的标注格式之一,核心是一个XML文件对应一张图片。里面记录了图像路径、尺寸、通道数,以及每一个目标的类别名称和边界框坐标:

<annotation> <folder>images</folder> <filename>000001.jpg</filename> <size> <width>1920</width> <height>1080</height> <depth>3</depth> </size> <object> <name>adenomatous_polyp</name> <bndbox> <xmin>320</xmin> <ymin>240</ymin> <xmax>780</xmax> <ymax>690</ymax> </bndbox> </object> </annotation>

VOC的坐标是绝对值,单位是像素,不依赖图像尺寸。好处是对人类阅读极其友好,用标注工具打开就能直接对应;坏处是训练前往往要转换成相对坐标或归一化坐标。而且XML文件携带了path、folder等无关信息,不同标注工具的细节差异很大,实际解析时不能假设字段一定存在。

用Python读取VOC标注非常容易,我习惯用xml.etree.ElementTree,不需要额外依赖:

import xml.etree.ElementTree as ET def parse_voc(xml_path): tree = ET.parse(xml_path) root = tree.getroot() size = root.find('size') img_w = int(size.find('width').text) img_h = int(size.find('height').text) objects = [] for obj in root.iter('object'): name = obj.find('name').text 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) objects.append({ 'name': name, 'bbox': [xmin, ymin, xmax, ymax] }) return img_w, img_h, objects

2.3 YOLO标注格式解析

YOLO格式是目前yolo系列训练框架的标准输入格式。每一张图片对应一个同名txt文件,每行代表一个目标,格式为:

class_id x_center y_center width height

注意,这5个数全部是归一化后的相对值,范围通常在0到1之间。x_center和y_center是边界框中心点的相对坐标,width和height是框的宽高除以图像宽高。归一化的目的是让标注与图像分辨率解耦,训练时无论模型喂入640x640还是1280x1280,坐标系都保持一致。

把VOC转YOLO就是小学四则运算:

x_center = (xmin + xmax) / 2 / img_w y_center = (ymin + ymax) / 2 / img_h w = (xmax - xmin) / img_w h = (ymax - ymin) / img_h

反过来,把YOLO转VOC也不难:

xmin = (x_center - w / 2) * img_w ymin = (y_center - h / 2) * img_h xmax = (x_center + w / 2) * img_w ymax = (y_center + h / 2) * img_h

这里有个很隐蔽的坑:YOLO格式要求类别索引是0到nc-1的整数。如果classes.txt里第一行是“adenomatous_polyp”,那它的索引就是0。假如你沿用VOC里的字符串名称去匹配,而不先做编码映射,解读出来的每一行类别都是错的。

3. 数据集的准备与预处理实战

3.1 解压与目录规划

7z格式压缩率高,但跨平台解压稍微有点讲究。

Linux环境先确保装了p7zip:

sudo apt update && sudo apt install -y p7zip-full 7z x "直肠息肉病变检测数据集VOC+YOLO格式10725张6类别.7z"

Windows下直接用7-Zip或Bandizip,右键解压,基本没坑。解压之后我强烈建议先做两件事:第一,用脚本统计每个类别的目标数量,看看是否存在极端不均衡;第二,随机抽样20个图,把标注框画上去人工确认,检查VOC和YOLO两套标注是否对同一张图描述一致。

这两步看似简单,但能筛掉80%以上后续训练阶段的低级问题。花了半小时做数据体检,比后面训练三天发现metric崩了再回头查数据要划算得多。

3.2 标注文件读取与检查脚本

我习惯把数据检查写成一个小脚本,每次拿到新数据集先跑一遍。核心是确认三件事:图片能正常打开、尺寸和标注尺寸匹配、边界框没有越界。

import os from PIL import Image def check_yolo_labels(img_dir, label_dir): issues = [] for img_name in os.listdir(img_dir): if not img_name.endswith('.jpg'): continue stem = os.path.splitext(img_name)[0] img_path = os.path.join(img_dir, img_name) label_path = os.path.join(label_dir, stem + '.txt') with Image.open(img_path) as im: w, h = im.size if not os.path.exists(label_path): issues.append((img_name, 'missing label')) continue with open(label_path, 'r') as f: lines = f.read().strip().splitlines() for line in lines: parts = line.split() cls_id = int(parts[0]) xc, yc, bw, bh = map(float, parts[1:]) xmin = (xc - bw / 2) * w ymin = (yc - bh / 2) * h xmax = (xc + bw / 2) * w ymax = (yc + bh / 2) * h if xmin < 0 or ymin < 0 or xmax > w or ymax > h: issues.append((img_name, 'box out of range', line)) return issues

越界是很常见的问题,通常出现在标注对象紧贴图像边缘时,也有一部分是格式转换过程中浮点精度丢失造成的。越界框在训练中会干扰anchor匹配,导致检测头收敛异常,必须处理掉或裁剪进图像范围内。

3.3 数据集划分与增强策略

如果压缩包里面没有划分train/val/test,那就要自己做。常规划分是7:2:1,随机打乱后切分。但医疗数据场景里有个额外的注意点:如果同一病人有连续多张内镜图像,直接随机划分容易造成数据泄露,训练和验证集里出现相似度极高的画面,验证指标虚高。这个数据集发布方如果已经做了序列去重,那就直接用;如果没有,你只能根据文件名前缀和图片内容先粗略聚类再划分。

划分脚本可以这样写:

import os, random, shutil random.seed(42) img_dir = 'images/all' train_dir = 'images/train' val_dir = 'images/val' os.makedirs(train_dir, exist_ok=True) os.makedirs(val_dir, exist_ok=True) imgs = [f for f in os.listdir(img_dir) if f.endswith('.jpg')] random.shuffle(imgs) n = len(imgs) train_imgs = imgs[:int(n * 0.7)] val_imgs = imgs[int(n * 0.7):int(n * 0.9)] for f in train_imgs: shutil.move(os.path.join(img_dir, f), os.path.join(train_dir, f)) for f in val_imgs: shutil.move(os.path.join(img_dir, f), os.path.join(val_dir, f))

数据增强方面,内镜图像有其特殊性。常规的随机翻转、平移、缩放、颜色抖动都可以用,但要注意不要做过于剧烈的几何扰动,因为息肉在真实内镜画面中的尺度、旋转角度都有生理约束,旋转超过30度基本脱离实际。推荐的增强组合是:水平翻转概率0.5、轻微缩放(0.8到1.2倍)、HSV色域微调(饱和度±20%)、轻微噪声。

4. 基于YOLOv8的训练与评估

4.1 环境与配置文件

这个数据集既然直接提供YOLO格式,最方便的路线就是用它跑ultralytics的YOLOv8或YOLO11。

pip install ultralytics

然后准备一个data.yaml。注意,路径最好填绝对路径,训练时相对路径容易因为工作目录不对而报错找不到图片:

path: /data/rectal_polyp_dataset train: images/train val: images/val test: images/test nc: 6 names: ['hyperplastic_polyp', 'tubular_adenoma', 'villous_adenoma', 'sessile_serrated_lesion', 'inflammatory_polyp', 'adenocarcinoma']

names的顺序一定和classes.txt保持一致。这也是为什么我前面反复强调先打开classes.txt看一眼,越早确认越省事。

4.2 训练策略与关键参数

训练命令一句话能启动:

yolo detect train data=data.yaml model=yolov8n.pt epochs=150 imgsz=640 batch=16 patience=30

但参数值得再抠一抠。医疗检测里,病变区域往往在图像中占比很小,属于典型的小目标问题。如果有条件,imgsz提高到960甚至1280,对小息肉检出有明显帮助。代价是显存占用大增,AMD RX 580这种8GB级别显卡跑640输入都吃力,更别说960了,老老实实用yolov8n配合batch=8。

学习率方面,用默认值0.01起步问题不大。如果出现loss震荡或nan,优先把lr降到0.001,再检查标签是否有异常值。预训练权重选择yolov8n.pt还是yolov8s.pt,取决于你的算力和对精度的要求。n最快但精度一般,s在医疗数据上通常能比n高出2到3个点的mAP,代价是训练时间大约翻倍。

类别不平衡是这个数据集需要留心的核心问题。如果统计发现前两个类别占了80%的目标,模型很容易偏向高频类别。对策有三个:一是使用带权重的损失函数;二是对低频类别做过采样;三是在评估时多关注per-class AP,而不是只看整体mAP。ultralytics默认输出每个类别的AP,这是最直接的观察入口。

4.3 评估指标与部署建议

训练完成后,官方命令直接出指标:

yolo detect val model=runs/detect/train/weights/best.pt data=data.yaml

重点看mAP50和mAP50-95。医疗检测场景中,mAP50-95比单一阈值下的mAP50更有参考价值,因为它要求模型在不同IoU阈值下都有稳定输出,更能反映框的定位精度。如果mAP50尚可但mAP50-95偏低,说明框的定位不够准,常见原因是标注框本身边界模糊、训练时在坐标回归上欠拟合。这种情况下可以尝试多训练一些epoch,或者检查数据增强是否过于剧烈。

推理部署就相当简单了:

yolo detect predict model=best.pt source=test.jpg conf=0.25 iou=0.5

医疗场景的置信度阈值要谨慎设置。偏低的conf(比如0.1)会输出很多低置信度框,漏检少但误检多;偏高的conf(比如0.5)则相反。实际使用中建议在验证集上画conf-threshold曲线,找一个precision和recall平衡的点。

5. 实际踩坑记录与避坑清单

5.1 常见问题速查表

跑数据集训练时,最容易撞上的问题我整理成一张表:

现象可能原因解决办法
训练时loss直接nan学习率过大、标签出现越界或nan降低lr至0.001,检查txt标注内容
一个epoch训练极慢图像分辨率过大、batch过大降低imgsz,减小batch,开启半精度
验证集某类AP为0该类别样本过少或标注错误检查该类的样本数量和质量,考虑过采样
框的位置偏得离谱类别id与names顺序错位核对classes.txt与data.yaml的names顺序
CUDA out of memorybatch或imgsz超显存减小batch,或使用梯度累积策略
训练集loss很低,验证集很差过拟合增加数据增强,使用patience早停

关于显存,还提一嘴AMD显卡。YOLOv8的官方实现主要面向NVIDIA生态,RX 580跑起来默认用CPU或需额外配置DirectML分支,别指望开箱即用。

5.2 关于医疗数据集的几点提醒

使用这份数据集,有几件技术之外但非常重要的事必须说清楚。

第一,医疗数据涉及患者隐私和伦理合规。数据集发布方如果明确开源可用,那在授权范围内做科研和学术验证没有问题;但如果发布信息模糊,先找发布文档确认授权条款,不要默认可以商用。数据训练出的模型只应作为辅助研究工具,不能直接作为临床诊断依据,更不能替代医生判断。

第二,类别定义以标注文档为准,不要套用自己经验里的病理分类。不同团队对这6类的定义粒度可能不同,标注标准不同会直接影响模型的边界学习。

第三,内镜图像具有明显的数据域特征,不同厂商设备、不同分辨率、不同光照条件都可能造成domain gap。用这份数据集训练的模型,换到另一批内镜图片上性能大概率会显著下降。这并不代表训练有问题,而是医疗影像的常见现象。缓解办法是后续用新场景数据做fine-tune,或者使用域适应技术。

最后再分享一个偏实践的小技巧:拿到压缩包后不要修改原始标注文件的字段顺序,不管是VOC的XML还是YOLO的txt,都原样保留。很多转换脚本对格式是敏感的,一个不起眼的空格差异可能让解析器读错字段,而且这种错非常难查。做个备份目录,原始数据永远不动,所有预处理都写脚本生成新目录,这样无论后面哪里出了问题,都能快速定位是不是转换过程引入的bug。

我在实际整理这类数据时还有一个习惯:把每个类别的样本数、平均目标数量、平均框面积占比先统计出来画个图贴到项目文档里。这个看似简单的动作,在写论文和向团队汇报数据质量时能省大量口舌,也能帮自己快速发现数据分布异常。做医疗AI,数据整理和模型训练至少是五五开的时间投入,别觉得画框、检查、统计是杂活,这恰恰是整个项目最有价值的地基。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询