☰
航拍人体检测数据集构建与YOLO模型训练全流程实战
2026/9/28 6:44:25 网站建设 项目流程

1. 航拍人体检测到底在解决什么问题

1.1 从操场航拍到数据集构建的完整链路

第一次接触航拍人体检测这个方向,很多人以为就是拿无人机飞一圈拍点视频,然后丢进YOLO里跑训练就完事了。我当初也是这么想的,结果踩了整整两周的坑才把整个链路跑通。航拍人体检测和普通的地面人体检测完全不是一个难度级别,核心差异在于视角和尺度。

地面摄像头拍人,通常是平视或略微俯视,人的长宽比大概是1:3到1:4,特征非常明显——头、肩膀、躯干、四肢,YOLO在COCO数据集上预训练之后直接推理就能有不错的效果。但航拍视角下,尤其是操场这种场景,无人机通常在50到150米高度,俯角在30度到90度之间,人在画面里就变成了一个几十像素的小点,长宽比接近1:1,有时候连四肢都分不清,只能看到一个椭圆形的色块。这就导致直接用COCO预训练权重去推理,召回率低得可怜,我实测过,在100米高度拍的操场画面里,YOLOv8n的默认权重对人体的召回率不到35%。

所以航拍校园操场人体检测数据集的核心价值就体现出来了:它要解决的是小目标、密集场景、俯视视角这三个叠加难题。操场这个场景又特别典型——学生做操、上体育课、军训的时候,人员高度密集,穿着统一(比如军训服),背景相对干净但存在大量遮挡和阴影干扰。这种数据在通用数据集里几乎找不到,COCO里面航拍视角的人体样本占比不到2%,而且大多是稀疏场景。

这个数据集适合谁用?我总结下来是三类人:第一类是做校园安全监控的开发者,需要检测操场区域的人员密度和分布;第二类是做无人机视觉的研究者,想验证YOLO系列在小目标检测上的改进效果;第三类是计算机视觉课程的学生,需要一个有挑战性但又不是特别庞大的数据集来做课程项目。如果你属于这三类中的任何一类,这个数据集都值得花时间研究。

1.2 为什么选YOLO而不是Faster R-CNN或者SSD

这个问题我被问过很多次。航拍人体检测这个任务,YOLO系列几乎是默认选择,原因有三个层面。

第一是速度。航拍场景往往需要实时或准实时处理,无人机图传的帧率通常是30fps,如果检测模型单帧推理时间超过33ms,就没办法做实时叠加显示了。YOLOv8n在V100上推理一张640x640的图大概只要2到3ms,YOLOv8m大概8到10ms,而Faster R-CNN即使是最轻量的版本也要30ms以上。这个差距在航拍场景里是致命的。

第二是小目标检测能力。YOLOv8之后的版本在neck部分做了很多改进,比如PAN-FPN结构、多尺度特征融合,对小目标的召回率比SSD好很多。SSD虽然也是单阶段检测器,但它的anchor设计对航拍这种极端长宽比的目标不太友好。我实测过SSD300在同一个航拍数据集上的表现,mAP比YOLOv8低了将近12个百分点。

第三是生态和部署便利性。YOLO系列有完整的训练、验证、导出、部署工具链,从PyTorch到ONNX到TensorRT到RK3588,社区里都有现成的方案。你如果要做边缘部署,比如把模型跑到无人机的机载计算模块上,YOLO的量化工具链成熟度远超其他框架。这一点在实际项目中太重要了,我见过太多项目因为部署环节卡住而延期。

当然YOLO也不是没有缺点。航拍场景下,YOLO的正样本匹配策略有时候会出问题——因为人体太小,如果anchor的尺度设置不合理,很多真实目标会被判为负样本。这个问题在YOLOv5和YOLOv8里都存在,需要通过调整anchor或者用YOLOv8的TaskAlignedAssigner来缓解。后面我会详细讲怎么调。

2. 数据集构建的核心细节与实操要点

2.1 航拍数据采集的参数设置与场景覆盖

数据集的质量从采集那一刻就决定了。我见过太多人随便飞一圈拍几段视频,然后抽帧标注,最后训练出来的模型泛化能力极差。航拍人体检测数据集的采集有几个关键参数必须控制好。

