☰
航拍操场人体检测:从数据集构建到YOLO训练全流程解析
2026/9/29 11:30:12 网站建设 项目流程

航拍校园操场上做人流统计或者人体检测,和平时在地面监控里做行人检测,根本是两个世界。你从无人机的高度往下看,操场上的学生就是几十个像素的小点,脚下拖着长长短短的阴影,塑胶跑道的标线、草坪纹理、篮球架的影子全是干扰源。这个项目做的事情,就是从零构建一套专门针对航拍校园操场场景的人体检测数据集,并且用YOLO系列模型跑通从标注、训练、评估到部署的完整流程。

这套东西能干什么用,其实很实在:体育课出勤快速点名、课间操集合人数统计、操场活动安全预警、大型集会人流密度评估,这些需求落到实际就都需要“从天上认出人”的能力。想做无人机视觉的初学者、正在被小目标检测折磨的工程师、或者准备自己攒数据集训练YOLO的学生,这篇里讲的采集参数、标注规则、训练参数和踩坑记录,你都能直接用上。

1. 项目定位:先想清楚你要检测的到底是什么

1.1 航拍视角和普通视角的人体检测根本不是一回事

地面摄像头拍到的人是“立体”的——有清晰的轮廓、可辨识的腿和手臂、靠近摄像头时甚至能看到人脸和衣服颜色。航拍完全相反,绝大多数情况你看到的是人的头顶和肩膀,从正上方或者大角度俯视,人体特征几乎全部丢失,轮廓只剩一个椭圆或者一个点。

我说个直观数字。用大疆这类常见消费级无人机,镜头等效焦距约24mm,视场角横向大概77°,悬停在100米高度垂直向下拍摄时,画面底部覆盖的地面宽度大约是158米。如果用4K分辨率3840像素宽度来算,每米大约对应24个像素,一个1.7米的学生在画面里只有不到40像素高。这个尺寸在目标检测里属于妥妥的“小目标”。飞到50米高度,目标能到80到120像素,稍微好一点,但依然比地面监控里的行人小一个量级。

小目标带来两个连锁问题:

  • 特征不足。40像素的框里几乎看不到纹理细节,网络只能靠颜色对比、轮廓形状、周围环境上下文来猜测这是不是人。
  • 标注不一致放大。一个目标70像素,有人标60,有人标80,差一两个像素在损失函数里就是好几个百分点的梯度波动,直接带偏边界框回归。

所以这个项目表面上是在“检测人”,实际上是在解决“如何在低分辨率、强纹理干扰、任意朝向的条件下,把一个个小信号从复杂背景里稳定提取出来”的问题。想清楚这一点,后面所有参数选择就都有依据了。

1.2 校园操场场景的特殊性

操场不是随机的空地,它有自己的视觉模式。这些模式既是训练的难点,也是可以利用的先验信息。

首先是背景强纹理。塑胶跑道的弧形标线、草坪的色块过渡、足球场禁区白线,从高处看就是大量高对比度的几何边缘。人在这种背景上如果不能与周围形成足够大的颜色差,模型很容易漏检。反过来,如果人穿着和跑道颜色接近的衣服(比如红色运动服落在红色跑道上),对比度极低,这直接决定了训练数据里必须覆盖不同颜色服装和不同背景组合。

其次是遮挡和聚集。操场教学场景里,学生经常三五成群站在树下、器材区旁边,或者密集聚集成队列。树荫遮挡、人群互相遮挡,在航拍视角下尤其严重。从上往下看,密集队形里前后两个人几乎是挨在一起的,框挨着框,NMS一压就得丢人。

第三个是光影变化剧烈。上午十点的阳光照在跑道上,人的影子会长出本体几倍的长度,影子本身在检测器眼里就是一个深色的椭圆目标。这种“影子误检”如果不靠数据去压,模型会学到“有个深色块那就是人”,一旦阴天或黄昏,性能直接崩掉。

还有个容易被忽略的点:操场是动态多场景的。同样的操场,运动会时临时搭了舞台和遮阳棚,体育课时摆了一排跨栏架,无人机巡航的航线稍微偏移,画面背景结构就完全变了。数据集如果只拍了一种状态,模型出了实验室就废。后面我会说怎么用最少的时间覆盖这些变化。

2. 数据集的构建:从无人机航拍到TXT标注文件

2.1 采集设备与航拍参数

