☰
肺炎检测数据集VOC+YOLO格式4983张2类别:从标注到YOLOv8训练全流程
2026/10/11 10:34:00 网站建设 项目流程

简介:本资源为肺炎检测数据集,面向医学影像分析方向的算法工程师、研究生及深度学习入门者,用于训练和验证肺炎阳性与阴性二分类目标检测模型。数据集同时提供Pascal VOC与YOLO两种标注格式,包含jpg图片及对应的xml、txt标注文件,标注工具为labelImg,采用矩形框标注,共2个类别:pneumonia negative与pneumonia positive,总框数达10041个,其中阴性框5328个、阳性框4713个。压缩包为7z格式,共2000个文件,以1999个xml标注文件和1个txt说明文件为主,整体约112.65MB,目录结构清晰,便于直接接入主流检测框架。需注意数据集中包含较多增强图片,建议下载前仔细查看图片预览并斟酌使用。目前已有469人学习下载,适合需要快速获取标注数据、开展医学影像检测实验与模型对比的读者参考使用。

1. 肺炎检测数据集 VOC+YOLO 格式 4983 张 2 类别:这批数据到底能训出什么

拿到一个标注好的肺炎检测数据集,第一反应通常不是「太好了」,而是「这 4983 张到底够不够、2 个类别是哪两类、VOC 和 YOLO 两种格式怎么选」。肺炎检测在胸片场景里属于典型的密集小目标问题——病灶区域边界模糊、对比度低、不同设备成像差异大,和 COCO 里那些轮廓清晰的日常物体完全不是一回事。这批数据同时提供 VOC XML 和 YOLO TXT 两套标注,意味着你既能直接喂给 YOLOv8/v11 这类检测器,也能用 VOC 格式做数据清洗和可视化复核。它适合两类人:一是想跑通医学目标检测全流程的入门者,二是手里有胸片数据、需要一份可对照的标注规范做参考的从业者。核心价值不在「数据量大」,而在「格式齐全、类别干净」,省掉了最耗时的格式转换和标注校验环节。

2. 肺炎检测数据集的两套标注格式:VOC 与 YOLO 到底差在哪

2.1 VOC XML 的结构与肺炎场景下的字段含义

Pascal VOC 格式用一张图对应一个 XML 文件,核心节点是<object>,里面记录类别名和<bndbox>的四个坐标。肺炎检测里,<name>通常就是pneumonia和normal两类,<bndbox>用的是绝对像素坐标,左上角xmin/ymin、右下角xmax/ymax。这种绝对坐标的好处是直观——你打开 XML 就能知道框在图上哪个位置,做可视化复核时不用换算。但缺点也明显:图像缩放后坐标全部失效,必须重新标注或做同步缩放。

<annotation> <filename>patient_001.png</filename> <size> <width>1024</width> <height>1024</height> <depth>3</depth> </size> <object> <name>pneumonia</name> <!-- 类别名,2 类别场景下另一类是 normal --> <bndbox> <xmin>312</xmin> <!-- 绝对像素坐标,左上角 --> <ymin>208</ymin> <xmax>498</xmax> <!-- 右下角 --> <ymax>376</ymax> </bndbox> </object> </annotation>

上面这段 XML 里,<size>记录原图宽高,是后续做坐标归一化的基准。<name>必须和你的classes.txt严格一致,大小写、空格都不能差,否则训练时会出现「标注文件里有的类别,模型配置里没有」的报错。<bndbox>四个值必须是整数且xmax > xmin、ymax > ymin,肺炎病灶框如果出现零宽或零高,多半是标注时误操作,训练前必须过滤。

2.2 YOLO TXT 的归一化坐标与类别索引映射

YOLO 格式每张图对应一个 TXT,每行一个目标,格式是class_id x_center y_center width height,全部是归一化到 0~1 的浮点数。和 VOC 最大的区别有两点:一是类别用整数索引而不是字符串,索引顺序由classes.txt或data.yaml里的names列表决定;二是坐标是中心点加宽高,不是角点。肺炎检测里病灶框往往偏小,归一化后数值可能只有 0.0x 级别,这时候要特别注意浮点精度——用 Python 写回文件时保留 6 位小数足够,保留 2 位会把小框压没。

# VOC XML 转 YOLO TXT 的核心换算 def voc_to_yolo(xmin, ymin, xmax, ymax, img_w, img_h): x_center = (xmin + xmax) / 2.0 / img_w # 中心点 x 归一化 y_center = (ymin + ymax) / 2.0 / img_h # 中心点 y 归一化 w = (xmax - xmin) / img_w # 宽归一化 h = (ymax - ymin) / img_h # 高归一化 return x_center, y_center, w, h