飞行高度建议覆盖50米、80米、100米、120米四个档位。为什么是这四个?50米高度下人体在画面里大概占60到80像素,属于中等目标;100米高度下大概占30到40像素,属于小目标;120米高度下只有20到25像素,属于极小目标。如果你的数据集只覆盖一个高度,模型就只会在那个尺度上表现好。我建议每个高度至少采集30%的数据量,保证尺度多样性。

俯仰角度要覆盖30度、45度、60度、90度(正俯视)。操场场景里,正俯视(90度)是最常见的,因为无人机通常垂直向下拍。但30度到45度的斜俯视也很重要,因为实际部署时无人机不一定能保持正俯视。不同角度下人体的外观差异很大,正俯视看到的是头顶和肩膀,斜俯视能看到部分躯干和四肢。

光照条件要覆盖晴天顺光、晴天逆光、阴天、傍晚四种。逆光条件下人体会变成剪影,这对模型的鲁棒性是个考验。我实测过,如果训练集里没有逆光样本,模型在逆光场景下的召回率会下降20%以上。

场景多样性方面,操场本身就有很多变化:塑胶跑道、草坪、篮球场、看台区域。人员状态也要多样:站立、行走、跑步、做操、蹲下、躺下(比如军训时的匍匐)。穿着方面,校服、军训服、运动服、便装都要有。我甚至建议加入一些负样本,比如操场上的篮球架、旗杆、看台座椅,这些容易被误检为人体。

采集设备方面,我用的是大疆Mavic 3E,它的机械快门在高速飞行时不会有果冻效应,这一点对后续标注很重要。如果是用消费级无人机,建议飞行速度不要超过5m/s,否则画面模糊会导致标注困难。

2.2 标注规范与常见标注错误

标注是数据集构建里最耗时也最容易出错的环节。航拍人体检测的标注和普通人体检测有几个关键区别。

标注框的松紧度要统一。航拍视角下人体边界模糊,不同标注员对同一个人的框选范围可能差10到20个像素。我的做法是制定一个明确的规则:标注框要包含人体的可见部分,包括头部、肩膀、躯干,如果四肢可见也要包含。对于被遮挡的人体,只标注可见部分,不要脑补被遮挡的区域。这个规则听起来简单,但实际标注时争议很大,需要反复对齐。

最小标注尺寸要设定阈值。我建议低于8x8像素的人体不标注,因为这种目标即使标了,模型也学不到有效特征,反而会引入噪声。8x8到15x15像素的目标标注为“困难样本”,训练时可以选择忽略或者降低权重。

密集场景的处理是航拍标注的最大难点。操场做操时,人与人之间的间距可能只有几个像素,标注框会大量重叠。这时候要确保每个标注框对应一个独立的人体,不能合并标注。我见过有人把一排人标成一个大框,这是绝对错误的。如果实在分不清,可以用点标注辅助,先点出每个人体的中心点,再生成边界框。

常用的标注工具方面,LabelImg适合小规模标注,但它的界面在密集场景下操作效率很低。CVAT支持视频标注和插值,适合航拍视频抽帧后的连续标注。Roboflow的在线标注工具对密集小目标有放大镜功能,标注体验最好,但免费版有数量限制。我个人的组合是:CVAT做初标,Roboflow做复核和格式转换。

标注完成后必须做一致性检查。我通常会随机抽100张图,让两个标注员独立标注,然后计算IoU一致性。如果平均IoU低于0.85,说明标注规范需要重新对齐。这个步骤很花时间,但能避免后续训练时模型学到的边界模糊。

2.3 数据增强策略:针对航拍场景的定制方案

数据增强是提升航拍人体检测模型泛化能力的关键手段。但通用的增强策略(比如随机裁剪、颜色抖动)在航拍场景下需要调整参数,否则会适得其反。

Mosaic增强是YOLO系列默认开启的,它把四张图拼成一张。这个策略对小目标检测特别有效,因为它增加了单张图里的目标数量和尺度多样性。但航拍场景下要注意:Mosaic拼接后的图里,不同区域的光照和视角可能差异很大,模型可能会学到错误的上下文关系。我的做法是把Mosaic的概率从默认的1.0降到0.5,并且只在训练前期使用,后期关闭。