我自己常用的是大疆Mini系列或Mavic系列,这类机器画质够、便携、飞行稳定性好,对数据采集这种需要反复起降的场景非常合适。如果你手头是御3这种带长焦的更好,但主摄拍的数据其实就够用,长焦在低空反而因为视角太窄不适合做覆盖式采集。

航拍参数不要凭感觉来,我建议按下面这套基线走:

  • 视频分辨率:4K30帧录制,不要用1080P,后面抽帧还有裁剪的余地。
  • 飞行高度:30米、50米、80米三个高度各飞一遍。30米数据负责“中等目标”尺度,50米是主战场景,80米以上专门给检测器喂小目标样本。
  • 云台角度:垂直90°拍一组,40°到60°斜视拍一组。纯俯视图训练出来的模型在斜视视角下会很脆弱,两种角度混合才能让模型学会泛化。
  • 航线规划:用“网格航线”平铺飞一遍整个操场,再用“环绕航线”沿着操场边界绕两圈。网格保证覆盖均匀,环绕补充大量不同朝向和透视变化的目标。
  • 重叠率:如果直接用拍照模式,相邻照片重叠率控制在60%到80%,后面不容易出现同一目标在不同照片里姿态差异过大的情况。

采集时间尽量分散。早上七点半、上午十点、下午四点、阴天、晴天各来两组。我知道很多人嫌麻烦,但航拍数据最值钱的就是光影多样性,这一条直接影响模型在真实巡航时的误检率。

2.2 从视频到干净训练图的抽帧策略

录像之后你手上是一段一段的长视频,直接全量抽帧不行——相邻帧几乎一模一样,喂进去就是一堆高度相关的重复样本,训练会向着冗余数据过拟合。

我的做法是两步:

  • 第一步,按时间均匀抽帧,每5到10秒抽一帧,先把数据量降下来。
  • 第二步,人工或脚本粗筛,把画面模糊的、无人机转弯时拖影明显的、大范围遮挡的帧删掉。航拍视频里无人机转弯瞬间画面倾斜加运动模糊的情况非常多,这种帧留在数据集里就是纯噪声。

还有一个很多人忽略的操作:给每一个视频片段建立一个“场景分组标签”,比如“上午晴天-南侧看台-50米”“傍晚阴天-跑道弯道-30米”。后面划分训练集和验证集时,按这个分组去切,而不是按随机帧去切,这能避免同一个时间段临近帧同时出现在训练集和验证集里造成的“数据泄漏”——一旦泄漏,验证集指标会虚高,换个环境直接打回原形。

抽完帧之后,原始图统一做一次轻量处理:如果原图是4K,首轮实验先缩到1920×1080存一份用于快速迭代,同时保留一份原分辨率用于最终训练时吃细节。不要来回压缩JPG,保存成PNG或者高质量JPG,标注和训练都对图像质量敏感。

2.3 标注规范与YOLO格式转换

标注工具我建议X-AnyLabeling,免费、支持YOLO格式直接导出,而且内置了SAM辅助标注模型,航拍图里人虽然小,但用SAM粗分割再转成框,效率能比纯手标高一倍。Roboflow也好用但涉及上传,很多团队的数据敏感,离线工具更放心。

这一行有个铁律:格式是小事,规范是大事。标注前先定规则,全部标完再回头统一检查。我的标注规范是这样写的:

  • 类别只有一类person,不做“站着的人”“躺着的人”“跑步的人”这种子类拆分,除非你的下游任务明确需要,否则拆分只会稀释样本量。
  • 目标在画面中高度小于15像素、或者可见面积不足40%的,不标。低于这个尺寸即便标了,网络也学不出来,反而制造大量低质量正样本。
  • 有遮挡的目标照标,但严格用“可见区域的最小外接轴对齐矩形”。不要脑补被树挡住的半边身体,标注不能靠想象力。
  • 框要紧贴目标。航拍下人很小,标框时稍微松一点就多出10%的背景,这个误差在损失函数里会被放大,宁可紧一点也不要留白太多。
  • 影子不标。影子再像人也绝对不能标成人,否则网络把“深色长条”学成特征,阴天就翻车。
  • 队列中密集的人挨个标。哪怕两个框重叠90%,也要各自标自己的框,这是人流统计类任务的基本前提。

YOLO格式本身的转换很简单,标注工具都能直接导出。格式就是一行一个目标:类别ID、归一化的中心点x、中心点y、宽度w、高度h,四个坐标值都在0到1之间。比如一张1080P的图里,某个人中心在像素坐标(500, 300),宽80,高120,那对应的标签就是 0 0.463 0.278 0.074 0.111,分母是图片宽度和高度。如果自己写转换脚本,千万注意归一化是按整图尺寸算的,不是按标注框的裁剪尺寸算。