这段换算里,img_w和img_h必须来自 XML 的<size>节点,不能凭经验假设 1024。肺炎数据集里图像尺寸不统一是常态,有的设备出 2048,有的出 512,写死尺寸会导致框整体偏移。换算完建议做一次反向校验:把 YOLO 坐标还原成像素坐标,和原 XML 对比,误差超过 1 像素就说明中间有取整问题。

2.3 两类别标注在训练配置里的写法

2 类别意味着nc=2,names列表顺序必须和 TXT 里的class_id对应。常见做法是0: pneumonia、1: normal,但有些数据集会把normal放 0。这个顺序一旦定下,训练、验证、推理全流程都不能改,否则模型会把肺炎当正常。建议在data.yaml里显式写清楚,并在训练前用脚本统计一遍每个类别的框数量,确认没有类别被漏标。

# data.yaml 关键字段 path: ./pneumonia_dataset train: images/train val: images/val nc: 2 names: 0: pneumonia 1: normal

path指向数据集根目录,train和val是相对路径。如果 VOC 和 YOLO 两套格式都保留,建议只把 YOLO 格式放进images/labels结构,VOC XML 单独放一个annotations_voc目录做备份,避免训练时路径扫描到多余文件。nc写错是最隐蔽的坑——写成 1 时模型只学一个类,另一个类的框会被当成背景,训练 loss 看着在降,实际漏检严重。

3. 用这批数据跑通 YOLOv8 训练:从解压到第一轮验证

3.1 解压后的目录整理与文件配对检查

拿到.7z压缩包,先别急着解压到桌面。肺炎数据集 4983 张图加标注,解压后文件数接近一万,散落在桌面会拖慢文件系统。我一般建一个pneumonia_workspace目录,里面分raw、datasets、runs三个子目录。raw放解压原始内容,datasets放整理后的 YOLO 结构,runs留给训练输出。

# 解压并整理目录结构 mkdir -p pneumonia_workspace/{raw,datasets,runs} 7z x pneumonia_dataset.7z -o./pneumonia_workspace/raw # 整理成 YOLO 标准结构 cd pneumonia_workspace/datasets mkdir -p images/train images/val labels/train labels/val # 假设原始图片和 TXT 在同一目录,按 8:2 划分 python split_dataset.py --src ../raw --dst . --ratio 0.8

split_dataset.py的核心逻辑是:遍历所有图片,找到同名 TXT,按比例复制到images/train和labels/train。这里有个血泪经验——图片和标注必须同名且成对,缺一个就跳过并在日志里记下来。肺炎数据集里偶尔会有标注文件存在但图片损坏的情况,直接训练会在 dataloader 阶段报错,提前检查能省掉半夜排查的时间。

3.2 训练命令与 batch size 在 4983 张规模下的取值

4983 张图、2 类别,属于中小规模检测任务。YOLOv8n 或 YOLOv8s 足够,没必要上 L 或 X,参数量大了反而过拟合。batch size 取决于显存:8G 显存跑 640 分辨率,batch=16比较稳;12G 以上可以上batch=32。epoch 建议 100 起步,肺炎病灶特征不明显,收敛比 COCO 慢。

yolo detect train \ data=./datasets/data.yaml \ model=yolov8s.pt \ epochs=150 \ imgsz=640 \ batch=16 \ device=0 \ patience=30 \ project=./runs \ name=pneumonia_v1

imgsz=640是 YOLO 默认值,但肺炎胸片原始分辨率往往更高,直接缩到 640 会丢失小病灶细节。如果显存允许,可以试imgsz=1024,mAP 通常有 2~5 个点提升。patience=30表示 30 轮验证指标不升就早停,避免无效训练。device=0指定第一块 GPU,多卡场景下要确认 CUDA 可见设备顺序。

3.3 第一轮验证看什么指标:mAP50 与混淆矩阵

训练跑完,先别只看mAP50。肺炎检测里mAP50-95更能反映框的定位质量,因为病灶边界本身就模糊,IOU 阈值一高,很多框就掉到 0.5 以下。混淆矩阵要重点看normal被误判成pneumonia的比例——临床上把正常当肺炎是过度诊断,反过来是漏诊,两者代价不同,调阈值时要有倾向。

from ultralytics import YOLO model = YOLO('./runs/pneumonia_v1/weights/best.pt') metrics = model.val(data='./datasets/data.yaml', imgsz=640) print(metrics.box.map) # mAP50-95 print(metrics.box.map50) # mAP50 print(metrics.confusion_matrix.matrix) # 混淆矩阵

metrics.box.map是核心指标,肺炎场景下能到 0.35 以上就算可用。混淆矩阵打印出来是二维数组,行是真实类别,列是预测类别,对角线是正确预测。如果normal那一行的非对角线值很高,说明模型对正常样本过敏感,可以适当提高推理时的conf阈值。