随机缩放的尺度范围要针对航拍调整。默认的缩放范围是0.5到1.5,但航拍人体本身就只有几十像素,再缩小到0.5倍就只剩十几像素了,标注框会变得极小。我建议把缩放范围调整为0.8到1.2,保证目标不会缩得太小。

旋转增强在航拍场景下特别有用,因为无人机可以朝任意方向飞行,人体在画面里的朝向是随机的。我通常设置旋转角度范围为-45度到45度,并且配合旋转后的边界框重计算。这里有个坑:很多增强库在旋转后不会自动调整边界框,导致标注框和实际目标错位。用Albumentations的时候要确保使用BboxParams并设置format='yolo'。

颜色抖动要谨慎使用。航拍场景下,操场的地面颜色(红色跑道、绿色草坪)是重要的上下文信息,过度抖动颜色会让模型忽略这些线索。我建议把亮度、对比度、饱和度的抖动范围控制在0.2以内,色调抖动控制在0.1以内。

Cutout和Random Erasing对航拍人体检测有帮助,因为实际场景中人体经常被树木、建筑、看台遮挡。但要注意遮挡区域不要太大,否则会把整个人体都盖住。我通常设置遮挡区域占图像面积的5%到15%。

还有一个航拍特有的增强:模拟无人机抖动。可以通过随机仿射变换(小角度的旋转+平移+缩放)来模拟。这个增强能提升模型对无人机姿态变化的鲁棒性。我实测下来,加入这个增强后,模型在测试集上的mAP提升了大概3个百分点。

3. 从零训练一个航拍人体检测模型

3.1 环境配置与数据集格式转换

训练环境这块,我推荐用PyTorch 2.0以上配合Ultralytics 8.x。Ultralytics的YOLOv8和YOLOv11封装得非常好,训练脚本几行就能跑起来。但航拍人体检测有一些特殊配置需要手动改。

先讲环境。CUDA版本建议11.8或12.1,cuDNN用8.9以上。Python用3.10,太新的版本有些依赖包还没适配。安装命令很简单:

pip install ultralytics pip install albumentations opencv-python

如果你要用V100训练,注意V100是Volta架构,不支持BF16,只能用FP16。在训练配置里要设置amp=True,但不要设置bf16=True。

数据集格式方面,YOLO用的是txt标注,每行格式是class_id x_center y_center width height,所有坐标都是归一化到0到1之间的。如果你的原始标注是VOC格式(xml),需要转换。我写了一个转换脚本,核心逻辑是:

import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, img_w, img_h, output_path): tree = ET.parse(xml_path) root = tree.getroot() lines = [] for obj in root.findall('object'): cls_name = obj.find('name').text if cls_name != 'person': continue bbox = obj.find('bndbox') xmin = float(bbox.find('xmin').text) ymin = float(bbox.find('ymin').text) xmax = float(bbox.find('xmax').text) ymax = float(bbox.find('ymax').text) 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 lines.append(f"0 {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}") with open(output_path, 'w') as f: f.write('\n'.join(lines))

转换完之后要检查一遍,我遇到过因为图像尺寸读错导致所有标注框偏移的情况。检查方法很简单:用OpenCV读一张图,把标注框画上去,肉眼看一下是否对齐。

数据集的目录结构要按YOLO的要求组织:

dataset/ images/ train/ val/ test/ labels/ train/ val/ test/

train/val/test的比例建议是7:2:1。如果数据量少于5000张,可以调整为8:1:1。注意划分时要按场景分,不能随机分。比如同一个视频抽出来的帧,不能一部分在train一部分在val,否则验证集就失去了意义。我的做法是按采集批次划分,每个批次内部再随机分。

3.2 模型选型与训练参数调优

模型选型这块,航拍人体检测我推荐从YOLOv8s或YOLOv8m开始。YOLOv8n虽然快,但参数量太少,小目标检测能力有限。YOLOv8l和YOLOv8x参数量太大,训练慢且容易过拟合。如果你要用最新的YOLOv11,YOLOv11m是个不错的平衡点。

训练参数方面,有几个关键项需要针对航拍场景调整:

