资讯动态

YOLOv5肺结节CT数据集:从数据准备到小目标调参实践

发布时间:2026/9/12 21:50:43 来源:尧图企业网站定制
简介面向医学图像目标检测任务该资源提供肺结节CT图像数据集并按YOLOV5标准目录结构整理标注统一为txt格式读取后即可供YOLO系列模型直接训练省去格式转换与目录修改步骤便于快速投入算法迭代。数据仅包含“肺结节”一个目标类别训练集包含220张图像及对应220个标签文件测试集包含28张图像及对应标签同时附带类别字典txt文件可用于配置模型类别数满足基础训练与验证需求。压缩包共499个文件主体为248张jpg格式CT影像与249个txt格式标注文件另附一个可直接运行的Python可视化脚本随机传入一张图片即可绘制边界框并将结果保存到当前目录有助于人工核验标注是否准确也便于展示检测效果。整个资源包大小约5.14MB体量小巧、目录结构清晰适合本地快速搭建实验环境。目前已有988人学习下载尤其适合医学影像算法研究者、目标检测方向学生以及进行项目开发或算法验证的工程师使用同时规模适中、格式规范也可作为深度学习初学者理解目标检测标注流程与YOLO数据组织的入门数据。1. 拿到一份YOLOV5目录格式的肺结节CT数据集先别急着训练肺结节CT图像目标检测是医学影像AI里最典型的「小目标低对比度」场景结节在CT切片上可能只有十几像素灰度差异又小直接套用通用目标检测流程很容易漏检。这份数据集已经按照YOLOV5目录格式整理好训练集220张、验证集28张共248张CT切片图像单类别「肺结节」标签全部是YOLO格式的txt文件还附带一个无需修改就能跑的可视化脚本。6MB的体积决定了它的定位不是临床级模型训练集而是用来跑通YOLOV5从数据加载、训练到评估的完整流程或者做迁移学习的起点。下面按数据组织、标签解析、可视化验证、训练配置和调参五个部分把这份数据集的用法和边界一次说清。2. 从CT切片到YOLO标签数据组织与格式拆解在动手训练前先把数据目录和标注格式看清楚。YOLOV5对数据组织有约定俗成的结构这个数据集基本沿用了通用目标检测数据集的 layout只是内容换成了医学CT图像。2.1 目录结构与数据集划分常见做法是datasets/下划分images和labels各自再按train、val分目录。这份数据集保存为训练集datasets/images/train、验证集datasets/images/val对应的标注文件放在datasets/labels/train和datasets/labels/val图片和标签文件名一一对应只是扩展名不同。展开来看是这样的datasets/ ├── images/ │ ├── train/ │ │ ├── R1.3.6.1.4.1.14519.5.2.1.6655.2359.111547677257119150655452340387.jpg │ │ ├── ... │ └── val/ │ ├── R1.3.6.1.4.1.14519.5.2.1.6655.2359.108523832239873578979600404354.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── R1.3.6.1.4.1.14519.5.2.1.6655.2359.111547677257119150655452340387.txt │ │ └── ... │ └── val/ │ └── ... ├── classes.txt └── visualize.py文件名里那一长串数字不是随机数而是 LIDC-IDRI 这类公开肺部CT数据集中 DICOM 文件的 SOP Instance UID。用 UID 做文件名好处是跨数据集不重名缺点是可读性差训练日志里要定位某张图时会比较费劲。表格统计一下数据规模数据划分图片数量标注txt数量类别数单张尺寸train2202201512x512 左右val28281512x512 左右总大小 6MB平均每张图片只有 25KB 左右说明这些CT切片很可能已经做过压缩或转成JPG。真实临床DICOM单张就要几百KB到1MB这也提醒我们这份数据适合流程验证不适合直接衡量模型在真实影像设备上的表现。2.2 YOLO标注格式归一化坐标与目标框YOLO 格式的 txt 文件每一行表示一个目标框格式是class x_center y_center width height。注意所有数值都相对于图片宽高做了归一化取值在 0 到 1 之间。随便打开一个标签文件内容会是这样0 0.5238 0.6114 0.0876 0.0932 0 0.7812 0.3251 0.0547 0.0612第一列 0 是类别编号因为只有一个类别所以全部是 0。后面四列分别是边界框中心的 x、y 坐标以及框的宽度和高度全部是归一化后的比例值。例如第一个框0.5238 0.6114表示目标中心点位于图片横向 52.38%、纵向 61.14% 的位置框宽高占图片宽高的 8.76% 和 9.32%。一个容易踩的坑是COCO 格式和 YOLO 格式的坐标顺序不同。COCO 是x_min y_min width heightYOLO 是x_center y_center width height两者换算关系如下x_center (x_min x_max) / 2 / image_width y_center (y_min y_max) / 2 / image_height width (x_max - x_min) / image_width height (y_max - y_min) / image_height如果你从其他工具拿到的是 COCO 标注务必先做转换再喂给 YOLOV5。数据集作者已经把标签转好这一步对使用者是透明的但理解换算关系有助于后面排查标注错位问题。2.3 类别字典与 classes.txt数据集根目录下的classes.txt是类别字典文件YOLOV5 在训练时会读取它来生成类别名列表。因为只有 肺结节 一类字典内容通常是单行nodule文件名可能是classes.txt也可能被写成nodule.yaml里的names字段。如果后续要在这个数据集上增加新类别比如把 磨玻璃结节 和 实性结节 分开就要同时修改classes.txt和每个 label 文件的第一列编号这是一个容易漏改的地方。我一般会在数据准备阶段写个小脚本统一校验类别编号是否越界避免训练中途报错。这一点在下一章展开。2.4 CT图像的小目标特性对标注的影响CT切片的肺结节在512x512的图像里往往只占几十个像素对应到归一化坐标上width 和 height 可能只有 0.02 到 0.1。这个量级说明默认的 YOLOV5 锚框设计并不一定适配。标准的 COCO 预训练模型锚框最小为 10x13对应到 640x640 输入也就是约 1.5% 的图幅对于更小的结节仍然会偏大。所以在这类数据上训练流程要和自然图像目标检测有所区别这一点会在第5章具体展开。另外CT图像是灰度图很多 YOLOV5 预训练模型是在 RGB 自然图片上预训练的训练时会把单通道复制成三通道。这不一定最优但实践表明在小数据集上直接使用预训练特征仍然比从零训练好。如果后续有多模态需求比如融合 PET 或 MRI才需要考虑更换 backbone 或输入分支。3. 训练前先看图用可视化脚本校验标注质量数据集的标注是人眼标注后转换的但转换过程可能出现坐标越界、框偏移、漏标错标。训练之前必须把标注可视化一遍这是所有目标检测项目里最值得花时间的步骤之一。3.1 运行自带的 visualize.py数据集作者提供了一个可视化 py 文件放在数据集根目录随机传入一张图片即可绘制边界框并保存到当前目录。正常使用方式是把脚本和数据放在同一个目录在终端执行python visualize.py --img datasets/images/train/R1.3.6.1.4.1.14519.5.2.1.6655.2359.111547677257119150655452340387.jpg脚本内部逻辑通常是用 OpenCV 读取图片和同名 txt逐行解析五个数值用cv2.rectangle在图上画框最后cv2.imwrite保存。运行后目录下会多出一张带框的图片直接打开看就能快速发现标注是否有整体偏移、框大小是否明显不符合结节形态。如果脚本接收的是图片路径需要保证图片名和标签名严格一致文件名里那一长串 UID 不要手动改改短后会导致脚本找不到 txt 而报错。3.2 自己写一个标签校验脚本如果原作者的可视化脚本只适合单张查看我一般会再写一个批量校验脚本把所有训练图片和标签过一遍检查三个问题文件是否成对、坐标是否越界、框是否过小或太大。下面这个脚本可以直接跑输出异常样本列表。import os import cv2 img_dir datasets/images/train label_dir datasets/labels/train for img_name in os.listdir(img_dir): if not img_name.endswith(.jpg): continue label_name img_name.replace(.jpg, .txt) label_path os.path.join(label_dir, label_name) img_path os.path.join(img_dir, img_name) # 1. 检查标签文件是否存在 if not os.path.exists(label_path): print(MISSING LABEL:, img_name) continue # 2. 检查归一化坐标是否越界 img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(BAD FORMAT:, img_name, line) continue cls, xc, yc, bw, bh parts xc, yc, bw, bh map(float, (xc, yc, bw, bh)) if not (0 xc 1 and 0 yc 1 and 0 bw 1 and 0 bh 1): print(OUT OF RANGE:, img_name, line) # 3. 按反归一化检测框尺寸 box_w, box_h bw * w, bh * h if box_w 3 or box_h 3: print(TOO SMALL:, img_name, box_w, box_h) print(done)这段脚本的逻辑很简单但很实用。第一段检查图片和标签是否成对排查漏转换或漏复制第二段把归一化坐标还原到像素尺寸标记出那些在 512x512 图上小于 3 像素的框。小于 3 像素的目标即使人眼也需要放大才能确认通常需要和医生确认是否保留。如果你的数据集里结节的真实最小直径都在 5 像素以上那么这些过小的框多半是标注噪声可以剔除。如果发现框整体偏移大概率是图像预处理时做了裁剪但标签没有同步变换。这类问题在可视化阶段暴露得越早后面浪费的 GPU 时间越少。如果要扩展到多类标注脚本里的cls变量还可以用来统计每个类别的目标数量分布。比如想知道结节大小分布可以把所有标签的bw、bh收集起来画直方图看是不是集中在 0.05 附近。这种分布信息在决定锚框和输入分辨率时非常有用。3.3 标签异常类型与处理方式异常现象可能原因处理方式标签文件缺失文件复制遗漏重跑划分脚本补全对应 txt坐标出现大于1或小于0标签转换未归一化将像素坐标除以图片宽高框绘在图像边缘但比例合理原标注框越界被裁剪裁剪时 clamp 坐标到 [0,1]尺寸异常小结节直径过小或标注误差与医学背景人员确认后决定保留或剔除这里重点提一下“坐标越界”的处理。很多工具在标注时会把框扩展到图像边缘之外转换脚本如果没有 clamp就会留下负数或大于1的值。这种数据直接训练YOLOV5 的损失函数虽然不会崩溃但会给出大量负样本拉低召回。建议统一按x min(max(x, 0), 1)的方式裁剪而不是直接把这些样本删掉因为边缘结节本身就是肺结节检测的重要场景。4. 用YOLOv5训练肺结节检测配置与命令数据检查通过后就是标准 YOLOV5 流程。这里以官方 ultralytics/yolov5 仓库为例版本分支选 v6.0 之后的版本都可以因为数据接口不变。关键是写好 data.yaml 和数据路径。4.1 准备数据集配置文件 data.yamlYOLOV5 通过一个 yaml 文件告诉训练脚本图片和标签在哪里、有多少类。打开nodule.yaml内容如下train: datasets/images/train val: datasets/images/val nc: 1 names: [nodule]注意train和val写的是images目录路径YOLOV5 会自动把路径中的images替换成labels来寻找标签文件。所以标签目录名必须保持和 images 下的划分一致否则会直接报assertion error找不到标签。这一点经常有人搞错有人把train字段写成 labels 路径结果数据加载器在 labels 下再找 labels自然找不到。如果你把数据集放在了自定义目录可以在 yaml 里写绝对路径也可以写相对路径以你执行训练命令的当前目录为基准。我倾向于用绝对路径避免换终端后路径失效。4.2 训练命令与超参数选择进入 yolov5 仓库目录安装依赖后执行python train.py \ --data /path/to/nodule.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0参数含义如下--data上一步配置的数据集文件指定类别和路径。--weights预训练权重。数据量很小用 COCO 的 yolov5s 做迁移学习能显著提升收敛速度和最终精度。--img输入尺寸640 是 YOLOV5 默认值CT 原图是 512x512用 640 会在训练时先 resize 到 640会轻微拉伸。由于 YOLOV5 默认启用 letterbox 填充不会改变宽高比所以可以接受。--batch批量大小6MB 的小数据集可以先从 16 开始根据显存调整。如果显存只有 8G--batch 8更稳妥。--epochs小数据集建议 100 起步。由于样本少训练很快一个 100 epoch 的流程在单张 3090 上十几分钟就能跑完。--device指定 GPU没有 GPU 可以去掉用 CPU 训练 248 张图也能跑但速度慢很多。小数据集上我建议再加几个参数python train.py \ --data /path/to/nodule.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --patience 20 \ --save-period 10--patience 20表示 20 个 epoch 内 mAP 没有提升就提前结束防止过拟合--save-period 10每 10 个 epoch 保存一次 checkpoint方便观察中间状态。这两个参数在长训练里很实用。表格里是几个影响较大的超参数参考值超参数建议值说明--img640可尝试 768 提升小目标召回--batch8-16根据显存调整--epochs100-300样本少参考 loss 曲线--weightsyolov5s.pt迁移学习--hypdata/hyps/hyp.scratch-low.yaml小数据集可选用低增强策略训练过程中看到终端打印类似Epoch gpu_mem box_obj cls ...的信息主要关注box_loss和obj_loss是否整体下降以及每个 epoch 结束时的mAP0.5。如果 loss 反复震荡不下降优先检查学习率YOLOV5 默认学习率 0.01在小数据集上可以降到 0.001 试试。--multi-scale参数可以每 10 轮随机变化一次输入尺寸范围是--img的 0.5 到 1.5 倍。对小目标检测有一定帮助因为它等于把目标按不同比例呈现给模型。但在这个数据集上我建议先关闭因为样本量太少多尺度会增加训练不稳定性等基线跑通后再开启对比效果。4.3 评估输出与结果文件训练结束后runs/train/exp目录下会生成weights/best.pt、results.png、confusion_matrix.png等。验证集只有 28 张指标波动会很大使用best.pt而不是last.pt是关键。可以用下面命令在验证集上单独评估python val.py \ --data /path/to/nodule.yaml \ --weights runs/train/exp/weights/best.pt \ --img 640 \ --conf-thres 0.001 \ --iou-thres 0.6注意--conf-thres设为 0.001 是为了在验证时统计所有可能的目标框避免因为置信度阈值过高而遗漏低置信度漏检。真正做推理时再使用 0.25 或 0.5。评估结果里mAP0.5和mAP0.5:0.95要分开看。肺结节这类小目标mAP0.5 可能在 0.7 以上但 mAP0.5:0.95 往往低不少因为 IoU 阈值提高后框位置稍有偏差就判为不匹配。这并不完全代表模型差而是小目标定位精度本来就难。如果你需要把训练好的模型导出为 ONNX 或 TensorRT 做推理可以使用export.py。但要注意导出的模型输入尺寸固定最好用训练时的--img一致的值否则精度会下降。这个小数据集的实验价值就在于此你能在几小时内快速验证一套端到端流程是否可行。5. 小目标调参锚框、数据增强与验证技巧肺结节检测的难点不在类别区分而在「目标太小」。248 张图、单类别默认 COCO 锚框可能不是最优。这一章给三个可落地的技巧。5.1 用 autoanchor 重算锚框YOLOv5 会根据数据集自适应锚框训练时会自动计算也可以禁用。小数据集上建议先用utils/autoanchor.py工具重新计算python utils/autoanchor.py --data nodule.yaml --img 640它会统计所有标签的宽高分布输出新的锚框建议。如果输出的锚框与默认值差别较大可以在yolov5s.yaml中手动替换anchors字段再重新训练。注意 autoanchor 的结果要放到模型 yaml 里而不是 data yaml 里。这一步对肺结节这种尺寸变化大的目标很有用因为 CT 结节直径从 3mm 到 30mm 都有对应像素差异接近 10 倍固定锚框覆盖不全。如果重算锚框后 mAP 反而下降可以保留默认锚框因为对于数据量极小的场景预训练锚框携带的分布先验可能比数据统计更可靠。此时--noautoanchor参数可以强制关闭自动锚框计算。5.2 降低 mosaic 增强对医学小目标的影响YOLOv5 默认开启 mosaic 增强将四张图拼接成一张。对普通目标检测是好事但对肺结节来说拼接后每个结节被进一步缩小容易变成 2-3 像素的噪声。我一般会在小目标场景把 mosaic 概率从 1.0 降到 0.5 甚至关闭方法是在训练命令里指定 hyp 文件python train.py --data nodule.yaml --hyp hyp.scratch-low.yaml --epochs 100然后编辑hyp.scratch-low.yaml中的mosaic: 0.5或mosaic: 0.0。同时保留轻微尺度抖动scale: 0.5帮助模型适应不同大小的结节。如果之后发现正样本数量太少还可以开启copy_paste但它对小目标的增益不明显反而增加训练时间不建议优先尝试。5.3 用特征图或结果图确认漏检原因训练完成后用detect.py在验证集上输出带框图片重点看假阴性样本。对于漏检的结节检查它周围是否有血管截面或其他高密度组织干扰。如果某几个固定位置漏检往往是标注问题而非模型问题回到第 3 章的可视化脚本复查那几张图。另一个办法是打印results.png中的 P、R 曲线观察 Recall 是否在低 confidence 区间有突然下跌如果有说明漏检集中在小目标上可以考虑提高输入分辨率或者重新调整锚框。清理未标注的近空白样本或去除异常小的标注后重训练通常能稳定提升 1-2 个点的 mAP。这种反复验证标注质量的过程比盲目调超参数更值得做。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价