
简介面向无人机视觉与计算机视觉研究者、开发者的行人检测数据集旨在为无人机航拍场景下的行人识别与避障提供高质量训练材料。整个压缩包共1895个文件包含630张jpg原图、630个xml边界框标注、634个txt标签说明并附1个py预处理/转换脚本包体约206.8MB。数据已划分训练集、测试集和验证集图像与标注一一对应覆盖从数据准备、格式转换到模型训练、评估的完整链路可直接用于YOLO、Faster R-CNN、SSD等主流检测框架免去自行采集和标注的繁琐工作。读者既能据此验证航拍视角下的检测效果也能通过对比实验分析不同模型性能同时学习PASCAL VOC风格标注与txt标签的组织方式。目前已有3956人学习下载适合无人机巡检、安防监控、智慧交通等场景下的算法研究与工程实践。1. 无人机行人检测数据集标注好了不等于直接能用关键看这四件事一个“已标注”的无人机行人检测数据集听起来像是拿到了现成的答案解压、训练、出模型三步走完。但我在本地跑过几个公开渠道能找到的无人机视角行人检测数据集之后最大的感受是标注好只是起点能不能让模型真的在无人机画面上把人检出来取决于标注质量、视角分布、目标尺寸和场景覆盖这四件事。这也是为什么同样用“已标注”的数据集有人三天跑出能用的模型有人折腾两周还在跟漏检和误检搏斗。这篇文章要解决的就是把你从“拿到数据集”带到“模型能落地”这段路。适合正在做无人机巡检、安防监控、智慧城市相关项目的开发者也适合刚入门目标检测、想用现成数据集快速验证算法思路的同学。我会从数据集的构成和标注规范讲起然后给出一套从数据校验到模型训练的可复现流程最后把高手才会注意的边界条件和踩坑点拆开讲。2. 数据集构成与标注规范先弄清楚“已标注”到底标注了什么拿到任何一个“已标注”的无人机行人检测数据集第一件事不是解压跑脚本而是先看清楚它的目录结构和标注格式。很多翻车现场都是从这里开始的看起来是同一套标注格式实际用的时候才发现坐标系统、类别编号、图片尺寸记录方式对不上白白浪费一下午。2.1 数据来源与场景分布先判断它适不适合你的任务无人机视角的行人检测和普通监控摄像头视角有本质区别。监控摄像头大多是俯仰角固定、目标尺度相对稳定无人机是俯视视角行人在画面里通常是小目标占比不到整张图的百分之几而且会随飞行高度和速度发生剧烈的尺度变化。数据里如果大多数图片的拍摄高度在30米以下、行人占比大那你拿去做50米高度的巡检任务就会出现明显漏检。我一般拿到数据集先做三件事统计图片分辨率分布、统计标注框面积分布、统计每张图的平均目标数。这三个数字直接决定这个数据集适不适合当前任务。标注框面积分布特别值得看——如果绝大多数框的长边小于64像素训练时需要重点考虑小目标检测策略如果数据和实际作业高度落差太大优先找同场景的数据集或者自己补采。2.2 标注格式与目录结构VOC、YOLO还是COCO常见的无人机行人检测数据集有三种标注形态Pascal VOC格式的XML文件、YOLO格式的TXT文件、COCO格式的JSON文件。三种格式的坐标表达方式不同VOC和COCO都是绝对像素坐标且用xmin、ymin、xmax、ymax这类方式记录YOLO格式用的是归一化的中心点坐标和宽高。图片尺寸记录这件事也容易踩坑VOC的XML里带有图片宽高可以直接校验YOLO的TXT不带尺寸信息如果原始图片被缩放标注坐标会全军覆没。我习惯用下面这条命令先摸清目录结构再决定怎么下手# 查看数据集目录树限制层级为3 cd dataset_root tree -L 3 -d # 统计图片数量、XML/TXT/JSON标注文件数量 find . -name *.jpg | wc -l find . -name *.xml | wc -l输出结果能告诉你数据集是原始结构还是已经做了划分。如果是划分好的通常有train、val、test三个目录但不少数据集只分了两部分需要自己再切一次验证集。# 统计标注框尺寸分布的Python脚本片段 # 这里按照YOLO格式的txt标注为例 import os from collections import Counter img_width, img_height 1920, 1080 size_bins Counter() label_dir labels/train for f in os.listdir(label_dir): if not f.endswith(.txt): continue with open(os.path.join(label_dir, f)) as fp: for line in fp: _, cx, cy, w, h line.strip().split() pixel_w float(w) * img_width pixel_h float(h) * img_height if pixel_w 32 or pixel_h 32: size_bins[tiny] 1 elif pixel_w 96 or pixel_h 96: size_bins[small] 1 else: size_bins[large] 1 print(size_bins)这段脚本的关键作用是提前暴露目标尺度分布。如果tiny类占比超过一半后面训练必须启用多尺度训练和更高分辨率的输入图。代码里img_width和img_height需要改成你手里数据的真实值不确定的话用Python的PIL库批量读取一张图确认。标注文件的格式如果是VOC或者COCO解析逻辑要相应改成XML或JSON取值但判断思路是一样的。3. 把数据集跑起来从解压到可视化校验的一条龙操作数据集的目录结构摸清了标注格式也确认了接下来不能直接进训练。先做可视化校验这是整个流程里最便宜的一道后悔药把标注框画到原图上人眼看一遍就能发现坐标偏移、类别错标、框没贴住目标这些问题。省下的是后面训练半天发现loss不下降的排查时间。3.1 先做数据划分与文件完整性检查训练前一定要划分数据。不要直接拿所有图片训练否则你连模型过拟合还是欠拟合都判断不了。常见做法是训练集、验证集、测试集按7:2:1划分。如果数据集本身划分好了检查一遍文件是否齐整——图片和标注文件一一对应是这步的重点。# 检查图片与标注文件是否一一对应 import os from pathlib import Path def check_pairs(img_dir, label_dir): imgs {Path(f).stem for f in os.listdir(img_dir) if f.endswith((.jpg, .jpeg, .png))} labels {Path(f).stem for f in os.listdir(label_dir) if f.endswith(.txt)} img_only imgs - labels label_only labels - imgs print(f缺标注的图片数: {len(img_only)}) print(f缺图片的标注数: {len(label_only)}) # 打印前5个缺标注的图片名方便定位 for name in list(img_only)[:5]: print(missing label:, name) check_pairs(images/train, labels/train)这段代码用意是暴露配对问题。很多数据集从网盘下载后会出现文件缺失或文件名被截断直接用完整的数据集训练会让模型在加载时报错或者默认跳过某些图片。缺标注的图片一定要从训练集里剔除否则训练过程中会随机报错而且报错信息往往不直观只显示一个DataLoader worker崩溃。剔除缺标注图片的方法不复杂把上面脚本里img_only里的文件移到另一个目录或者生成一个保留清单。我一般直接把训练清单写成文本训练脚本读取这个清单来加载图片这样比物理移动文件更灵活后面增删样本也方便。3.2 用可视化脚本给标注框画出来坐标对不对一眼便知校验标注正确性最快的方式就是画框。下面这段脚本读取YOLO格式标注并画在图上输出到preview目录。代码里做了坐标越界判断这是从踩坑里学来的不少数据集的标注框有极小概率越界如果不加保护后续变成COCO或VOC格式时数值会异常。# 可视化YOLO标注输出效果预览图 import cv2 import os import numpy as np def draw_yolo_boxes(img_path, label_path, out_dir): img cv2.imread(img_path) h, w img.shape[:2] colors [(0, 255, 0), (0, 0, 255), (255, 0, 0)] with open(label_path) as fp: for line in fp: parts line.strip().split() if len(parts) ! 5: continue cls int(parts[0]) cx, cy, bw, bh map(float, parts[1:]) # 反归一化还原像素坐标 x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) # 越界裁剪 x1, y1 max(0, x1), max(0, y1) x2, y2 min(w, x2), min(h, y2) cv2.rectangle(img, (x1, y1), (x2, y2), colors[cls % len(colors)], 2) cv2.putText(img, fcls-{cls}, (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[cls % len(colors)], 1) os.makedirs(out_dir, exist_okTrue) cv2.imwrite(os.path.join(out_dir, os.path.basename(img_path)), img) # 遍历前50张训练图做预览 img_dir images/train label_dir labels/train for i, fname in enumerate(os.listdir(img_dir)): if i 50: break stem os.path.splitext(fname)[0] lbl os.path.join(label_dir, stem .txt) if os.path.exists(lbl): draw_yolo_boxes(os.path.join(img_dir, fname), lbl, preview)从预览图里最容易发现的几个问题框整体偏移说明坐标归一化基准不对某些框宽高为0说明标注文件损坏类别编号大量超出预期说明数据集里可能混入了其他类别的样本。这批预览图务必肉眼过一遍至少抽看训练集、验证集、测试集各一部分。我见过有人在这个环节发现整个数据集的标注都没有贴住行人而是框住了背景这种问题不提前发现训练再久也不会有好结果。4. 用数据集训练检测模型完整流程与关键参数校验没问题就到了正式训练环节。多数人拿到“已标注”的无人机行人检测数据集目标是把模型训练到一个能用的水平。这个部分我以YOLO系列为例展开这也是目前无人机目标检测里最主流的方案兼顾速度和精度。训练流程上覆盖从选模型到判读训练曲线的完整路径。4.1 模型选型与数据格式适配模型选型的核心逻辑是算力有限就优先考虑YOLO系列的轻量版本需要极致精度且推理设备允许大模型再往上加。无人机场景通常是在嵌入式设备或者边缘计算盒子上跑推理参数规模太大会带来帧率压力。经验值是在30万像素级别的输入分辨率下轻量版能做到实时标准版有明显精度优势但速度下降明显。数据格式适配这一步是把第3章校验通过的YOLO格式TXT和图片组织成训练框架要求的目录结构。不同框架对数据组织方式要求不同但训练集和验证集的图、标分别放两个目录是最通用的做法# YOLO系训练框架通用的数据目录布局 datasets/ drone_person/ images/ train/ # 训练集图片 val/ # 验证集图片 labels/ train/ # 训练集标注txt val/ # 验证集标注txt data.yaml # 数据配置文件data.yaml是训练入口里面记录类别数、类别名和路径。写这个文件时有个高频坑路径最好写绝对路径或者使用相对当前工作目录的路径不要写一个看起来对但实际不存在的路径。# data.yaml 内容示例 path: /home/user/datasets/drone_person train: images/train val: images/val nc: 1 names: [person]这个文件的难点不在格式在于理解path字段的基准意义。很多框架会基于path拼接train和val的路径如果你把train写成/home/user/datasets/...这种绝对路径框架会拼出一串错误的地址。建议先写相对路径images/train然后在命令行验证路径拼接结果。框架启动时会打印实际加载的图片路径扫一眼就能确认。4.2 训练启动与参数调整训练启动命令看着简单但参数怎么设直接决定结果上限。我常用的训练命令如下# 以YOLO系框架为例启动训练 yolo train \ modelyolov8s.pt \ datadata.yaml \ epochs100 \ imgsz1280 \ batch16 \ lr00.01 \ mosaic0.5逐个说参数考虑imgsz1280是应对无人机小目标的关键设置。很多现成教程默认给640但无人机画面里的行人只有几十个像素分辨率太低会直接抹掉细节。显存够就上1280不够就降到960。mosaic0.5是马赛克增强的概率无人机行人数据集如果场景比较单一把增强概率降下来能避免训练分布和真实分布偏离太多。lr0初始学习率0.01是一个稳妥起点如果训练曲线震荡明显就降到0.005。# 训练后验证模型效果 yolo val \ modelruns/detect/train/weights/best.pt \ datadata.yaml这里的best.pt是训练过程中在验证集上精度最高的模型权重不是最后一轮的last.pt。用best做验证能反映真实可用精度。验证输出里主要看mAP50、mAP50-95这两个指标。对无人机行人检测来说mAP50的意义更大因为行人检测的判断标准通常框得差不多就行不需要像素级精确mAP50-95考察的是更严格的框质量如果这个数值过低而mAP50不低说明模型的框定位偏粗糙可以考虑在后续迭代里调整回归损失的权重。4.3 训练曲线的判读方法训练过程输出两张关键曲线loss曲线和验证指标曲线。loss曲线里训练loss下降而验证loss不降反升是过拟合的典型信号两个loss都在下降但速度很慢大概率是学习率太小或者数据增强过重。验证指标曲线里mAP50在前20个epoch快速上升、后面缓慢爬升是正常节奏如果前10个epoch完全没有上升迹象回查数据yaml和标签格式可能更高效。我一般会盯着前20个epoch的loss曲线做判断而不是等100个epoch全跑完。前20轮如果训练loss和验证loss同步下降这组参数就是健康的让它继续跑就行如果验证loss在20轮内出现了持续上升就可以直接停掉调参不浪费后面的几十轮时间。这也是遇到过太多次训练数小时、结果发现标签坐标是反的过程之后养成的习惯。5. 无人机行人检测避坑指南五个高频问题与排查路径这个数据集方向上几乎每个坑都会让训练时间翻倍。以下五条是从实际操作里反复踩出来的每条都按现象、原因、解决三个层次来写。5.1 小目标漏检严重模型几乎对远处的行人无感现象训练后的模型对近距离行人检测效果尚可但画面里的远距离行人大量漏检甚至完全不报。验证集上mAP50不低但实际飞高之后效果立刻劣化。原因训练数据里小目标样本占比高但模型输入分辨率不足网络下采样后小目标特征被卷积层抹掉了。多数模型的下采样倍率是32倍输入640时一个32像素的行人在最终特征图上只有1个像素点几乎不可能被检出。解决三步走。第一步把imgsz提升到1280让同样一个行人占据更多像素第二步开启多尺度训练让模型见过不同尺寸的行人第三步如果仍然漏检用基于锚点的检测头并单独调高小目标层的权重。5.2 标注框和图片分辨率对不上坐标明显偏移现象可视化预览时所有框集体向左上偏移而且远处小目标的框偏得格外明显。原因数据集里图片原始分辨率是4000x3000但标注坐标是基于缩略图1500x1000做的训练时直接读取原始图片导致坐标换算错误。这类问题在从网盘下载的多个来源混合数据集里特别常见。解决检查图片的真实尺寸并用它作为反归一化的基准。不要信文件命名里的尺寸信息用Python的PIL或OpenCV读一遍。如果发现混用批量将图片统一缩放到标注坐标对应的尺寸或者把标注坐标重新换算到图片实际尺寸。5.3 负样本太少误检成群出现现象模型把屋顶、车辆、树冠频繁识别成行人而且误检位置集中在某些特定纹理区域。原因数据集中绝大多数图片都包含行人纯背景帧几乎没有。模型学到的是“有纹理的局部区域像行人”而不是真正区分行人的结构特征。解决从无人的巡检视频里抽帧加入20%到30%作为负样本标注文件留空即可。这是成本最低又最有效的防误检手段。加入负样本后模型会学会“在没有行人时输出空检测”而不是硬找出一个框。5.4 类别不平衡导致训练不收敛现象损失函数持续震荡验证mAP在一两个点之间来回跳模型输出的类别概率倾向于某一类比如背景类。原因数据集中某些类别样本极少检测头对这类目标的梯度贡献被大类别淹没。在行人数据集里这往往表现为“行人和骑行的人混在一起但其中一类数量很少”。解决最简单的做法是给不同类别设置不同的loss权重或者在采样器里做类别重采样。另一个可行方案是把稀有类别合并到大类别里——如果你的任务不要求区分这两个子类合并是更务实的做法。5.5 训练集和验证集分布不一致现象训练loss下降漂亮验证集mAP也很高但模型在真实场景里表现稀烂。换了一批图片测试后精度掉了一半以上。原因数据划分时没有做随机化或者是按时间顺序切分导致验证集和训练集场景高度相似验证结果虚高。更隐蔽的情况是如果数据集里包含同一个场景的连续帧随机划分会让相似的画面同时出现在训练集和验证集严重的“数据泄露”会让指标失真。解决按视频序列划分数据同一个视频来源的帧只能出现在一个集合里。只需要在划分前按文件名前缀分组再对组进行划分就能避免这个问题。这样评估结果才真正反映模型面对新场景时的表现。6. 把数据集的价值最大化三个让模型更进一步的技巧当你已经在“已标注”的数据集上跑通了基线模型接下来这三个技巧能让模型的实用性和精度再上一个台阶。这三个技巧用到最多的场景是模型已经能用、但距离实际作业要求还差一口气的时候。第一个技巧是多尺度训练与推理联动。训练时开启多尺度每轮迭代随机从某个尺度范围内采样输入尺寸让模型适应行人尺度的变化。推理时用TTA测试时增强把原图和缩放后的图分别送进模型推理再融合结果。这个组合能让小目标检测的mAP提升大约3到5个点代价是推理耗时增加。实测中TTA对无人机场景的收益特别明显因为行人的绝对尺寸在飞行高度变化时会剧烈波动。第二个技巧是利用伪标注迭代优化。把已训练模型拿到目标场景的新视频上跑一遍推理得到一批带置信度的检测结果人工筛选高置信度框作为伪标注加入训练集。这个过程能显著提升模型在新场景的适应能力。筛选标准要高置信度至少0.8以上并且经过人工抽检确认。一轮伪标注迭代大约能让新场景的recall提升10%以上。我在项目中试过用这个方法让模型的场景迁移成本降低了七成但要注意每轮迭代后都要重新划分数据集避免数据泄露。第三个技巧是可视化特征图来定位失败原因。训练结束后选取一张漏检图片把网络中间层的特征图可视化出来观察小目标区域在网络深层是否还有响应。如果响应微弱说明网络在这个尺度上已经丢失了目标信息如果响应强烈但最终输出没有框则问题多半出在检测头或者后处理阶段。这类排查比盲调参数高效得多能直接把优化方向从“玄学调参”变成“针对修复”。我自己的教训是每次拿到新数据集先花一个小时做第2、3章的校验再开始训练这样后面省下的时间通常是三倍以上。哪怕数据是官方发布的“精品数据集”也值得走一遍这个流程。希望帮到你。本文还有配套的精品资源点击获取