输入尺寸:默认是640,但航拍人体太小,我建议用1280。输入尺寸翻倍后,小目标的像素数变成原来的4倍,检测效果提升明显。代价是显存占用增加,V100 32G跑YOLOv8m@1280大概占18G显存,可以接受。如果显存不够,可以用960作为折中。

Batch size:根据显存来定,V100 32G跑1280输入的话,YOLOv8m的batch size大概能到16。如果显存不够,可以用梯度累积来模拟大batch。

学习率:默认是0.01,但航拍数据集通常不大,我建议降到0.005,并且用余弦退火调度。学习率太大会导致训练不稳定,BN层容易崩溃。

Anchor设置:YOLOv8用的是无anchor的TaskAlignedAssigner,但YOLOv5还是基于anchor的。如果你用YOLOv5,需要用k-means重新聚类anchor。航拍人体的宽高比接近1:1,和COCO的anchor差异很大。聚类命令:

python utils/autoanchor.py --data dataset.yaml --img-size 1280

损失函数:YOLOv8默认用的是CIoU Loss + DFL + BCE分类损失。航拍场景下,CIoU对小目标的梯度可能不够,可以尝试换成SIoU或EIoU。我实测下来SIoU在航拍人体检测上比CIoU的mAP高1.5个百分点左右。

数据增强参数:在data.yaml同级目录建一个hyp.yaml,关键参数如下:

mosaic: 0.5 scale: 0.2 flipud: 0.1 fliplr: 0.5 hsv_h: 0.01 hsv_s: 0.2 hsv_v: 0.2 degrees: 45.0 translate: 0.1

训练命令:

yolo detect train data=dataset.yaml model=yolov8m.pt epochs=200 imgsz=1280 batch=16 lr0=0.005 cos_lr=True patience=50

训练过程中要盯着混淆矩阵和PR曲线。航拍人体检测最常见的混淆是“人体”和“背景”的混淆,也就是漏检。如果混淆矩阵显示大量人体被预测为背景,说明模型对小目标的特征学习不足,需要增大输入尺寸或者增加正样本权重。

3.3 训练过程中的BN崩溃与梯度异常排查

训练航拍人体检测模型时,BN层崩溃是个高频问题。表现是loss突然变成NaN,或者BN的running_mean和running_var变成异常值。我遇到过好几次,排查下来主要有三个原因。

第一个原因是学习率太大。BN层对学习率很敏感,尤其是batch size小的时候。如果你用batch size 8以下,学习率超过0.01就很容易崩。解决办法是降低学习率到0.001到0.005,或者用梯度裁剪,设置max_norm=10.0。

第二个原因是数据里有异常样本。比如标注框的宽高为0,或者坐标超出0到1的范围。这种样本会导致loss计算时出现除零或log(0)。训练前一定要做数据清洗,检查所有标注文件:

import os def check_labels(label_dir): for fname in os.listdir(label_dir): if not fname.endswith('.txt'): continue with open(os.path.join(label_dir, fname)) as f: for i, line in enumerate(f): parts = line.strip().split() if len(parts) != 5: print(f"{fname} line {i}: 格式错误") continue cls, x, y, w, h = map(float, parts) if w <= 0 or h <= 0: print(f"{fname} line {i}: 宽高为0") if not (0 <= x <= 1 and 0 <= y <= 1): print(f"{fname} line {i}: 坐标越界")

第三个原因是混合精度训练。AMP在V100上用的是FP16,FP16的动态范围小,BN的方差计算容易溢出。如果遇到BN崩溃,可以先关掉AMP(amp=False)跑几个epoch,确认模型能正常收敛后再开启。

还有一个隐蔽的原因:预训练权重不匹配。如果你用的是COCO预训练的YOLOv8m,但你的数据集只有1类(person),加载权重时分类头的维度会不匹配。Ultralytics会自动处理,但如果你手动加载权重,可能会出错。建议直接用model=yolov8m.pt让框架自动处理。

4. 模型评估与部署实操

4.1 航拍人体检测的评估指标解读

训练完之后,评估指标不能只看mAP。航拍人体检测有几个特殊的评估维度需要关注。

