尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

人脑肿瘤检测数据集:VOC/COCO/YOLO三格式与YOLO11跨平台训练全解析

人脑肿瘤检测数据集:VOC/COCO/YOLO三格式与YOLO11跨平台训练全解析 简介这是一份人脑肿瘤检测数据集的配套说明与获取资料面向医学图像处理、目标检测方向的开发者和研究者可用于CT图片场景下的人脑肿瘤检测项目也可作为通用人脑检测场景数据的补充。资料包共1个文件为PDF格式大小仅2.59MB内含数据集基本情况、标注示例及完整获取方式。对应数据集包含1000张真实CT高质量人脑图片采用LabelImg人工标注标签质量较高并同时提供VOC(xml)、COCO(json)、YOLO(txt)三种标准格式省去自行转换的麻烦可直接代入YOLO等算法训练流程。说明中还介绍了配套的YOLO11一键训练脚本支持GPU(GPUs)、CPU、Mac(M芯片)三平台运行并附有博主训练结果日志方便在实际训练前评估效果和设置预期。目前已有377人学习下载对于准备开展人脑目标检测实验的读者有直接参考价值。1. 人脑肿瘤检测的三个标签格式意味着什么拿到一个目标检测数据集第一步往往不是急着训练而是先弄清楚标签是怎么组织的。这个标题把三件事写得很清楚检测对象是人脑肿瘤医学影像数据量 1000 张同时提供 VOC / COCO / YOLO 三种格式标签外加一套跨 GPU / CPU / Mac 平台的 YOLO11 训练脚本。真正有经验的人看到这一行关注点不会停留在「数据集能不能用」而是会立刻想到三个现实问题三份标签是否来自同一次标注、划分后的训练集验证集在三种格式下是否严格对齐、以及脚本在 MPS 和 CUDA 两种后端下的默认参数是否合理。1000 张医学影像属于典型的小样本检测场景。对于 YOLO11 这类依赖大量自然图像预训练的模型直接从头训练并不现实通常做法是以预训练权重为起点做迁移学习再根据肿瘤区域尺寸分布调整输入分辨率和锚框策略。三种标签格式同时提供意味着做模型对比实验时可以省去格式转换这一步——用 COCO 的 JSON 跑 RT-DETR 或 DETR 类模型用 YOLO 的 txt 跑 YOLO 系列用 VOC 的 XML 跑老牌检测框架互不干扰。这篇文章就顺着「数据结构 → 校验 → 划分 → 训练脚本 → 多平台验证」这条线把这个标题对应的完整落地路径讲透。2. 人脑肿瘤检测数据集的目录结构与三格式标签的对应关系2.1 VOC / COCO / YOLO 三种标注格式在肿瘤影像上的组织差异先看这三种格式的核心差异。VOC 格式的标注单位为单个 XML 文件图像文件名与 XML 文件名一一对应坐标使用像素绝对值的 xmin、ymin、xmax、ymax 形式。COCO 格式则将所有标注汇总到一个 JSON 文件里按 images、annotations、categories 三个数组组织坐标采用像素绝对值的 x、y、width、height且每个标注都有一个全局唯一的 id。YOLO 格式最简洁每张图对应一个同名 txt 文件每行代表一个目标格式为 class_id x_center y_center width height坐标归一化到 01 区间。对医学影像场景来说一个容易被忽略的点是坐标精度。VOC 和 COCO 的整数像素坐标在肿瘤边界不清晰、标注人员打框存在主观偏差时反而保留了粗糙度YOLO 的浮点归一化坐标则能够表达亚像素信息但在 resize 时如果数据集脚本写了取整操作精度反而会丢失。我一般拿到数据集后第一件事就是随机抽几张图把三种格式对应的框都画出来叠加对比确认它们可视化结果一致再进入训练流程。三种格式在类别表示上也不同。VOC 的 XML 里类名是字符串nametumor/nameCOCO 的 JSON 里有独立的 categories 列表维护 id 到类名的映射YOLO 的 txt 里只写整数 class_id。分类 id 的顺序在 YOLO 格式里至关重要如果数据集的 YOLO 标签是用脚本从 COCO 转换来的转换时字典遍历顺序稍有不同class_id 就可能错位而这种问题不会在读取时报错只会让训练出来的模型学到一个完全错误的映射。这也是我拿到多格式数据集后坚持先做交叉校验的根本原因。2.2 1000 张肿瘤影像的三套标签如何保证文件级对齐多格式数据集最怕的不是格式本身复杂而是三套标签文件在文件名匹配上出现缝隙。典型的目录结构一般是这样的brain-tumor-dataset/ ├── images/ │ ├── patient001_frame001.jpg │ ├── patient001_frame002.jpg │ └── ... ├── VOC/ │ ├── JPEGImages/ │ │ ├── patient001_frame001.jpg │ │ └── ... │ └── Annotations/ │ ├── patient001_frame001.xml │ └── ... ├── COCO/ │ ├── images/ │ └── annotations/ │ └── instances_train.json └── YOLO/ ├── images/ └── labels/ ├── patient001_frame001.txt └── ...注意这里有一个隐藏陷阱VOC 的 JPEGImages 目录里必须是有图像的因为 XML 只存标注信息不存图像路径。有些所谓多格式数据集VOC 目录下只放了 XML图像全部集中在 images 根目录这虽然不影响最终使用但如果你用 torchvision 的 VOCDetection 接口直接读就会因为 JPEGImages 里找不到文件而报错。拿到数据集后我一般会先核对文件名集合images 目录的 jpg 列表、VOC 的 XML 列表、COCO 的 images 数组、YOLO 的 txt 列表全局 diff 一遍确认四个集合完全一致再开始做别的。2.3 写一个标签一致性校验脚本别让格式问题带进训练基于上面的考虑我每次拿到多格式数据集都会先跑一个校验脚本比对同一张图像在三种格式下的目标数量和框坐标是否一致。这里不需要引入额外依赖库只用 Python 标准库加 OpenCV 就能完成。核心逻辑是分别解析三种格式把结果统一到一个中间结构里再比较import xml.etree.ElementTree as ET import json import os VOC_ANN_DIR VOC/Annotations COCO_JSON COCO/annotations/instances_train.json YOLO_LABEL_DIR YOLO/labels IMG_DIR images def parse_voc(xml_path): 返回该图的 bbox 列表每项为 [xmin, ymin, xmax, ymax] tree ET.parse(xml_path) root tree.getroot() boxes [] for obj in root.findall(object): bndbox obj.find(bndbox) boxes.append([ int(float(bndbox.find(xmin).text)), int(float(bndbox.find(ymin).text)), int(float(bndbox.find(xmax).text)), int(float(bndbox.find(ymax).text)), ]) return boxes def parse_coco(coco_path, image_id): 从 COCO JSON 中取出指定 image_id 的所有 bbox with open(coco_path, r, encodingutf-8) as f: coco json.load(f) boxes [] for ann in coco[annotations]: if ann[image_id] image_id: x, y, w, h ann[bbox] boxes.append([x, y, x w, y h]) return boxes def parse_yolo(txt_path, img_w, img_h): 从 YOLO txt 还原像素坐标 bbox boxes [] with open(txt_path, r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue _, cx, cy, bw, bh parts cx, cy, bw, bh float(cx), float(cy), float(bw), float(bh) boxes.append([ (cx - bw / 2) * img_w, (cy - bh / 2) * img_h, (cx bw / 2) * img_w, (cy bh / 2) * img_h, ]) return boxes这段代码的可取之处在于它把三种格式统一到了同一个坐标系下。VOC 和 COCO 解析出的都是像素绝对值YOLO 则需要图像的宽高做反归一化。比较时需要注意一个细节COCO 的 bbox 是 [x, y, width, height]要转换成 [xmin, ymin, xmax, ymax] 才能和 XML 直接对比。同时由于不同工具在标注时可能存浮点或整数比较操作不要用精确相等给一个 2 像素以内的容差才是合理的。提示如果发现某张图在 YOLO 格式下的目标数和 VOC/COCO 不一致优先级最高。比如 YOLO txt 里少了一行通常发生在格式转换脚本过滤掉了面积过小的目标时这种丢失在训练时不会报错但会直接影响召回率。3. YOLO11 训练前的数据划分与 YOLO 格式准备3.1 以 VOC 的 ImageSets/Main 为唯一划分事实源三种格式都提供时最忌讳的是在三种格式里各自划一遍训练集、验证集最后得到三份划分结果不同的清单。正确做法是确定一个「唯一事实源」用它导出所有格式的划分。VOC 格式自带 ImageSets/Main 目录其中 train.txt、val.txt、test.txt 正好承担这个角色。如果数据集作者在 VOC 目录里放了这三个文件就直接以它们为准。# 查看 VOC 划分文件中是否包含 test 集 cat VOC/ImageSets/Main/train.txt | head -5 cat VOC/ImageSets/Main/val.txt | wc -l cat VOC/ImageSets/Main/test.txt | wc -l我一般会先确认三个集合加起来是否等于 1000。常见的划分比例是 8:1:1 或 7:2:1医学影像小样本场景更推荐 8:1:1因为验证集的作用是反映训练效果而非最终精度占总量的 10% 已经足够在 1000 张图的前提下每多留一张给训练集对模型泛化都是实打实的帮助。3.2 用划分脚本同步生成 YOLO 格式的 train.txt / val.txt / test.txtYOLO11 的 dataset.yaml 中 train、val、test 字段支持两种写法一种是直接指向包含图像的目录另一种是指向 txt 文件txt 的每行是一个图像文件的绝对路径。多格式数据集场景下用 txt 文件管理划分是最干净的方案因为图像路径本身就是唯一的划分标识。生成脚本如下import os SPLIT_DIR VOC/ImageSets/Main IMG_ROOT os.path.abspath(images) YOLO_SPLIT_DIR YOLO/splits os.makedirs(YOLO_SPLIT_DIR, exist_okTrue) for split in [train, val, test]: txt_path os.path.join(SPLIT_DIR, f{split}.txt) if not os.path.exists(txt_path): continue with open(txt_path, r, encodingutf-8) as f: names [line.strip() for line in f if line.strip()] out_lines [] for name in names: img_path os.path.join(IMG_ROOT, f{name}.jpg) if not os.path.exists(img_path): img_path os.path.join(IMG_ROOT, f{name}.png) out_lines.append(os.path.abspath(img_path)) out_path os.path.join(YOLO_SPLIT_DIR, f{split}.txt) with open(out_path, w, encodingutf-8) as f: f.write(\n.join(out_lines) \n) print(f{split}: {len(out_lines)} images - {out_path})这段脚本的重点在于把 VOC 里不带扩展名的文件名映射为实际图像路径并统一转为绝对路径。这一步在 Windows 环境下尤其重要因为如果后续训练脚本的工作目录变化相对路径会全部失效。另外有些数据集的图像可能混合了 jpg 和 png 两种格式上面代码用 os.path.exists 做了兜底判断把 jpg 找不到的情况自动切到 png。3.3 生成 YOLO11 可直接读取的 dataset.yaml数据划分完成后YOLO11 还需要一个 YAML 文件描述数据集的类别和划分文件位置。这里可以直接复用 3.2 生成的三个 txt# brain_tumor.yaml path: /absolute/path/to/brain-tumor-dataset train: YOLO/splits/train.txt val: YOLO/splits/val.txt test: YOLO/splits/test.txt nc: 1 names: 0: tumorYAML 里的 path 字段会被用来解析相对路径我这里 train 用的是绝对路径 txt 文件所以 path 字段是否准确影响不大但保留它可以让整个配置更完整。names 是类别名按 0 起始的索引排列因为人脑肿瘤数据集只有一个类别所以这里只需要一个名字。如果你的数据集是多个类别直接在 names 下依次列出即可顺序要与 YOLO labels 目录下 txt 文件里的 class_id 完全一致。3.4 模型选型yolo11n 还是 yolo11sYOLO11 提供 n、s、m、l、x 五个规格从模型参数量和推理速度两个维度递进。1000 张医学影像对应的小样本场景下我一般首选 yolo11n 作为基线。原因很简单数据量有限时大模型更容易过拟合n 版本参数量少、正则化效果天然更好而且能以较快速度完成单轮实验方便快速验证标签质量和数据划分是否合理。如果基线 mAP50 能达到可接受水平再换 s 或者 m 做对比实验看模型容量增大带来的收益是否值得额外的训练时间。4. 三平台 YOLO11 一键训练脚本的写法与参数取舍4.1 设备自动检测与默认参数的平台差异化标题中「GPU / CPU / Mac 三平台」对应的其实是三种不同的训练后端CUDA GPU、纯 CPU、Apple Silicon 的 MPS。写一键训练脚本时最基础的工作是自动检测当前机器可用设备而不是让用户手动指定。Ultralytics 的 YOLO11 底层依赖 PyTorch所以可以通过 torch 的 API 完成检测import torch def detect_device(): if torch.cuda.is_available(): return 0, cuda elif torch.backends.mps.is_available(): return mps, mps else: return cpu, cpu这里选择把 CUDA 设备固定为0适用于单卡训练。如果你的机器有多块 GPU这个位置可以考虑改成0,1来启动多卡训练但单机多卡在小数据集上收益有限1000 张图的规模下先跑通单卡流程更重要。MPS 是 Apple Silicon 上的 GPU 加速后端需要注意的是 MPS 对某些算子支持不完整在训练循环中遇到不支持的算子时会自动回退到 CPU 执行表现为训练速度下降而非报错。基于设备类型脚本需要自动调整三个关键参数batch size、是否启用 AMP 混合精度、worker 数量。以下是一套相对稳妥的默认值方案device, device_type detect_device() if device_type cuda: batch_size 16 amp True workers 4 elif device_type mps: batch_size 8 amp False workers 2 else: batch_size 4 amp False workers 0这里有两个细节值得解释。一是 MPS 和 CPU 下关掉 AMPPyTorch 的自动混合精度在 CUDA 上通过 NVIDIA 的 Tensor Core 加速但 MPS 后端对 float16 的支持仍然有限强行开启 AMP 虽然不报错但部分算子会以 float32 执行额外引入类型转换开销。二是 CPU 下 workers 设 0因为多进程数据加载在 CPU 训练时会和计算争抢核心反而拖慢速度。4.2 完整训练脚本参数解析、训练调用与结果落盘把上面的设备检测和参数默认值整合进完整脚本提供命令行覆盖入口才能称得上「一键训练」import argparse import torch from ultralytics import YOLO def parse_args(): parser argparse.ArgumentParser(descriptionYOLO11 brain tumor training) parser.add_argument(--data, typestr, defaultbrain_tumor.yaml, helpdataset yaml path) parser.add_argument(--model, typestr, defaultyolo11n.pt, helppretrained model name or weights path) parser.add_argument(--epochs, typeint, default100) parser.add_argument(--imgsz, typeint, default640) parser.add_argument(--batch, typeint, defaultNone, helpoverride auto batch size) parser.add_argument(--device, typestr, defaultNone, helpoverride device: 0/mps/cpu) return parser.parse_args() def main(): args parse_args() if args.device: device args.device device_type cuda if device.startswith(0) else device else: device, device_type detect_device() batch args.batch if batch is None: batch {cuda: 16, mps: 8, cpu: 4}[device_type] amp device_type cuda model YOLO(args.model) model.train( dataargs.data, epochsargs.epochs, imgszargs.imgsz, batchbatch, devicedevice, ampamp, projectruns/train, namebrain_tumor, exist_okTrue, ) if __name__ __main__: main()这段脚本的核心设计思路是让用户只需要改三个参数数据配置、预训练权重名、训练轮数。用 UltraLytics 的默认参数作为其余配置的兜底避免训练脚本里堆砌十几个超参数反而让使用者无从下手。脚本中 device 参数支持显式覆盖比如在 Mac 上用户明确想用 CPU 跑而不走 MPS就可以用--device cpu来指定。提示yolo11n.pt 会从官方 GitHub Release 自动下载如果在无外网环境或下载缓慢可以先在有网机器上下载好再通过--model /path/to/yolo11n.pt指向本地权重。4.3 训练过程中的参数监控与中断恢复YOLO11 训练过程中runs/train/brain_tumor/目录下会实时生成多个文件其中results.csv记录了每一轮的 loss、mAP50、mAP50-95、precision、recall 等指标。训练跑起来之后不要干等可以另开一个终端直接查看 CSV 的变化tail -20 runs/train/brain_tumor/results.csv另一个实用技巧是中断恢复。训练到一半因断电或被 kill 掉时Ultralytics 支持从上次保存的权重继续训练model YOLO(runs/train/brain_tumor/weights/last.pt) model.train(resumeTrue)注意 resume 模式会沿用原训练的所有参数配置这时命令行传入的 epochs 等参数会被忽略脚本里要避免在 resume 场景下又设置互相冲突的参数。训练结束后best.pt是验证集上指标最优的权重后续推理和部署都优先使用它。4.4 三个平台的典型训练失败场景排查CUDA 环境下最常见的报错是CUDA out of memory出现时优先调低 batch size 到 8 或 4如果仍然不够再把imgsz降到 512。医学影像有个特性是原始分辨率往往很大而肿瘤区域只占图中很小一部分直接在 640 分辨率下训练会丢失大量小目标细节。如果发现 mAP50 一直很低可以尝试把imgsz提升到 1024 或 1280 训练代价是显存占用指数级上升。Mac 上的 MPS 训练如果出现RuntimeError: Placeholder storage has not been allocated这是因为 MPS 的统一内存机制在批量推理时分配临时存储失败把 batch size 降到 4 或 2 通常能解决。CPU 训练则要预期速度远慢于 GPU1000 张图 100 轮、640 分辨率在 8 核 CPU 上大约需要数小时这时可以把workers调回 2 并观察 CPU 是否跑满如果跑不满说明数据加载成了瓶颈。5. 多平台推理验证与结果复现的细节5.1 给训练脚本配套一个三平台通用的推理验证脚本训练完成只是第一步真正检验模型的是在独立测试集上的推理表现。推理脚本同样要沿用设备自动检测逻辑并输出可视化结果和置信度信息import torch, argparse from ultralytics import YOLO def main(): parser argparse.ArgumentParser() parser.add_argument(--weights, typestr, defaultruns/train/brain_tumor/weights/best.pt) parser.add_argument(--source, typestr, requiredTrue) parser.add_argument(--conf, typefloat, default0.25) args parser.parse_args() if torch.cuda.is_available(): device 0 elif torch.backends.mps.is_available(): device mps else: device cpu model YOLO(args.weights) results model.predict( sourceargs.source, confargs.conf, devicedevice, saveTrue, projectruns/predict, namebrain_tumor_infer, exist_okTrue, ) for i, r in enumerate(results): print(f{i}: {len(r.boxes)} objects, fconf{r.boxes.conf.mean():.3f}) if __name__ __main__: main()推理脚本的 conf 参数默认 0.25但医学影像场景下我建议实际使用中调到 0.1 到 0.2 之间。肿瘤边界模糊、灰度对比度低模型输出的置信度天然偏低在医生复核的场景下宁可多画几个假阳性框让人眼筛掉也不能漏掉一个真正的肿瘤区。保存到runs/predict/brain_tumor_infer/的可视化结果可以直接用图像查看器打开快速判断模型学到的特征是否合理——比如是否聚焦在肿瘤区域的纹理和形状上还是错误地关注了图像角落的水印或文字。5.2 输出 mAP50 与 mAP50-95 的差异对肿瘤检测的意义三个平台的训练结束后不要只盯着一张 PR 曲线图。results.csv里的 mAP50 衡量的是 IoU 阈值 0.5 下的平均精度mAP50-95 则是对 0.5 到 0.95 之间多个 IoU 阈值的平均。人脑肿瘤检测场景下标注框本身带有标注者的主观性——同一张图上不同医生框出的范围可能有 5 到 10 个像素的偏差在 mAP50-95 这种对框位置精度敏感的指标上天然吃亏。因此评估模型好坏要同时看两个指标mAP50 反映目标检测的召回能力mAP50-95 反映定位精度。如果 mAP50 不错但 mAP50-95 明显偏低说明模型能找到肿瘤但框的位置不够准这时可以试试调低 anchor 的宽高比或使用更高输入分辨率。5.3 用 AMP 和 ONNX 导出做最后的跨平台效率验证模型训练完成后最后一个值得落地的技巧是用 ONNX 导出验证模型在非 Python 环境下的可用性。Ultralytics 提供了统一的 export 接口yolo export modelruns/train/brain_tumor/weights/best.pt formatonnx imgsz640导出 ONNX 后可以用onnxruntime推理控制台会输出每个输入节点的具体尺寸和数据类型。这里有个容易踩的坑在 Mac 上用torch.onnx.export导出时如果默认设备是 MPS部分算子会导出成 MPS 专用实现在 CPU 上跑 ONNX 时报不支持。Ultralytics 的 export 会自动切换到 CPU 完成导出不需要手动干预但如果你自己用 torch 写导出脚本要在导出前手动执行model.cpu()。最终在测试集的独立推理结果中如果模型的 mAP50 数值与训练时相近说明整个数据集从标签格式校验到训练脚本再到模型导出全链路是自洽的这个数据集也就可以放心复用到后续的模型迭代和对比实验中。本文还有配套的精品资源点击获取
返回列表