2.4 数据质量管控:比数量更重要的抽检

很多人以为数据集越大越好,航拍场景真不是。我见过三千张图的数据集因为标注漏一半,效果不如认真标的一千张。质量管控我建议按这个比例做:

  • 总量:2000到4000张图是一个比较舒服的区间,再往上边际收益递减,除非你要刷比赛指标。
  • 难度分布:简单目标(大目标、清晰无遮挡、晴天顺光)占60%,中等(30到60像素、轻微遮挡)占30%,困难(小于30像素、强阴影、密集人群)占10%。
  • 负样本:专门采100到200张完全没人的操场空镜,晴天和阴天各半。很多人训练时从不放负样本,模型推理到没有人的操场时就会开始凭空报检,负样本是压误检最直接的手段。
  • 抽检比例:标注完抽10%到20%的图做二遍标注,计算两个标注结果的IoU,低于0.85的框全部退回修改。这个环节必须人工盯,脚本只能帮你筛出候选。

我踩过一个很深的坑:第一版数据集全部在中午前后采集,阳光顶头照,人几乎没有影子,训练出来的模型mAP很高,但拿到下午四点实际巡航时影子一出来,准确率直接掉十个点。后来加入清晨和傍晚的数据,把带长影子的正样本喂进去,模型才学会区分“人”和“人的影子”。这类问题在实验室里根本暴露不出来,只能靠多样化的数据分布去扛。

3. 训练阶段的配置与参数选择

3.1 数据集划分:按拍摄片段切,千万别按帧随机切

划分训练集、验证集、测试集的标准做法是按“拍摄片段”切,也就是前面提到的场景分组。一个视频片段的所有帧只能属于一个集合,绝对不能随机打散到三个集合里。

原因前面提过:相邻帧相似度太高,随机切会让验证集出现大量训练集的“近亲”,指标虚高。你辛辛苦苦调参,验证集mAP0.92,以为模型很强,结果拿到新操场上一测只有0.4,多半是这里出了问题。比例上我习惯70%训练、15%验证、15%测试。测试集单独留一组完全没参与过调参的拍摄片段,最后测一次就行,别反复拿测试集调参。

注意,校园操场场景里“时间段”比“光线角度”更容易造成分布漂移。比如同一片操场,早晨和傍晚人群运动模式完全不同,下午放学后可能空无一人。如果你把训练集全安排在上午,验证集全是傍晚,那你看模型mAP波动大的时候,很难分清楚到底是模型问题还是数据分布问题。所以划分时每种时间段都尽量在训练集和验证集里各留一些。

3.2 数据增强:航拍场景的正确打开方式

YOLO自带的数据增强管线在通用目标检测上不错,但直接用在场上有几个地方要调。

先说Mosaic。YOLO默认开启Mosaic拼接四张图,这个增强对小目标有利,因为相当于把四方图缩到一半尺寸,目标变小了,变相让模型适应小尺度。但航拍数据本身目标就小,Mosaic拼完很多目标缩到十几个像素,成了无效正样本。我的做法是:Mosaic概率开到0.5,同时把mosaic拼图后的缩放限制放宽,不让目标缩得太狠。

再说旋转。地面行人检测一般旋转增强到±30°就差不多了,但航拍不一样,无人机的朝向、航线的走向让目标在画面里可以出现在任意角度,头顶朝上朝下朝左朝右都有。这里旋转增强可以开到90°的倍数甚至任意角度(YOLO里旋转增强是随机角度),能大幅提升模型对目标朝向的鲁棒性。但要注意,旋转会产生黑色填充区域,增强后的图会有一部分是纯黑补边,这部分是不能被当作背景学进去的,所以YOLO在做旋转增强时通常会配合仿射变换把图填充撑满,这个细节你不用改代码,但要意识到它有这个行为。

水平翻转和垂直翻转可以全开。HSV颜色增强我开到0.02到0.04的幅度,航拍图受天气影响颜色偏移严重,适度抖动有好处,但别开太大——操场跑道的红色、草皮的绿色都是强特征,颜色学飞了反而坏事。

最后是尺度变化。这个对航拍尤其关键。飞行高度不同,目标大小跨了一个量级。我建议在增强里允许0.5到1.5倍的随机缩放,让网络见过不同高度下的目标尺度分布。如果接下来你想用大图训练,增广里的随机缩放还能帮忙缓解大图上样本量不足的问题。