mAP@0.5是基础指标,但它对航拍小目标不够敏感。因为小目标的IoU本身就难算高,一个偏移5像素的预测框,在100像素的大目标上IoU还有0.9,但在20像素的小目标上IoU可能只有0.6。所以我建议同时看mAP@0.5:0.95和mAP@0.75。如果mAP@0.5很高但mAP@0.75很低,说明模型的定位精度不够,需要调整回归损失。

召回率在航拍人体检测里比精确率更重要。因为漏检一个人可能意味着安全监控的盲区,而误检一个背景物体只是多一个假警报。我通常要求召回率在0.9以上,精确率可以放宽到0.7。

尺度分组评估是航拍场景特有的。把测试集按人体像素尺寸分成三组:小(小于32x32)、中(32x32到96x96)、大(大于96x96),分别计算mAP。如果小目标的mAP明显低于中大目标,说明模型的小目标检测能力不足,需要增大输入尺寸或者用更密集的特征金字塔。

混淆矩阵要重点看“person vs background”的误分类。如果大量person被预测为background,说明正样本匹配策略有问题。可以尝试降低box损失的权重,或者用Focal Loss来缓解正负样本不平衡。

我实测下来,一个训练良好的YOLOv8m在航拍操场人体检测数据集上的表现大概是:mAP@0.5在0.85到0.92之间,mAP@0.5:0.95在0.55到0.65之间,召回率在0.88到0.94之间。如果你的指标明显低于这个范围,说明训练配置或者数据质量有问题。

4.2 模型导出与边缘部署要点

训练完的PyTorch模型要部署到实际设备上,通常需要导出成ONNX或TensorRT。航拍场景的部署目标可能是机载计算模块(比如Jetson Orin)、地面站(比如RK3588)或者云端服务器。

导出ONNX的命令:

yolo export model=best.pt format=onnx imgsz=1280 opset=12 simplify=True

注意imgsz要和训练时一致,否则检测效果会下降。simplify=True会做图优化,去掉冗余算子。

导出TensorRT:

yolo export model=best.pt format=engine imgsz=1280 half=True device=0

half=True表示用FP16量化,在Jetson和V100上都能用。但要注意,FP16量化后小目标的检测精度可能会下降1到2个百分点。如果对精度要求高,可以用INT8量化,但需要准备校准集。

RK3588部署的话,需要先把ONNX转成RKNN格式。Rockchip提供了rknn-toolkit2工具。转换时要注意量化方式,航拍人体检测建议用dynamic_fixed_point而不是asymmetric_quantized,因为前者的精度损失更小。转换脚本的核心参数:

from rknn.api import RKNN rknn = RKNN() rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform='rk3588') rknn.load_onnx(model='best.onnx') rknn.build(do_quantization=True, dataset='calibration.txt') rknn.export_rknn('best.rknn')

部署时还有一个关键点:后处理。YOLO的输出是原始的特征图,需要做NMS才能得到最终的检测框。在边缘设备上,NMS的计算量可能比模型推理还大。我建议用硬件加速的NMS,比如TensorRT的EfficientNMS插件,或者RKNN的NPU加速NMS。如果都没有,可以用CPU做NMS,但要注意优化,比如用OpenMP并行。

4.3 实际部署中的误检漏检排查

模型部署到实际场景后,误检和漏检是必然出现的。我整理了一个排查清单,按优先级排序。

漏检排查:首先看漏检的人体尺寸。如果都是小目标,说明输入分辨率不够,需要增大imgsz。如果各种尺寸都有漏检,说明模型的召回率本身就不够,需要重新训练,增加正样本权重或者用Focal Loss。如果漏检集中在特定场景(比如逆光、密集人群),说明训练集覆盖不够,需要补充对应场景的数据。

误检排查:航拍场景最常见的误检是树木、阴影、地面纹理被误判为人体。排查方法是把误检的图拿出来,看模型的置信度分布。如果置信度在0.3到0.5之间,说明模型不确定,可以通过提高置信度阈值来过滤。如果置信度很高(大于0.7),说明模型学到了错误的特征,需要加入负样本重新训练。

密集场景漏检是航拍人体检测的顽疾。当人与人之间间距小于10像素时,NMS可能会把相邻的人体框合并。解决办法是调低NMS的IoU阈值,从默认的0.45降到0.3。但这样会增加误检,需要权衡。另一个办法是用Soft-NMS,它不会直接删除重叠框,而是降低置信度,对密集场景更友好。

