简介:这份资源面向医学影像分析与目标检测方向的开发者、研究生及算法工程师,提供真实CT场景下的人脑肿瘤检测数据集,可用于肿瘤检测项目训练,也可作为通用人脑检测数据的补充。数据集共5000张高质量图片,采用labelimg标注,同时提供VOC(xml)、COCO(json)、YOLO(txt)三种主流格式标签,可直接接入YOLO等检测算法。资源包为1个PDF文件,大小约2.26MB,因原始数据体量较大,PDF内附数据集基本情况介绍与百度网盘获取方式。随附YOLO11一键训练脚本,覆盖GPU、CPU及Mac(M芯片)三平台方案,并给出博主训练结果日志供参考,便于快速复现与调参。目前已有401人学习,适合希望低成本获取医学影像标注数据、快速验证检测模型的中高级读者。
1. 人脑肿瘤检测数据集:5000 张 CT 图配齐 VOC/COCO/YOLO 三格式,值不值得下
做医学影像目标检测的同行大概都有过这种体验:模型结构调了半天,loss 曲线也好看,一到自己标注的数据上就翻车——不是框歪了,就是漏检,回头一查,标注规范不统一、格式转换丢坐标。所以当我看到这份「人脑肿瘤检测数据集」时,第一反应不是看它有多少张图,而是看它的标注链路是否干净。这份资源给的是 5000 张真实 CT 场景图片,用 labelimg 标注,同时提供 VOC(xml)、COCO(json)、YOLO(txt) 三种格式标签,还附了数据集划分脚本和 YOLO11 一键训练脚本,覆盖 GPU、CPU、Mac(M 芯片) 三平台。它解决的核心问题很明确:让你跳过「找数据—标注—转格式—写训练脚本」这条最耗时的前置链路,直接把精力放在模型和调参上。适合做医学影像检测的算法工程师、赶毕设的学生,以及想拿真实 CT 数据验证 YOLO 系列改进效果的人。下面我按「这份资源是什么—怎么跑起来—坑在哪」的顺序拆一遍。
2. 三种标签格式的差异与选型:为什么同一批图要存三份
拿到数据集先别急着训练,得搞清楚 VOC、COCO、YOLO 三种格式到底差在哪,否则后面转换和评估环节会莫名其妙报错。这三种格式本质上是同一批标注框的三种「方言」,坐标表达和文件组织方式不同,选错了轻则训练脚本读不进去,重则框位置整体偏移。
2.1 坐标表达:绝对像素 vs 归一化
VOC 的 xml 里,bndbox存的是xmin/ymin/xmax/ymax四个绝对像素值,原点在左上角。COCO 的 json 里,bbox存的是[x, y, width, height],同样是绝对像素,但注意它是左上角坐标加宽高,不是右下角。YOLO 的 txt 则是归一化的class x_center y_center width height,全部除以图片宽高,取值 0~1。
这个差异直接决定了你换格式时要不要重算。常见做法是:训练 YOLO 系列用 txt,做 COCO 评估(比如 pycocotools 算 mAP)用 json,而很多老的可视化脚本和标注工具只认 xml。这份资源三种都给,省去了自己写转换脚本的麻烦,但你要清楚每种格式对应哪个环节。
| 格式 | 坐标类型 | 单文件组织 | 典型用途 |
|---|---|---|---|
| VOC | 绝对像素 xmin/ymin/xmax/ymax | 每图一个 xml | labelimg 原生、可视化脚本 |
| COCO | 绝对像素 x/y/w/h | 全量一个 json | pycocotools 评估、多任务 |
| YOLO | 归一化中心点+宽高 | 每图一个 txt | YOLO 系列训练 |
2.2 类别映射:别让 class id 对不上
VOC 的 xml 里类别是字符串名字,COCO 的 json 里categories是 id 加 name 的映射,YOLO 的 txt 里直接是数字 class id。三者之间最容易出问题的就是类别顺序。比如你训练时data.yaml里写的names: ['tumor'],但转换出来的 txt 里肿瘤被标成了 1,背景被当成 0,模型就会学歪。
我一般会先跑一段脚本把三种格式的类别统计出来对齐,确认没有错位再开训。这份资源标注质量高,但你自己接手的项目里,类别映射这一步永远要手动核一遍,这是血泪经验。
2.3 划分脚本:train/val/test 不能随手切
数据集划分脚本是这份资源里容易被忽略但很关键的一环。医学影像数据如果按随机切分,可能出现同一病人的切片同时出现在训练集和验证集里,导致验证指标虚高。常见做法是按病人 ID 或扫描批次做分组划分,保证验证集和训练集不共享同一来源。
资源里附带的划分脚本,我建议你先看它是不是按文件名前缀分组。如果是纯随机,自己改成按前缀分组更稳妥。划分比例一般 7:2:1 或 8:1:1,小数据集可以 8:2,但 test 集最好留出来,别拿验证集当测试集用。
import os import random from collections import defaultdict # 按文件名前缀分组,避免同一来源切片跨集 def split_dataset(img_dir, out_txt, ratios=(0.7, 0.2, 0.1)): groups = defaultdict(list) for f in os.listdir(img_dir): if f.lower().endswith(('.jpg', '.png', '.jpeg')): # 假设文件名前缀是病人/批次标识,按实际规则调整 prefix = f.split('_')[0] groups[prefix].append(f) keys = list(groups.keys()) random.shuffle(keys) n = len(keys) n_train = int(n * ratios[0]) n_val = int(n * ratios[1]) train_keys = keys[:n_train] val_keys = keys[n_train:n_train + n_val] test_keys = keys[n_train + n_val:] with open(out_txt, 'w') as fw: for k in train_keys: for img in groups[k]: fw.write(f"train/{img}\n") for k in val_keys: for img in groups[k]: fw.write(f"val/{img}\n") for k in test_keys: for img in groups[k]: fw.write(f"test/{img}\n") split_dataset('./images', './split.txt')这段脚本的逻辑是:先按前缀把图片分组,再对组做随机打乱和切分,最后把每个组内的图片整体分配到 train/val/test。参数ratios控制三集比例,prefix的切法要根据你实际文件名规则改。跑完检查一下split.txt里三集数量是否符合预期,别出现某一集为空的情况。
3. YOLO11 一键训练脚本落地:三平台参数怎么设
资源附的是 YOLO11 一键训练脚本,支持 GPU、CPU、Mac(M 芯片) 三平台。这一章把脚本拆开讲清楚每个参数的含义,以及不同平台下该怎么改,避免你直接python train.py一把梭然后卡在环境或显存上。
3.1 环境准备与依赖安装
YOLO11 一般走 ultralytics 这个库。GPU 平台先确认 CUDA 和 PyTorch 版本匹配,Mac 平台走 MPS 后端,CPU 平台就是纯 torch CPU 版。常见做法是建独立虚拟环境,别在 base 环境里装,否则版本冲突排查起来很痛苦。
# 创建虚拟环境 python -m venv yolo11_env source yolo11_env/bin/activate # Windows 用 yolo11_env\Scripts\activate # 安装 PyTorch,按平台选 # GPU (CUDA 12.1 示例) pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 # Mac M 芯片 pip install torch torchvision # CPU pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 安装 ultralytics pip install ultralytics安装完跑一句python -c "import torch; print(torch.cuda.is_available())"验证 GPU 是否可用。Mac 平台看torch.backends.mps.is_available()。这一步没过,后面训练全是白搭。
3.2 data.yaml 配置:路径和类别名
YOLO 训练靠data.yaml告诉它数据在哪、有几类。这份资源三种格式都有,训练时用 YOLO 格式的 txt 标签,data.yaml里指向对应的 images 和 labels 目录。
# data.yaml path: ./brain_tumor_dataset # 数据集根目录 train: images/train # 训练集图片相对路径 val: images/val test: images/test nc: 1 # 类别数,按实际标注调整 names: ['tumor'] # 类别名,顺序必须和 txt 里的 class id 一致nc和names是最容易出错的地方。如果你拿到的 txt 里 class id 有 0 和 1 两个值,但nc写了 1,训练会直接报索引越界。先统计一遍所有 txt 里的最大 class id,再决定nc。
3.3 训练命令与关键参数
一键脚本的核心就是一行 ultralytics 的 train 调用,但参数怎么设决定了你能不能跑完、跑得好。
from ultralytics import YOLO # 加载预训练权重,没有就写 yolo11n.yaml 从零训 model = YOLO('yolo11n.pt') results = model.train( data='data.yaml', epochs=100, # 医学数据一般 100~300,看收敛情况 imgsz=640, # CT 图分辨率高可试 1024,但显存吃紧 batch=16, # GPU 显存小就降到 8 或 4 device=0, # GPU 填 0,CPU 填 'cpu',Mac 填 'mps' workers=4, # 数据加载线程,Windows 下建议 0 避免卡死 patience=20, # 20 轮无提升就早停 project='runs/train', name='brain_tumor' )参数说明:epochs是训练轮数,医学影像数据量不大时容易过拟合,配合patience早停更稳。imgsz是输入尺寸,CT 图细节多,640 可能丢小肿瘤,显存够就上 1024。batch和device是平台差异最大的两个,GPU 显存 8G 以下建议 batch 8,Mac M 芯片走mps但速度比 GPU 慢不少,CPU 训练只适合小规模验证。workers在 Windows 上设 0 能避免多进程数据加载卡死,这是踩过的坑。
3.4 训练日志怎么看
资源里附了博主的训练结果日志,参考价值在于看 loss 曲线和 mAP 走势是否正常。重点看三个指标:box_loss是否稳定下降、mAP50是否在涨、cls_loss有没有震荡。如果 box_loss 降但 mAP 不涨,多半是标注框和类别有问题;如果 loss 直接 NaN,检查学习率或数据里有没有空标签文件。
4. 从 VOC/COCO 转 YOLO:转换脚本与坐标校验
虽然资源三种格式都给了,但实际项目里你经常需要自己转——比如拿到一批只有 xml 的补充数据,或者要把 COCO 的 json 拆成 YOLO 的 txt。这一章给一套可复用的转换脚本,并讲清楚转换后怎么校验,避免框整体偏移这种玄学问题。
4.1 VOC xml 转 YOLO txt
VOC 转 YOLO 的核心是把绝对像素的 xmin/ymin/xmax/ymax 转成归一化的中心点和宽高。注意 xml 里图片宽高要从<size>节点读,不能想当然用固定值。
import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_dir, out_dir, classes): os.makedirs(out_dir, exist_ok=True) for xml_file in os.listdir(xml_dir): if not xml_file.endswith('.xml'): continue tree = ET.parse(os.path.join(xml_dir, xml_file)) root = tree.getroot() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) lines = [] for obj in root.iter('object'): cls = obj.find('name').text if cls not in classes: continue cls_id = classes.index(cls) bbox = obj.find('bndbox') xmin = float(bbox.find('xmin').text) ymin = float(bbox.find('ymin').text) xmax = float(bbox.find('xmax').text) ymax = float(bbox.find('ymax').text) # 归一化中心点和宽高 x_center = (xmin + xmax) / 2.0 / w y_center = (ymin + ymax) / 2.0 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}") out_path = os.path.join(out_dir, xml_file.replace('.xml', '.txt')) with open(out_path, 'w') as f: f.write('\n'.join(lines)) voc_to_yolo('./annotations', './labels', ['tumor'])逻辑说明:遍历 xml,读图片宽高,对每个 object 算归一化坐标。classes列表的顺序决定 class id,必须和data.yaml里的names一致。坐标保留 6 位小数足够,YOLO 读取时会自己解析。转换完一定要抽查几张,用可视化脚本把框画回原图上看是否对齐。
4.2 COCO json 转 YOLO txt
COCO 的 json 是单文件全量标注,转换时要先建 image_id 到文件名的映射,再按 image_id 分组写 txt。
import json import os def coco_to_yolo(json_path, out_dir, classes): os.makedirs(out_dir, exist_ok=True) with open(json_path, 'r') as f: data = json.load(f) # image_id -> (file_name, width, height) img_info = {img['id']: img for img in data['images']} # 按 image_id 收集标注 anns = {} for ann in data['annotations']: anns.setdefault(ann['image_id'], []).append(ann) for img_id, img in img_info.items(): w, h = img['width'], img['height'] lines = [] for ann in anns.get(img_id, []): cls_id = ann['category_id'] - 1 # COCO 类别从 1 开始,YOLO 从 0 x, y, bw, bh = ann['bbox'] x_center = (x + bw / 2) / w y_center = (y + bh / 2) / h lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {bw/w:.6f} {bh/h:.6f}") name = os.path.splitext(img['file_name'])[0] + '.txt' with open(os.path.join(out_dir, name), 'w') as f: f.write('\n'.join(lines)) coco_to_yolo('./annotations.json', './labels', ['tumor'])关键点在category_id - 1:COCO 的类别 id 通常从 1 开始,YOLO 从 0 开始,不减这一下类别全错位。另外 COCO 的 bbox 是左上角加宽高,算中心点要加半个宽高,别直接拿 x 当中心。
4.3 转换后的校验方法
转换脚本跑完不代表万事大吉。我一般做两步校验:一是统计每个 txt 的框数量和对应 xml/json 是否一致,二是随机抽 10 张用可视化脚本画框。框偏移最常见的原因是图片宽高读错,比如 xml 里 size 写的是缩放后尺寸,但实际图片是原图,这种只能靠可视化发现。
5. 避坑与排查:训练不收敛、显存爆、Mac 报错的真实记录
这一章集中写我在跑这类医学检测数据集时踩过的坑,每条按现象、原因、解决来,你对照自己的报错看。
5.1 训练 loss 不降,mAP 一直是 0
现象:训练跑起来了,box_loss 在动但 mAP50 始终为 0,验证集预测全是背景。原因:最常见的是data.yaml里names顺序和 txt 里 class id 对不上,或者 txt 文件路径没被正确索引到,模型读到的全是空标签。解决:先跑一遍统计脚本,确认每个 txt 非空且 class id 在nc范围内;再检查data.yaml的train路径是相对path还是绝对路径,ultralytics 对路径拼接比较敏感,建议直接写绝对路径试一次。
5.2 GPU 显存爆,batch 降到 1 还 OOM
现象:CUDA out of memory,把 batch 降到 1 依然报错。原因:多半是imgsz设太大,或者workers开太多导致数据加载占用显存,也可能是没加载预训练权重从零训,梯度占用更高。解决:先把imgsz从 1024 降到 640,workers设 2 或 0,确认model = YOLO('yolo11n.pt')用的是预训练权重而不是 yaml。还不行就换更小的模型变体,n 换 s 再换 m,别硬上大模型。
5.3 Mac M 芯片跑 mps 报错或速度极慢
现象:device='mps'报算子不支持,或者能跑但一个 epoch 要几十分钟。原因:MPS 后端对部分算子的支持还不完整,YOLO11 某些层会回退到 CPU,速度骤降。解决:先升级 torch 到较新版本,MPS 支持在持续完善;如果还报错,把device改成'cpu'跑小规模验证,正式训练换 GPU 机器。Mac 适合调试流程,不适合大规模训练,这是硬件边界,别跟它较劲。
5.4 验证集指标虚高,测试集一塌糊涂
现象:val 的 mAP 很高,换 test 集掉一大截。原因:划分时同一病人的切片跨了 train 和 val,模型见过相似图像。解决:回到第 2 章的划分脚本,按病人或批次前缀分组切分,保证 val/test 和 train 不共享来源。医学影像里这个坑特别隐蔽,因为切片之间肉眼看着不一样,但模型能学到泄漏特征。
5.5 标注框有负坐标或超出图片范围
现象:转换后的 txt 里出现负数或大于 1 的坐标,训练时报 assert 错误。原因:原始 xml 里标注框画到了图片边界外,或者图片宽高读的是缩放尺寸。解决:转换脚本里加一层 clamp,把坐标限制在 0~1,同时打印出被裁剪的框数量,数量多说明标注或尺寸读取有问题,要回头查源数据。
6. 进阶技巧:用混淆矩阵和 PR 曲线定位漏检,把 mAP 再抬一档
训练跑通只是起点,真正决定这份数据集能不能用在项目里的,是你能不能从评估结果里定位问题。YOLO11 训练完会在runs/train/下生成混淆矩阵和 PR 曲线,这两个图比 mAP 一个数字信息量大得多。
先看混淆矩阵。医学肿瘤检测通常只有一类,矩阵是 2x2(背景 + 肿瘤)。如果背景被大量预测成肿瘤,说明假阳性高,可能是标注里把正常组织也框进去了,或者模型对纹理敏感;如果肿瘤被预测成背景,就是漏检,常见于小目标,得考虑提高imgsz或加数据增强。我一般会把混淆矩阵和验证集的预测可视化对照看,找出具体是哪几张图在错。
再看 PR 曲线。曲线下的面积就是 mAP,但曲线形状告诉你更多:如果曲线在高召回区急剧下降,说明模型为了多召回牺牲了大量精度,这时候调低置信度阈值没用,得从数据或模型容量入手;如果曲线整体偏低但平缓,可能是类别定义模糊,标注一致性不够。
一个具体技巧是:把验证集里置信度在 0.25~0.5 之间的预测单独导出,人工看一遍。这批「模棱两可」的框往往暴露了标注边界问题——比如肿瘤边缘到底框到哪,不同标注员标准不一致。把这些问题框修正后重训,mAP 通常能涨几个点,比调参来得实在。
from ultralytics import YOLO model = YOLO('runs/train/brain_tumor/weights/best.pt') # 导出验证集预测,conf 设低一点捞回模糊框 results = model.predict( source='./images/val', conf=0.25, save_txt=True, save_conf=True, project='runs/predict', name='val_check' )这段预测脚本把验证集每张图的预测框和置信度存成 txt,conf=0.25是故意放低阈值,把模型不确定的框也捞出来。跑完对照原图看那些低置信框,判断是标注漏了还是模型误报。这个习惯我从做第一个检测项目保持到现在,每次训完新数据都强制走一遍,比盯着 mAP 数字干着急有用得多。
医学影像检测和通用目标检测最大的区别在于容错率低,一个漏检可能意味着实际场景里的误判。所以别只追求 mAP 好看,把混淆矩阵、PR 曲线和低置信预测三样结合起来看,才能知道模型到底学到了什么。这份数据集标注质量不错,三种格式也省了转换的麻烦,但最终效果还是取决于你怎么用它。希望帮到你。
本文还有配套的精品资源,点击获取