3.3 YOLO训练参数详解:照着这份配置改

模型版本的选择上,YOLOv8和YOLOv11我都跑过。YOLOv8生态成熟、文档多、踩坑资料全,适合这个项目;YOLOv11在推理效率上有提升,部署时值得考虑。但模型架构对航拍小目标的提升远不如输入分辨率提升来得直接,入门先用YOLOv8n或者YOLOv8s把流程跑通,后面再升级不迟。

核心训练参数我给一套基线配置,直接抄:

参数推荐值说明
imgsz640起步,最终训练用1280分辨率提升对小目标收益巨大,但显存会翻四倍
epochs150到300,patience设30到50看验证集mAP停滞就早停
batch24GB显存用16,8GB用4到8batch太小影响BN统计量,别小于4
optimizerAdamW,lr0=0.001,lrf=0.01比SGD在调参上更省心
预训练权重用COCO预训练航拍场景虽然陌生,但COCO的底层特征提取能力仍然可迁移
冻结层前10层冻结50个epoch再解冻避免前期梯度把底层特征冲坏
类别数1只有person
正样本分配YOLO默认,不用调单类任务默认分配策略已经够用

这里重点说imgsz的选择。640分辨率下训练快、显存省,但40像素的小目标在640图里就是十几个像素,严重欠拟合。我的经验是:第一轮用640快速验证数据质量,如果mAP50能到0.8说明标注和增强没问题,再用1280分辨率做最终训练。1280下目标边长翻倍,有效信息量大幅提升,小目标召回率能明显改善。代价是显存和训练时间都要等比例增加,需要自己权衡。

还有两个容易被忽略的配置:workers上面表没写,设成CPU核心数的一半就行,注意不要在Windows下开太多worker,会频繁报DataLoader的坑;存验证集图片和混淆矩阵的功能开着,每个epoch结束看一眼验证集可视化结果,比盯终端里的loss数字有价值得多。

4. 结果评估与性能分析

4.1 指标怎么读:mAP50和mAP50-95要分开看

航拍小目标检测项目里,mAP50是底线指标,mAP50-95才是试金石。mAP50只要求预测框和真值框IoU超过0.5就算检对,对目标定位精度要求很低;mAP50-95是多个IoU阈值平均,从0.5到0.95每踩一个阶梯都算一次,对框的回归质量极其苛刻。

我的单类数据集跑完之后,结果大概长这样(这个水平已经算可用):

指标1280分辨率训练640分辨率训练
mAP500.910.87
mAP50-950.680.57
Precision0.890.85
Recall0.870.80

你看mAP50差得不多,但mAP50-95差距就拉开来了,这就是分辨率对小目标定位精度的影响。如果你的mAP50-95低于0.5,大概率问题出在:标注框不齐、目标太小、或者增强参数把正样本搞废了。

除了mAP,还要看每个类别的PR曲线。单类模型直接看整体PR曲线,选择置信度阈值时要在“宁可错杀十个不放走一个”和“宁可漏检也不误报”之间划线。做人数统计任务,我通常把置信度阈值设在0.3到0.4,减少漏检优先;做安全告警任务就提到0.5以上,减少误报噪音。

4.2 误检漏检案例分析

训练完别急着宣布成功,把验证集里预测结果可视化图翻一遍,按错误类型归类。航拍操场场景最常见的几类错误:

  • 漏检密集队形中心的人。队列里外圈的人清楚,中心的人互相遮挡严重,模型只检到最外侧一圈。这种情况靠增加遮挡样本、降低NMS阈值有一定帮助,但根源是数据里密集场景太少,回去补拍。
  • 误检深色轮胎和圆斑。操场边停的车、篮球架的黑色阴影基座,从上往下看都是深色圆块,极易被当成人的头顶。这类误检的修正方式是加负样本,不标这些目标,让模型学到“深色圆块不等于人”。
  • 误检操场上的涂鸦和图案。有些操场画了巨大的队形站位点或者数字,在高处看自带“人形轮廓感”。这种最头疼,只能通过增强视觉上下文、提高置信度阈值来压制。
  • 漏检与背景同色系的人。穿白色运动服的人跑在白色划线区旁边,特征接近背景,漏检率高。这个没有完美的解法,只能靠数据里多覆盖这类低对比度组合。

再补充一个细节:每轮训练结束,把置信度阈值从0.1到0.9扫一遍,画出F1曲线,找到F1峰值对应的阈值。这个阈值才是你这个模型在当前场景里的最优工作点,而不是拍脑袋选个0.5。