尺度不一致问题:如果模型在50米高度表现好,但在100米高度表现差,说明模型对尺度变化不够鲁棒。解决办法是在训练时加入更多的多尺度样本,或者用Test Time Augmentation(TTA),在推理时对同一张图做多尺度预测再融合。TTA能提升2到3个百分点的mAP,但推理时间会翻倍。

5. 航拍人体检测的进阶优化方向

5.1 小目标检测的针对性改进

航拍人体检测的核心难点就是小目标。除了增大输入尺寸,还有几个针对性的改进方向。

高分辨率特征图:YOLOv8的P3特征图是80x80(输入640时),对应8倍下采样。对于20像素的人体,在P3上只有2.5个像素,特征太弱。解决办法是增加一个P2特征图,对应4倍下采样,160x160。这样20像素的人体在P2上有5个像素,特征更丰富。Ultralytics支持通过修改模型配置来增加P2层,但会增加计算量。

注意力机制:在neck部分加入CBAM或ECA注意力模块,能让模型更关注小目标区域。我实测过,在YOLOv8m的neck里加入ECA,小目标mAP提升了2.1个百分点,推理时间只增加了3%。ECA的实现很简单:

import torch import torch.nn as nn class ECA(nn.Module): def __init__(self, channels, k_size=3): super().__init__() self.avg_pool = nn.AdaptiveAvgPool2d(1) self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding=(k_size - 1) // 2, bias=False) self.sigmoid = nn.Sigmoid() def forward(self, x): y = self.avg_pool(x) y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1) y = self.sigmoid(y) return x * y.expand_as(x)

切片推理:对于超大分辨率的航拍图(比如4K),直接缩放到1280会丢失小目标。SAHI(Slicing Aided Hyper Inference)的思路是把大图切成多个小图分别推理,再合并结果。这个方法对小目标检测提升明显,但推理时间会成倍增加。适合对实时性要求不高的场景。

损失函数改进:小目标的回归损失可以用NWD(Normalized Wasserstein Distance)代替IoU。因为小目标的IoU对位置偏移太敏感,NWD用高斯分布建模边界框,对小幅偏移更鲁棒。我实测下来,NWD在小目标上的mAP比CIoU高3到4个百分点。

5.2 多模态与多任务扩展

航拍人体检测可以和其他任务结合,提升整体价值。

人体检测+密度估计:在检测的同时估计人群密度,对校园安全监控很有用。可以在YOLO的backbone后面接一个密度回归头,用CSRNet的架构。训练时用密度图的MSE损失和检测损失联合优化。

人体检测+姿态估计:航拍视角下姿态估计很难,但可以估计人体的朝向(头朝哪个方向)。这对分析人群流动方向有帮助。可以在YOLO的检测头上加一个朝向分类分支,输出8个方向类别。

红外+可见光多模态:如果无人机同时搭载可见光和红外相机,可以把两个模态的图像融合后输入YOLO。红外图像在夜间和逆光条件下对人物检测更鲁棒。融合方式可以是简单的通道拼接,也可以用注意力机制做自适应融合。

时序信息利用:航拍视频是连续的,可以利用帧间信息来提升检测稳定性。简单的方法是对连续帧的检测结果做跟踪(比如ByteTrack),用跟踪结果来填补漏检。复杂的方法是用视频目标检测架构,比如在YOLO的backbone里加入时序注意力模块。

5.3 数据集迭代与持续优化

数据集不是一次构建就完事的,需要根据模型的表现持续迭代。

主动学习:训练一个初始模型后,用它去推理未标注的数据,把置信度低或者检测结果异常的样本挑出来,优先标注。这样能用最少的标注量获得最大的性能提升。我通常迭代3到4轮,每轮标注500到1000张,mAP能提升5到8个百分点。

困难样本挖掘:把验证集里漏检和误检的样本单独拿出来,分析它们的共同特征。如果漏检集中在某个特定场景(比如树荫下),就针对性地补充这个场景的数据。如果误检集中在某个特定物体(比如篮球架),就加入这个物体的负样本。

