ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

航拍校园人体检测数据集构建与YOLO训练调参实战

航拍校园人体检测数据集构建与YOLO训练调参实战 航拍视角下的人体检测和地面监控、手持拍摄完全是两码事。我最早接触这类需求是帮一个做校园安防的朋友处理一批无人机巡检素材——操场上有跑步的、踢球的、三三两两散步的还有蹲在角落系鞋带的人一多、角度一斜、光照一变通用的人体检测模型就开始疯狂漏检和误检。后来陆续又做了几个类似的项目才慢慢摸清了航拍人体检测这条路上的门道。这篇就围绕航拍校园操场人体检测数据集这个主题把数据集构建、YOLO训练调参、航拍场景特有的坑以及实测下来真正管用的技巧一次性讲透。不管你是刚入门目标检测的新手还是已经跑过几个YOLO项目想啃航拍这块硬骨头的从业者应该都能从里面捞到点能直接用的东西。1. 为什么航拍人体检测不能直接套用通用数据集1.1 航拍视角带来的三个根本性差异很多人拿到航拍人体检测任务的第一反应是去下载COCO或者VOC里带person类别的子集直接开训。我一开始也这么干过结果mAP惨不忍睹。问题出在航拍视角和常规视角之间存在三个根本性差异不解决这三个差异再好的模型也白搭。第一个差异是目标尺度极端偏小。地面监控里一个人可能占几百个像素高而航拍在几十米到上百米高度拍摄时一个人往往只有十几到几十个像素。校园操场这种场景尤其明显一个标准400米跑道无人机在100米高度拍全景跑道上的人可能就20×10像素左右。这么小的目标经过YOLO的多次下采样之后特征图上几乎就剩一两个像素点了网络很难学到有效特征。第二个差异是视角导致的形态畸变。地面视角看人是竖着的航拍俯视看人是横着的——你看到的主要是头顶、肩膀和一小截身体。人的姿态特征完全变了通用模型学到的头-躯干-腿这种垂直结构先验在航拍里基本失效。更麻烦的是俯视角度下人和地面的对比度会随高度、光照剧烈变化有时候人就是一个模糊的深色斑点。第三个差异是背景干扰的独特性。校园操场有跑道线、球场白线、树影、看台座椅、停放的自行车这些元素在航拍视角下都可能被误判成人。尤其是跑道上的白色分道线在低分辨率下和躺倒的人体轮廓有几分相似模型很容易在这里翻车。1.2 校园操场场景的特殊性拆解校园操场这个场景比一般的航拍人体检测还要更刁钻一些。我总结下来有几个特点做数据集的时候必须针对性考虑。人群密度分布极不均匀。上课时间操场可能空无一人课间操或者体育课时间又可能几百人同时出现。这种密度跨度意味着你的数据集既要有稀疏场景单人或几人也要有密集场景几十人聚集否则模型在某一端必然表现差。运动状态多样。跑步的人有运动模糊踢球的人姿态扭曲做操的人排列整齐但动作统一散步的人相对静止。不同运动状态对检测的影响完全不同数据集里必须覆盖。遮挡情况复杂。航拍俯视下人和人之间的遮挡是从上往下压的一个人可能被前面的人挡住大半个身子只剩一个肩膀露出来。这种遮挡模式和地面视角的左右遮挡完全不同标注时要有统一规则。光照和天气变化。同一块操场上午、正午、傍晚的光照方向完全不同阴影长度和方向也在变。阴天、晴天、甚至小雨天的成像差异也很大。如果数据集只覆盖单一光照条件模型上线后遇到其他条件就会崩。1.3 通用数据集迁移到航拍场景的实测差距我做过一组对比实验用COCO的person子集预训练模型直接在自建的航拍校园数据集上测试不做任何微调。结果在稀疏场景下mAP勉强能到0.4左右密集场景直接掉到0.2以下小目标的召回率更是惨到不足0.3。后来用航拍数据做微调之后稀疏场景mAP提到0.85以上密集场景也能到0.7左右。这个差距说明航拍人体检测数据集不是锦上添花而是雪中送炭——没有针对性的数据模型根本没法用。2. 航拍校园人体数据集从采集到标注的完整链路2.1 采集方案设计高度、角度、时段的组合策略数据集采集是整个项目的地基地基没打好后面调参调到天荒地老也救不回来。我踩过的最大坑就是一开始采集太随意只在一个高度、一个时段拍了几百张结果模型泛化能力极差。正确的做法是做参数矩阵。核心变量有三个飞行高度、拍摄角度、拍摄时段。飞行高度建议覆盖三档低空30-50米、中空60-100米、高空120-150米。低空目标大、细节多适合学精细特征高空目标小、挑战大是检验模型小目标能力的关键。三档数据都要有比例大概是低空30%、中空40%、高空30%。拍摄角度主要分两种正俯视云台垂直向下和斜俯视云台倾斜30-60度。正俯视目标形态最规整斜俯视更接近实际巡检场景但畸变更大。建议正俯视占60%斜俯视占40%。拍摄时段至少覆盖上午、正午、傍晚三个时段有条件的话加上阴天。不同时段的光照方向差异巨大正午顶光阴影短傍晚侧光阴影长这些都要让模型见过。采集时还要注意避免连续帧冗余。无人机悬停拍摄时连续帧之间差异极小如果直接全部拿来用数据集会有大量近似重复样本导致训练集和验证集分布过于接近评估结果虚高。我的做法是每隔一定时间间隔抽帧或者用图像相似度做去重保证样本多样性。2.2 标注规范小目标、遮挡、密集场景的处理原则标注这活儿说简单也简单画框嘛说难也难航拍场景下每个框怎么画都有讲究。我整理了一套自己一直在用的标注规范分享出来。小目标标注原则目标小于16×16像素时如果肉眼还能分辨出是人就标如果已经糊成一团完全无法确认就丢弃不标。这里的关键是一致性——同一批数据里要么都标要么都不标不能有的标有的不标否则模型会学到矛盾的信号。遮挡标注原则航拍俯视下只要目标可见部分超过30%就标完整框框住估计的完整人体范围可见部分不足30%的标可见部分框或者直接忽略。这个阈值可以根据你的实际需求调整但一旦定了就要严格执行。密集场景标注原则人群密集时人和人挨得很近框会大量重叠。这时候不要为了框不重叠而缩小框该重叠就重叠YOLO系列对重叠框的处理能力是够的。但要注意如果两个人完全重叠一个完全被另一个挡住只标可见的那个。标注工具选择我用过LabelImg、CVAT、Labelme几款。小目标密集场景下CVAT的体验最好支持缩放、复制框、快捷键操作效率比LabelImg高不少。Labelme适合做分割标注如果你后续想扩展到实例分割可以一开始就用它。2.3 数据增强针对航拍特性的定制策略通用数据增强翻转、旋转、色彩抖动在航拍场景下要慎用因为有些增强会破坏航拍图像的物理合理性。可以放心用的增强水平翻转、垂直翻转航拍俯视图没有明确的方向性翻转是安全的。90度整数倍旋转同理俯视图旋转90度依然合理。亮度、对比度微调模拟不同光照幅度控制在±20%以内。小幅度缩放模拟不同飞行高度缩放范围0.8-1.2倍。要谨慎用的增强任意角度旋转会产生非物理的倾斜除非你的实际场景确实有各种倾斜角度。大比例裁剪可能把目标裁得只剩一半破坏标注。马赛克增强MosaicYOLO训练常用但航拍场景下拼接会引入不自然的边界建议降低使用概率。航拍特有的增强思路我实测下来模拟运动模糊和模拟大气散射这两个增强对航拍场景特别有效。运动模糊用线性核卷积模拟大气散射用雾化效果模拟能让模型对无人机飞行中的成像退化更鲁棒。2.4 数据集划分与类别平衡的实操细节数据集划分看着简单其实坑不少。最基本的原则是按场景划分而不是随机划分。什么意思如果你把同一块操场、同一时段的图片随机分到训练集和验证集那验证集里的图片和训练集里的图片高度相似评估结果会虚高。正确做法是按采集批次、按时段、按场地划分保证验证集和训练集在分布上有真正的差异。类别平衡方面航拍人体检测通常只有person一个类别不存在多类别不平衡问题。但存在尺度不平衡问题——小目标数量往往远多于大目标。如果不管模型会偏向小目标因为小目标样本多大目标反而检测不好。我的做法是对大目标样本做上采样或者在损失函数里对不同尺度的目标加权。3. YOLO系列模型在航拍人体检测上的选型与改造3.1 YOLOv5到YOLOv8的实测对比我用YOLOv5s、YOLOv8s、YOLOv8m三个模型在同一份航拍校园数据集上做过完整对比结果挺有意思。模型输入尺寸mAP0.5小目标召回推理速度V100模型大小YOLOv5s6400.780.626.2ms14MBYOLOv8s6400.830.715.8ms22MBYOLOv8m6400.870.7611.5ms50MBYOLOv8s12800.890.8118.3ms22MB几个关键结论YOLOv8相比YOLOv5在同量级下确实有提升主要来自更好的特征融合和更优的损失函数设计。输入尺寸从640提到1280小目标召回提升非常明显0.71到0.81代价是推理速度慢了3倍多。如果你的场景对实时性要求不高1280输入是值得的。3.2 针对小目标的检测头与特征融合改造航拍人体检测的核心矛盾就是小目标。标准YOLO的检测头是在P3、P4、P5三个尺度上做的对应8、16、32倍下采样。对于20像素左右的小目标P38倍下采样上也就2-3个像素特征太弱。我的改造方案是增加P2检测头4倍下采样专门负责小目标。具体做法是在骨干网络里引出更浅层的特征和上采样后的深层特征做融合再接到一个额外的检测头上。这个改造会让模型参数量和计算量增加约15-20%但小目标召回能提升5-8个百分点很划算。另一个有效改造是改进特征融合方式。标准PANet用的是简单的concat我试过换成BiFPN的加权融合小目标检测有稳定提升。如果不想大改结构至少把neck部分的卷积核从3×3换成5×5增大感受野对小目标也有帮助。3.3 损失函数调优小目标加权的实践YOLOv8默认用的是CIoU损失加DFLDistribution Focal Loss。在航拍小目标场景下我做了两个调整。第一对小目标样本的定位损失加权。具体做法是根据目标面积计算权重面积越小权重越大权重范围控制在1.0-2.5之间。这样模型会更关注小目标的定位精度。第二调整DFL的回归范围。DFL默认的回归范围是16对于小目标来说这个范围偏大导致定位不够精细。我把它调到8小目标的定位精度有明显改善。这里要提醒一句损失函数的调整一定要配合验证集观察不能盲目调。我有一次把权重调得太激进结果大目标检测直接崩了mAP整体反而下降。3.4 输入分辨率与推理速度的权衡计算输入分辨率的选择本质上是精度和速度的权衡。我一般用这个公式做初步估算推理时间 ≈ 基准时间 × (新分辨率 / 基准分辨率)²比如YOLOv8s在640下是5.8ms提到1280就是5.8 × 4 23.2ms实测18.3ms比估算略好因为有些固定开销不随分辨率线性增长。实际选型时先明确你的速度要求。如果是实时巡检25fps以上单帧预算40ms那1280输入基本到极限了。如果是离线分析那直接上1280甚至1536精度优先。校园操场这种场景我一般推荐1280兼顾精度和可用性。4. 训练过程中的翻车现场与排查思路4.1 BN层崩溃航拍小目标训练的典型故障BNBatch Normalization崩溃是我在航拍小目标训练里遇到最多的故障没有之一。现象是训练到某个epochloss突然变成NaN或者BN层的running_mean/running_var变成异常值模型直接废掉。根本原因通常是batch内小目标样本太少统计量估计不稳定。航拍数据集里一张图可能只有几个小目标batch size又不敢开太大显存限制导致BN层每个batch看到的样本分布波动极大running统计量来回震荡最终崩掉。解决方案有几个我按推荐顺序排换用GroupNorm或者SyncBN。GroupNorm不依赖batch统计量稳定性最好但可能略微掉点。SyncBN在多卡场景下能扩大有效batch size效果也不错。冻结BN层的running统计量用预训练模型的统计量只训练affine参数。这个方案改动最小适合微调场景。梯度裁剪。把梯度范数限制在1.0以内能缓解但不能根治。降低学习率。BN崩溃有时是学习率太大导致的warmup阶段拉长一点有帮助。我现在的标准做法是微调场景直接冻结BN统计量从头训练场景用GroupNorm基本没再崩过。4.2 混淆矩阵不唯一多类别与单类别的坑热词里有个yolo混淆矩阵总合不唯一这个问题我也遇到过。混淆矩阵的每个格子是样本数理论上所有格子加起来应该等于验证集样本总数。但实际跑出来经常对不上原因通常有两个。一是置信度阈值和NMS的影响。YOLO输出的检测框经过置信度过滤和NMS之后有些真实目标被过滤掉了漏检有些预测框被合并了导致统计的预测总数和真实总数不一致。解决办法是在计算混淆矩阵时用较低的置信度阈值比如0.001并关闭NMS保证每个真实目标都有对应的预测。二是单类别场景下的显示问题。只有person一个类别时混淆矩阵就是2×2背景person有些工具会把背景类也算进去导致总数看起来不对。这个不是bug是显示逻辑问题理解清楚就行。4.3 漏检与误检的定向分析方法模型训完之后漏检和误检是必然存在的关键是要能定向分析出原因而不是盲目调参。我的分析流程是这样的第一步可视化错误样本。把漏检和误检的图片单独挑出来按错误类型分类。漏检通常集中在极小目标、严重遮挡、低对比度、运动模糊。误检通常集中在跑道线、树影、看台座椅、反光区域。第二步统计错误分布。按目标尺寸、按场景密度、按光照条件分别统计错误率。比如你发现漏检80%都发生在高空小目标上那方向就很明确了——要么加P2检测头要么提高输入分辨率。第三步针对性验证。针对分析出的原因做单变量实验。比如怀疑是分辨率不够就固定其他条件只改分辨率看漏检率变化。这样能确认因果关系而不是瞎猜。4.4 从训练曲线读出问题的经验训练曲线是最直接的问题信号源但很多人只看loss降没降忽略了其他信息。我分享几个自己总结的读曲线经验。train loss降但val loss不降甚至上升过拟合。航拍数据集通常不大过拟合很常见。对策是加数据增强、加正则化、早停。train loss和val loss都震荡学习率太大或者batch size太小。航拍小目标场景下batch size往往开不大这时候要配合更小的学习率和更长的warmup。mAP前期涨得快后期停滞可能是学习率衰减策略不合适。我一般用余弦退火比step衰减在航拍场景下表现更稳。小目标mAP远低于大目标mAP这是航拍场景的常态说明模型的小目标能力不足。对策就是前面说的加P2头、提分辨率、小目标加权。5. 部署落地时那些文档不会写的事5.1 模型导出与推理加速的实测选择训练完的模型要落地导出和加速是绕不开的。我实测过几种方案分享下结论。ONNX导出是最通用的YOLOv8官方支持很好。导出时注意opset版本建议用12或以上低版本对小目标的一些算子支持不好。导出后可以用onnxsim做简化能去掉一些冗余算子推理速度有5-10%提升。TensorRT在NVIDIA平台上加速效果最明显FP16精度下能比原生PyTorch快2-3倍。但要注意TensorRT对小目标的精度可能有轻微损失建议用FP16而不是INT8INT8在小目标上掉点比较明显。OpenVINO适合Intel平台CPU推理加速效果好。如果部署环境没有GPUOpenVINO是首选。RK3588等边缘设备热词里提到yolo rk3588这类国产边缘芯片现在用得很多。部署时要用厂商提供的转换工具把模型转成RKNN格式。注意RKNN对算子支持有限一些自定义的检测头结构可能要改写。5.2 边缘设备上的精度保持技巧边缘设备算力有限往往要牺牲精度换速度。我总结几个尽量保精度的技巧。输入分辨率不要降太狠。从1280降到640速度能快4倍但小目标召回可能掉20个点。如果实在要降建议降到960比640的精度损失小很多。量化时保护小目标。INT8量化对小目标伤害最大因为小目标的激活值范围小量化误差相对大。如果必须量化建议用感知训练量化QAT在训练时就模拟量化误差比训练后量化PTQ精度保持得好。后处理优化。NMS是后处理的大头边缘设备上可以用更高效的NMS实现或者降低NMS的IOU阈值来减少计算量。5.3 实际巡检场景的误报抑制模型上线后误报是最影响使用体验的。校园操场场景下我遇到的主要误报源和抑制方法如下。跑道线误报跑道白线在低分辨率下像躺倒的人。抑制方法是加一个后处理规则——检测框的长宽比如果超过某个阈值比如5:1且置信度不高就过滤掉。因为真实人体在航拍下长宽比一般不会太极端。树影误报树影形状不规则有时像人。这个比较难用规则抑制主要靠数据——在训练集里多放一些带树影的负样本让模型学会区分。看台座椅误报座椅排列整齐远看像坐着的人。同样靠负样本解决采集时专门拍一些空看台的图片作为负样本。时序一致性过滤如果是视频流可以用时序信息做过滤。真实的人体在连续帧里位置是连续变化的而误报往往是随机跳变的。加一个简单的跟踪逻辑只保留连续多帧都检测到的目标能过滤掉大部分随机误报。6. 数据集与模型的迭代维护思路6.1 难例挖掘与主动学习的落地模型上线不是终点而是迭代的起点。我一般用难例挖掘的思路持续优化。具体做法是模型上线后把置信度在0.3-0.6之间的检测结果不确定的和所有漏检、误检样本收集起来人工复核后加入训练集。这批难例对模型的提升往往比随机加数据大得多。主动学习是难例挖掘的进阶版。核心思想是让模型自己挑出最不确定的样本让人标注用最少的标注量获得最大的性能提升。航拍场景下我一般优先标注小目标密集、遮挡严重、光照极端的样本这些是模型的薄弱环节。6.2 数据集版本管理与可复现性数据集是要迭代的版本管理必须做好。我的做法是用DVC或者Git LFS管理数据集版本每次迭代打一个tag记录清楚这次加了什么数据、改了什么标注规则。可复现性方面训练配置、随机种子、环境依赖都要固定下来。我吃过亏——同一个配置跑两次结果不一样排查半天发现是数据加载的随机顺序没固定。现在我的训练脚本里随机种子、数据加载顺序、增强的随机参数全部固定保证结果可复现。6.3 从单场景到多场景的泛化扩展校园操场做熟了之后很自然会想扩展到其他场景——公园、广场、工地。这时候会发现直接拿校园模型去其他场景性能会掉不少。泛化扩展的关键是场景多样性。我的做法是新场景先采集少量数据几百张和校园数据混合训练让模型见过新场景的分布。混合比例大概是新场景30%、原场景70%这样既保留原场景性能又能适应新场景。另一个技巧是域自适应。如果新场景数据标注成本高可以先用无监督域自适应方法让模型在新场景的无标注数据上做自适应再少量标注微调。这个方法在航拍场景下效果不错因为航拍图像的域差异主要体现在光照和背景上自适应相对容易。7. 一些实测参数与配置参考7.1 一套跑通的训练配置把我自己跑通的一套配置贴出来基于YOLOv8s航拍校园人体检测供参考。# 训练配置 model: yolov8s.yaml # 加了P2检测头的版本 data: campus_aerial.yaml epochs: 300 batch: 16 imgsz: 1280 optimizer: AdamW lr0: 0.001 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 5 warmup_momentum: 0.8 box: 7.5 cls: 0.5 dfl: 1.5 patience: 50 close_mosaic: 20几个关键点说明imgsz用1280保证小目标close_mosaic在最后20个epoch关闭mosaic增强让模型在真实分布上收敛patience设50航拍场景收敛慢早停别设太激进。7.2 数据增强参数# 增强配置 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 degrees: 0.0 # 航拍不用任意旋转 translate: 0.1 scale: 0.5 shear: 0.0 perspective: 0.0 flipud: 0.5 # 俯视图上下翻转安全 fliplr: 0.5 mosaic: 0.5 # 降低mosaic概率 mixup: 0.0degrees设0是因为航拍俯视图任意旋转不物理mosaic降到0.5是因为拼接边界在航拍里不自然flipud开到0.5是航拍特有的地面场景一般不开。7.3 推理后处理参数# 推理配置 conf_thres 0.25 iou_thres 0.5 max_det 300 agnostic_nms False航拍密集场景下max_det要设大一点300是保守值人特别多时可以设500。iou_thres用0.5密集场景可以降到0.4减少框重叠。8. 写在最后的一点个人体会航拍校园人体检测这个方向我前后做了两年多最大的体会是数据质量决定上限模型调优决定下限。很多人一上来就折腾模型结构、损失函数但数据集本身如果采集不全面、标注不规范模型再怎么调也突破不了天花板。我见过太多项目模型换了一茬又一茬效果就是上不去最后发现问题出在数据集上——要么场景覆盖不全要么标注规则不统一。另一个体会是航拍场景没有银弹。小目标、遮挡、光照、背景干扰每个问题都要单独想办法指望一个模型结构改动解决所有问题是不现实的。务实的做法是先把数据做扎实再用工程手段逐个击破具体问题。最后分享一个小技巧如果你的航拍数据集标注成本太高可以先做半自动标注——用一个在通用数据上预训练的模型先跑一遍人工只修正错误的部分。这样标注效率能提升3-5倍而且模型越用越准形成正循环。我现在的项目基本都是这么起步的省下来的时间可以花在更难例的挖掘上。
返回列表