5. 常见问题与排查实录

5.1 小目标检测不理想的常见原因

如果你训练半天发现小目标(30像素以下)基本检不出来,先别急着换模型,按下面顺序排查:

  • 标注有没有把小于15像素的目标都丢了?如果训练集里最小目标是40像素,那模型没见过小目标,推理时当然不会检。标注时要刻意保留一批30像素以下的目标,哪怕它们很小、很模糊。
  • 增强有没有把目标缩得更小?Mosaic拼图之后,目标尺寸减半再减半,几十个像素变成十几个像素,梯度信号微弱,等于白标。检查增强后的效果图,确认小目标在增强后仍然可辨识。
  • 输入分辨率是否太低?640训练时,30像素目标只占图宽的4.7%,特征层上可能只剩一到两个像素。这是最常见的原因,解决办法就是上1280分辨率,或者用多尺度训练。
  • NMS是不是把小目标框给压掉了?密集人群里多个小目标框重叠,如果confidence偏低、iou阈值设得高,NMS会直接抹掉。把NMS iou从默认0.5调到0.45或者0.4,减小被抑制的概率。

5.2 训练不收敛、BN崩溃这类玄学问题

YOLO系列训练中batch size太小时,BatchNorm的统计量不稳定,可能出现loss波动剧烈甚至NaN的情况。我通常保证batch不小于4,最好到8以上。如果你显卡显存不够,先把imgsz降下来,再不行就调小模型,不要硬扛小batch。

另外用AdamW时lr0设置过高也会BN崩溃。YOLOv8默认lr0是0.01,训练COCO那种大数据集没问题,但校园操场这种几千张图的私有数据集,0.01明显偏激进,我调到0.001才开始稳定下降。SGD的话0.01配momentum 0.937也是常规做法,只是收敛慢一些。

还有一个常见误区:一开始就冻结太多层。你用的是COCO预训练,COCO里有大量的行人样本,底层特征其实挺适配的,冻结前10层只对前50个epoch有好处,后边必须解冻,否则模型上层在学航拍特征、下层还在输出地面视角的特征,整体是割裂的。

5.3 部署时的精度损失

训练好好的,一导出ONNX或者TensorRT,mAP掉几个点,这太常见了。原因主要有三个:算子不支持导致部分层退回到低效实现、量化精度损失、以及导出时输入尺寸不匹配。

我的做法是:导出ONNX之后,用onnxruntime重新跑一遍验证集,和PyTorch推理结果对比mAP。如果掉了超过2个点,先查是不是导出时固定了batch size、输入尺寸和原训练配置不一致。TensorRT做FP16量化时掉点小于0.5个点是能接受的,但如果掉得多就把敏感层保留FP32,或者改用INT8 PTQ加校准集重新量化。这套流程跑下来,部署端和训练端的指标差距可以控制在1个点以内。

6. 这个项目的扩展方向

数据集和模型跑通之后,下一步怎么走,取决于你的真实使用场景。如果只是做人数统计,可以接入ByteTrack之类的跟踪器,把逐帧检测框关联成轨迹,用轨迹中心计数,比直接数框稳定得多,还能顺便输出进出操场的人流方向。如果做运动异常分析,可以在检测框基础上再接一个行为分类头,区分奔跑、行走、静止,但这一步数据量需求就上来了,需要给每种行为单独标注。

如果是做大型集会的密度估计,单纯的目标检测框会有严重的重叠问题,可以考虑把YOLO检测结果作为辅助信号,再用密度图回归网络来输出人数热力图。实际项目里我见过用检测+密度图混合方案的,效果比单一方案稳定不少。

最后说两个我个人觉得值得投资的细节。第一,把数据集的采集扩展成“多季节多天气”版本,秋天的树影和冬天的光秃树枝在外观上天差地别,一个夏季采集的数据集基本不具备跨季节泛化能力。第二,定期用新采集的数据做增量训练,不需要全部重训,在现有权重上用小学习率续训几个epoch就能把新场景的知识吸收进去,这是维持模型长期可用最省钱的方法。

做航拍数据集这个方向,最大的体会是“数据远比模型更能决定成败”。同样的YOLOv8,标注规范、场景覆盖、负样本比例这些基本功做扎实了,效果吊打无脑堆数据或者盲目换新模型的方案。你先把你操场的数据攒扎实,后面换任何模型架构都只是锦上添花。

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

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

立即咨询