
简介这份空中飞鸟检测数据集面向从事目标检测的开发者、学生与科研人员适用于机场飞鸟入侵预警、飞鸟驱赶、鸟类识别与计数等实际项目也可直接用于课程作业、竞赛与算法验证。数据集共3362张图像标注精准、背景丰富、鸟种多样目标大小与分布均衡算法拟合效果较好。压缩包内文件总数达10088个以jpg原图、xmlVOC、txtYOLO和json三类标签文件为主三种格式可满足不同检测框架的直接读取需求整体约548.94MB目录组织清晰便于按格式快速检索与训练。目前已有1209人学习下载数据均来自作者实际项目与实验demo质量有保障。读者可据此省去繁琐的标注与格式转换环节快速搭建训练与评估流程并借助多格式标签灵活适配YOLO、Faster R-CNN等主流算法为飞鸟检测相关课题提供可靠的数据基础。1. 空中飞鸟检测数据集三种标签格式为什么 3362 张图能省掉两周标注拿到一个空中飞鸟检测数据集第一眼别急着看图片好不好看先看标签格式全不全。3362 张图配上 VOC 的 xml、YOLO 的 txt、还有 json 三种标签这件事本身就值钱——它意味着你从数据清洗到模型训练之间少了一道最耗人的格式转换工序。做过检测项目的人都懂标注格式不统一是血泪经验里排名前三的翻车点VOC 的坐标是左上角加右下角的绝对值YOLO 要的是归一化后的中心点加宽高json 又常常是 COCO 那套 id 映射结构三者之间转来转去稍不留神框就偏了。这个数据集解决的就是这件事。它面向的是需要做空中飞鸟检测的从业者——可能是机场周边鸟情监测可能是风电场的鸟类碰撞预警也可能是生态调查里的自动计数。这些人不一定缺算力缺的是拿来就能进训练循环的干净标签。3362 张不算大但三种格式齐备等于把格式转换的坑提前填了。你拿到手可以直接喂 YOLO也可以转成 COCO 跑 Detectron2还能用 xml 做可视化核对。接下来我把这套数据从目录结构、格式校验、训练配置到踩坑排查按我实际跑过的顺序讲一遍。2. 三种标签格式的目录结构与字段对照先看懂再动手2.1 VOC xml、YOLO txt、json 各自长什么样VOC 格式的 xml 是每张图一个文件根节点是 annotation里面 folder、filename、size 描述图片然后是若干个 object 节点每个 object 里有 name、pose、truncated、difficult以及最关键的 bndbox里面 xmin、ymin、xmax、ymax 是像素绝对值。YOLO 的 txt 则是每张图一个同名文件每行一个目标格式是class_id x_center y_center width height后四个都是相对图片宽高归一化到 0 到 1 之间的小数。json 常见的是 COCO 风格一个文件装下所有图images 数组存文件名和尺寸annotations 数组存 bbox 的[x, y, width, height]绝对像素值加 image_id 和 category_idcategories 数组存类别名。这三种格式描述的是同一批框但坐标系和存储粒度完全不同。VOC 和 YOLO 是一图一文件json 是全集一文件。VOC 用绝对坐标YOLO 用归一化中心点json 用绝对左上角加宽高。理解这一点后面所有转换和校验都是围绕这几个差异展开的。2.2 目录组织与文件命名对齐一个规整的空中飞鸟检测数据集目录通常长这样我按常见做法列出来你拿到手先核对bird_dataset/ ├── images/ │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── annotations_xml/ │ ├── 000001.xml │ └── ... ├── labels_yolo/ │ ├── 000001.txt │ └── ... ├── annotations_coco.json └── classes.txt关键是对齐images 下的000001.jpg必须能在 annotations_xml 找到000001.xml在 labels_yolo 找到000001.txt。json 里的 file_name 也要能对上。我一般先跑一段脚本统计三者的文件名集合是否一致差集不为空就说明有图缺标签或者标签缺图这种样本进训练就是噪声。import os img_dir bird_dataset/images xml_dir bird_dataset/annotations_xml txt_dir bird_dataset/labels_yolo imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir)} xmls {os.path.splitext(f)[0] for f in os.listdir(xml_dir)} txts {os.path.splitext(f)[0] for f in os.listdir(txt_dir)} print(图缺xml:, imgs - xmls) print(xml缺图:, xmls - imgs) print(图缺txt:, imgs - txts) print(txt缺图:, txts - imgs)这段脚本做的是集合差运算。os.path.splitext去掉扩展名只留主名三个集合两两对比就能定位缺失。参数上没什么可调的路径改成你自己的即可。跑完如果差集为空说明命名对齐没问题可以进下一步格式校验。如果有差集先别急着删人工看一眼是不是命名规则不统一比如有的用下划线有的用短横线。2.3 类别映射classes.txt 与 json 的 categories 必须一致YOLO 的 class_id 是从 0 开始的整数json 的 category_id 有时从 1 开始VOC 里存的是类别名字符串。这三者必须有一张统一的映射表。classes.txt 一般一行一个类别名行号减一就是 YOLO 的 class_id。我见过太多翻车案例训练时类别对不上模型把鸟学成了背景mAP 一直是零查半天才发现 json 的 category_id 从 1 开始而 YOLO 从 0 开始差了一位。with open(bird_dataset/classes.txt) as f: classes [line.strip() for line in f if line.strip()] print(类别数:, len(classes)) for i, c in enumerate(classes): print(fYOLO class_id{i} - {c})这段把 classes.txt 读成列表并打印索引映射。参数上注意空行要过滤掉否则索引会错位。如果 json 的 categories 里 id 不是从 0 连续递增你需要单独建一张 json_id 到 yolo_id 的字典转换时查表替换不能想当然认为它们一样。3. 用脚本校验三种标签是否自洽坐标转换与可视化核对3.1 VOC 与 YOLO 坐标互转公式VOC 的 bndbox 是 xmin、ymin、xmax、ymax转 YOLO 需要先算中心点和宽高再除以图片宽高归一化def voc_to_yolo(xmin, ymin, xmax, ymax, img_w, img_h): x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h return x_center, y_center, width, height反过来 YOLO 转 VOCdef yolo_to_voc(x_center, y_center, width, height, img_w, img_h): xmin (x_center - width / 2.0) * img_w ymin (y_center - height / 2.0) * img_h xmax (x_center width / 2.0) * img_w ymax (y_center height / 2.0) * img_h return xmin, ymin, xmax, ymax这两个函数是整个校验的核心。参数里 img_w 和 img_h 必须从图片实际尺寸读不能从 xml 的 size 节点直接信因为有些标注工具写的 size 和真实图片不一致这是常见坑。我一般用 PIL 或 OpenCV 重新读一遍图片尺寸和 xml 里的 size 对比不一致就以图片为准。3.2 批量校验脚本找出越界框和零面积框归一化坐标有个硬约束x_center、y_center、width、height 都必须在 0 到 1 之间且 x_center 加减 width 的一半不能越界。越界框进训练会让损失函数算出异常梯度轻则 loss 震荡重则 BN 崩溃。下面这段批量扫一遍import os def check_yolo_label(txt_path): bad [] with open(txt_path) as f: for line_no, line in enumerate(f, 1): parts line.strip().split() if len(parts) ! 5: bad.append((line_no, 字段数不对)) continue cls, xc, yc, w, h parts xc, yc, w, h map(float, (xc, yc, w, h)) if not (0 xc 1 and 0 yc 1): bad.append((line_no, 中心点越界)) if not (0 w 1 and 0 h 1): bad.append((line_no, 宽高非法)) if xc - w/2 -1e-6 or xc w/2 11e-6: bad.append((line_no, 横向越界)) if yc - h/2 -1e-6 or yc h/2 11e-6: bad.append((line_no, 纵向越界)) return bad for f in os.listdir(bird_dataset/labels_yolo): if f.endswith(.txt): issues check_yolo_label(os.path.join(bird_dataset/labels_yolo, f)) if issues: print(f, issues)这段逐行解析 YOLO txt检查字段数、中心点范围、宽高范围、以及框是否越出图片边界。容差用 1e-6 是为了放过浮点误差。跑完如果输出一堆文件说明标签质量有问题需要回到标注环节修。如果输出为空恭喜这批标签可以直接用。3.3 可视化核对把框画回图上脚本校验只能查数值合法性查不出语义错误比如框标到了云上而不是鸟。最可靠的办法是抽样画框import cv2 import os def draw_yolo(img_path, txt_path, out_path): img cv2.imread(img_path) h, w img.shape[:2] with open(txt_path) as f: for line in f: cls, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw/2) * w) y1 int((yc - bh/2) * h) x2 int((xc bw/2) * w) y2 int((yc bh/2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(out_path, img) for name in [000001, 000002, 000003]: draw_yolo(fbird_dataset/images/{name}.jpg, fbird_dataset/labels_yolo/{name}.txt, fvis_{name}.jpg)这段读图、读 YOLO 标签、把归一化坐标还原成像素坐标画矩形。参数上矩形颜色和线宽随意关键是坐标还原公式要和 3.1 节一致。抽十几张看一眼如果框都套在鸟身上说明标签语义没问题。如果框整体偏移大概率是宽高顺序搞反了YOLO 是宽在前高在后别写反。4. 把 3362 张图喂进 YOLO 训练数据配置与必调参数4.1 生成 train/val 划分与 data.yamlYOLO 训练需要一个 data.yaml 描述数据路径和类别。3362 张按 8:2 划分训练集约 2690 张验证集约 672 张。我一般用脚本随机划分并生成文件列表import os, random random.seed(42) names [os.path.splitext(f)[0] for f in os.listdir(bird_dataset/images)] random.shuffle(names) split int(len(names) * 0.8) train_names names[:split] val_names names[split:] with open(train.txt, w) as f: for n in train_names: f.write(fbird_dataset/images/{n}.jpg\n) with open(val.txt, w) as f: for n in val_names: f.write(fbird_dataset/images/{n}.jpg\n)固定随机种子 42 是为了可复现换种子会得到不同划分对比实验时别乱换。data.yaml 内容path: /abs/path/to/bird_dataset train: train.txt val: val.txt nc: 1 names: [bird]nc 是类别数names 要和 classes.txt 一致。path 用绝对路径相对路径在不同工作目录下容易翻车。4.2 训练命令与关键超参yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ device0参数说明imgsz 640 是常见起点飞鸟目标偏小可以试 960 或 1280但显存要够。batch 16 在 8G 显存上跑 640 尺寸一般没问题爆显存就降到 8。lr0 初始学习率 0.01 是 YOLO 默认小数据集可以降到 0.005 更稳。patience 20 表示 20 轮没提升就早停省时间。device 0 指定第一块 GPUCPU 训练把 device 设成 cpu 但会很慢。4.3 小目标飞鸟的锚框与增强策略空中飞鸟在 640 尺寸下往往只有几十像素属于小目标。YOLO 的默认锚框是 COCO 上聚类的对小鸟不一定最优。常见做法是开 mosaic 和 mixup 增强让模型多见小目标组合mosaic: 1.0 mixup: 0.1 scale: 0.5 flipud: 0.5 fliplr: 0.5mosaic 1.0 表示每张图由四张拼成能显著增加小目标出现频率。mixup 0.1 轻度混合太高会让小目标更糊。scale 0.5 允许缩放抖动flipud 和 fliplr 是上下左右翻转飞鸟场景上下翻转合理因为鸟在空中各个朝向都有。这些参数写在训练配置里或命令行传都行。5. 避坑与排查标签格式转换里最容易翻车的五件事5.1 现象训练 loss 正常但 mAP 始终为零原因类别映射错位。json 的 category_id 从 1 开始YOLO 的 class_id 从 0 开始转换时没减一导致所有标签指向一个不存在的类别模型学不到有效目标。解决转换前先打印 json 的 categories 和 classes.txt 对照建一张显式映射字典转换时查表。训练前用 3.3 节的可视化脚本确认框和类别都对。5.2 现象框整体偏移或大小不对原因宽高顺序写反或者归一化时除错了维度。YOLO 是x_center y_center width height有人写成x_center y_center height width框就会横竖颠倒。另一种是把 x 除以了高、y 除以了宽。解决回到 3.1 节的转换公式逐行核对用一张已知框的图手动算一遍和脚本输出对比。可视化画框是最快的验证手段。5.3 现象xml 里的 size 和真实图片尺寸不一致原因标注工具读图时用了缩略图或者图片被后期裁剪过但 xml 没更新。这会导致 VOC 转 YOLO 时归一化分母错误框全部偏移。解决转换时不要信 xml 的 size用 OpenCV 或 PIL 重新读图片真实宽高。批量脚本里加一句断言size 不一致就打印文件名人工处理。5.4 现象json 解析报错或字段缺失原因json 文件不完整或者用了非标准 COCO 结构比如 bbox 存成了[x1, y1, x2, y2]而不是[x, y, w, h]。COCO 标准是左上角加宽高但有人图省事存成两角点。解决解析前先看 json 顶层键确认 images、annotations、categories 三个都在。bbox 长度是 4 但语义不确定时抽一条和对应图片的可视化结果比对确认是哪种约定再写转换。5.5 现象训练中途 BN 崩溃或 loss 变 NaN原因标签里有零面积框或越界框归一化后 width 或 height 为 0计算损失时除零。也可能是某张图所有目标都被裁掉变成空标签文件。解决跑 3.2 节的校验脚本把所有非法框找出来。零面积框直接删越界框裁剪到边界内或删。空标签文件要么补标要么从训练集移除别留着。6. 用 json 标签做 COCO 评估与跨格式一致性抽查三种格式齐备的最大好处是你可以用 json 走 COCO 评估流程再用 VOC 或 YOLO 做训练最后交叉验证。具体做法把 YOLO 训练出的预测结果转成 COCO 格式的 results.json用 pycocotools 算 mAP和 YOLO 自带的验证指标对比。如果两者差距很大说明某一环的坐标转换有问题。from pycocotools.coco import COCO from pycocotools.cocoeval import COCOeval coco_gt COCO(bird_dataset/annotations_coco.json) coco_dt coco_gt.loadRes(predictions.json) evaluator COCOeval(coco_gt, coco_dt, bbox) evaluator.evaluate() evaluator.accumulate() evaluator.summarize()这段加载真值 json 和预测 json跑标准 COCO 评估。predictions.json 里每条要有 image_id、category_id、bbox、scorebbox 是[x, y, w, h]绝对像素。参数上注意 category_id 要和真值 json 一致别用 YOLO 的 0 基 id 直接填。跨格式一致性抽查我一般这么做随机抽 50 张图分别用 xml 和 txt 还原框算两者的 IoU正常应该全是 1.0因为描述的是同一批框。如果出现 IoU 小于 0.99 的说明转换有精度损失或某一边标签本身不一致。这个抽查能兜住大部分隐蔽的格式 bug。最后一个习惯每次拿到新数据集先跑一遍文件名对齐、坐标校验、可视化抽样这三板斧再进训练。3362 张图跑完这三步也就几分钟但能省掉后面几小时的 debug。希望帮到你。本文还有配套的精品资源点击获取