4. 肺炎检测训练避坑:标注、坐标与类别索引的 5 个翻车现场

4.1 现象:训练 loss 正常下降但 mAP 始终为 0

原因通常是类别索引错位。VOC XML 里写的是pneumonia,但data.yaml的names列表里pneumonia排在索引 1,而 TXT 文件里写的是 0。模型学的是「0 类」,验证时按「1 类」去匹配,自然全错。解决方法是写一个脚本,统计所有 TXT 里出现的class_id集合,和data.yaml的names长度对比,不一致就停下来查。

4.2 现象:部分图片训练时报「坐标越界」

原因是 VOC 转 YOLO 时没有做边界裁剪。肺炎标注里偶尔会出现xmax略大于图像宽度的情况,归一化后x_center + w/2 > 1。YOLO 的 dataloader 对越界坐标容忍度低,直接报错。解决是在转换脚本里加一行裁剪:x_center = min(max(x_center, 0), 1),宽高同理,同时记录被裁剪的样本,人工复核是不是标注错误。

4.3 现象:验证集 mAP 比训练集低 20 个点以上

这是典型的划分泄漏。4983 张图如果按随机划分,同一患者的多次检查可能同时出现在训练和验证集,模型记住了患者特征而不是病灶特征。肺炎数据尤其要注意按患者 ID 划分,而不是按图片随机分。如果数据里没有患者 ID,至少按图像来源设备或时间做分组划分。

4.4 现象:小病灶框在训练中被忽略

原因是 YOLO 的 anchor 匹配机制对小目标不友好。640 分辨率下,小于 16x16 像素的框很难被正样本匹配到。解决有两个方向:一是提高imgsz到 1024,让小框的绝对像素变大;二是用 YOLOv8 的close_mosaic参数,在最后几轮关掉 mosaic 增强,让模型专注小目标。

4.5 现象:推理时同一张图框数量忽多忽少

原因是conf阈值和 NMS 的iou阈值没调好。肺炎病灶密集时,NMS 的iou=0.7默认值会误删相邻框。建议推理时把iou降到 0.5,conf从 0.25 起调,观察框数量和实际病灶数的关系。如果框明显偏多,提高conf;框粘连,降iou。

5. 把 2 类别肺炎检测推到可用:阈值调优与误检复核的一个习惯

训练出best.pt只是起点,真正决定这批数据值不值得投入的,是推理阶段的阈值调优和误检复核。我一般会留出 200 张不参与训练的图做「临床模拟测试」,用不同conf和iou组合跑一遍,画一条 precision-recall 曲线,找那个「漏检可接受、误检不离谱」的平衡点。肺炎检测里,conf=0.35、iou=0.45是我在多个胸片数据集上试出来的起点,但每个数据集的成像风格不同,必须自己扫一遍。

import numpy as np from ultralytics import YOLO model = YOLO('./runs/pneumonia_v1/weights/best.pt') confs = np.arange(0.15, 0.65, 0.05) ious = np.arange(0.3, 0.7, 0.05) best = None for c in confs: for i in ious: r = model.val(data='./datasets/data.yaml', conf=c, iou=i, imgsz=640) # 综合 mAP50 和误检率,误检率用 1 - precision 近似 score = r.box.map50 - 0.3 * (1 - r.box.mp) if best is None or score > best[0]: best = (score, c, i, r.box.map50, r.box.mp) print(f"最佳组合 conf={best[1]:.2f} iou={best[2]:.2f} mAP50={best[3]:.3f} precision={best[4]:.3f}")

这段扫描的逻辑是:score把 mAP50 和 precision 加权,权重 0.3 是我根据肺炎场景定的——宁可稍微降一点 mAP,也要保证 precision 不太低,因为误检带来的复核成本很高。r.box.mp是平均 precision,1 - mp近似误检率。扫完之后,把最佳组合固定下来,写进推理脚本的默认参数。

另一个习惯是每次推理完,随机抽 20 张图,把预测框和原图叠在一起看。肺炎病灶有时候模型框的是肋骨边缘或者设备标记,这种误检在指标上看不出来,但临床上一眼假。我一般用 OpenCV 画框后存到runs/review目录,文件名带上conf值,方便回溯是哪组参数出的问题。这个复核习惯坚持下来,比多训 50 个 epoch 更能提升实际可用性。

最后说一句实在的:4983 张 2 类别的肺炎数据,训一个能用的筛查辅助模型是够的,但别指望它直接上临床。把它当成一个高质量的起点,用 VOC 格式做标注复核,用 YOLO 格式做快速迭代,把阈值调优和误检复核变成固定流程,这批数据的价值才能真正落地。希望帮到你。

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

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

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

立即咨询