标注质量复核:随着模型性能提升,标注错误的影响会越来越大。当mAP超过0.85后,标注噪声可能成为瓶颈。这时候需要做一轮全面的标注复核,用模型预测结果和人工标注对比,找出不一致的样本重新标注。

版本管理:数据集要有版本号,每次迭代记录变更内容。我通常用v1.0、v1.1这样的格式,每次变更写一个CHANGELOG.md,记录新增了多少张图、修改了多少标注、模型指标变化。这样出问题的时候可以回溯。

6. 实操心得与避坑指南

6.1 训练效率提升的五个技巧

航拍人体检测数据集通常不大,但训练起来很慢,因为输入尺寸大。我总结了五个提升训练效率的技巧。

第一,用缓存。Ultralytics支持cache=True,把解码后的图像缓存到内存或磁盘。如果数据集小于50G,建议用cache='ram',训练速度能提升30%以上。如果内存不够,用cache='disk'。

第二,用多GPU训练。如果你有多张V100,用device=0,1,2,3开启DDP训练。注意DDP模式下batch size是每张卡的batch size,总batch size要乘以卡数。学习率也要相应调整,通常按线性缩放。

第三,冻结backbone。训练前期可以冻结backbone,只训练neck和head。这样能加快收敛,减少显存占用。Ultralytics支持freeze=10,表示冻结前10层。训练10个epoch后再解冻。

第四,用更小的验证频率。默认每个epoch都做验证,但验证很耗时。可以设置val_period=5,每5个epoch验证一次。但要注意,这样可能会错过最佳模型,建议同时开启save_period=5。

第五,用混合精度。AMP能减少显存占用并加速训练,但要注意BN崩溃问题。如果稳定,AMP能提升20%到30%的训练速度。

6.2 常见问题速查表

问题现象可能原因排查方法解决方案
loss变成NaN学习率太大看loss曲线降低lr到0.001
BN层崩溃batch size太小看BN的running_var增大batch或降低lr
小目标漏检严重输入尺寸不够按尺度分组评估增大imgsz到1280
密集场景漏检NMS阈值太高看NMS后的框数降低NMS IoU到0.3
误检树木/阴影负样本不足看误检样本加入负样本重训
验证集mAP波动大验证集太小看每轮mAP增大验证集或交叉验证
训练速度慢数据加载瓶颈看GPU利用率开启cache和多worker
模型过拟合数据量太少看train/val loss差距增加增强或减少参数量

6.3 我踩过的三个大坑

第一个坑是标注框的坐标系搞错。有一次我用了一个开源标注工具,它导出的坐标是左上角和右下角的绝对像素值,但我以为是归一化的中心点坐标,直接拿去训练。结果模型完全学不到东西,mAP一直是0.01。排查了一整天,最后画了个框才看出来。教训是:拿到任何标注数据,第一件事是可视化检查。

第二个坑是验证集泄露。我一开始是按随机划分做train/val split,结果同一个视频的相邻帧被分到了train和val。因为相邻帧几乎一样,模型在验证集上的表现虚高,实际部署时性能差很多。后来改成按视频划分,验证集mAP降了5个百分点,但更真实了。

第三个坑是过度依赖预训练权重。COCO预训练的YOLO在航拍人体上直接推理效果很差,我一开始以为是模型不行,换了好几个模型都没用。后来才意识到是域差异太大,必须用航拍数据微调。微调之后,同样的模型mAP从0.35提升到了0.88。所以千万不要跳过微调这一步。

6.4 后续扩展方向

这个数据集和模型还可以往几个方向扩展。一是多类别检测,除了人体,还可以检测自行车、篮球、旗杆等操场常见物体,做成一个多类别航拍检测数据集。二是行为识别,在检测的基础上判断人体是在站立、跑步还是做操,这需要时序信息。三是三维定位,结合无人机的GPS和姿态信息,把检测框反投影到地面坐标系,得到每个人的实际位置。这个在校园安全监控里很有价值。

我个人在实际操作中的体会是,航拍人体检测这个方向,数据质量比模型结构重要得多。你花一周时间调模型结构,可能只提升1个百分点;但花一周时间补充困难场景的数据,可能提升5个百分点。所以如果你的模型效果不理想,先别急着改网络,去看看数据里缺什么。

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

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

立即咨询