☰
航拍校园操场人体检测数据集构建与YOLO训练实战
2026/9/29 18:22:09 网站建设 项目流程

搞过人体检测的人都知道,一个模型能不能在真实场景里站稳脚跟,往往不取决于网络结构有多花哨,而是取决于训练数据有没有覆盖到目标真正会出现的视角和条件。我这次想聊的项目,标题写得很直白:航拍校园操场场景下的人体检测数据集,配上YOLO系列模型跑训练。这类数据集的特殊之处在于,它不是常见的平视监控视角,也不是自动驾驶里的车顶摄像头,而是无人机在几十米高度俯拍,目标小、相互遮挡少但尺度悬殊,光照和背景也极其单一——一堆人站在绿色或红色的塑胶跑道上。把这样的场景做成一套可复用的数据集,再落到YOLO里训练和推理,途中踩过的坑,我觉得值得完整记录下来。

这套东西到底能解决什么问题?往大了说,校园操场的人群密度估计、大型集会的安全预警、体育课堂的自动化考勤,都需要“从空中认出每个人”的能力;往小了说,它就是一套从无人机采集到标注、训练、部署的完整闭环。适合谁参考?如果你手里正好有航拍素材不知道怎么标,或者你训练通用YOLO模型后发现俯视拍出来的操场漏检严重,又或者你只是在做一个毕设、个人作品想让人体检测落地到校园场景,这篇文章都可以直接当成操作手册来用。我下面说的所有环节,都基于一个真实做过的航拍校园操场数据集项目,参数、数量、错误样本都是实测记录。

1. 项目思路:为什么航拍校园操场的人体检测这么麻烦

1.1 俯视视角带来的“人不像人”问题

先讲一个很多人没意识到的点:主流公开人体数据集,比如大家常用的COCO的person类别、或者一些行人检测数据集,绝大多数是平视或者略微俯视的视角。目标高度通常在几十到几百像素,身体比例完整,头、肩、四肢的轮廓清晰。YOLO在这些数据上训练出来的先验框,本质上学习的是“直立人体的侧影或正影”的形态。

但无人机飞到操场上方,你会得到完全不同的画面:人变成了“头顶上的一个点”,或者说是一个圆形头部加上肩部阴影的组合。高度到了30米以上,一个人可能就只占大约20×40像素;身体被压缩成前后两个色块,四肢在阴影里几乎看不见。YOLO模型在特征提取阶段,会对这些“小色块”输出极低的置信度,甚至直接忽略。第一次用通用模型跑航拍画面时,漏检率会高到你怀疑人生,这不是模型性能问题,是训练分布和测试分布根本不匹配。

1.2 数据量、成本与质量的取舍

既然要做专用数据集,那做多大的量才合理?网上有声音说“目标检测数据集至少要上万张”,这话对通用任务没错,但对航拍单场景任务,我认为更重要的是“平铺视角覆盖全”。我这次数据集最终控制在2500张左右,每张图里的目标数在10到80人之间,总标注目标数约3.2万个。为什么不再多标几万张?因为操场的拍摄条件相对固定,场景的多样性有限,到了3000张以后,边际收益会变得非常低。真正影响模型泛化能力的不是图片总量,而是高度、角度、顺光逆光、阴晴天气的组合数量。

另外,成本也要算:一架能拍4K视频的无人机,一次飞行的电池续航是三十分钟左右,2500张图意味着至少十几次起落,再算上挑选有效帧、清洗画面、人工标注、二次复核的时间,一个熟练标注员每天能处理大约200到300张复杂场景图。如果你一个人从零干到完,留出两到三周是比较现实的时间预算。所以我的建议是:数据量先瞄准“够用”,把每一张图的质量和视角多样性做足,比盲目堆数量划算得多。

2. 数据采集与标注:训练效果的“地基”

2.1 航拍数据怎么拍

数据采集这一步,听起来最简单,实际上最容易返工。我用的方案是消费级四旋翼无人机,飞行高度分三档:低空20米、中空40米、高空80米。20米能拍到比较清晰的个体姿态,适合让模型学到“俯视下的轮廓细节”;40米是中间过渡;80米则是真正的大场景俯瞰,单个人会缩小到不足15像素,这档数据是保证模型在远端不失效的关键。拍摄时不要一直悬停,而是沿着操场边线匀速飞“之”字形航线,让画面覆盖到跑道、足球场、篮球场看台周边等不同区域。

这里有两个细节特别重要。第一个是快门间隔,不要用视频抽帧抽得太密,否则连续帧之间目标位置变化太小,数据集会有大量高度相似图片,训练时容易过拟合。我采用的是飞行过程中每隔3秒拍一张,同时保证相邻照片至少有一半以上画面是不同的区域。第二个是对焦策略,无人机自动对焦在这种大面积同色地面上经常会犹豫,导致画面发虚。我直接把对焦模式切到无穷远,光圈默认,ISO压在100到200之间,保证地面纹理和人体轮廓锐利。实测下来,凡是虚焦严重的帧,标注之后再训练,对模型精度只有破坏作用,宁可少要也不要这部分数据。

2.2 标注细节与格式转换

标注工具上,我用了LabelImg,虽然它界面朴素,但胜在轻量且导出的VOC格式转YOLO格式非常顺手。类别就一个:person。为什么不做“student / teacher / other”这种多分类?因为从80米高度往下看,你作为标注员根本分不清谁是老师谁是学生,强行分只会制造大量噪声。目标检测里错标签比漏标签更可怕,它会直接教坏分类器。

航拍人体标注有一个和普通行人标注完全不同的判断逻辑:普通场景里,框要贴住人身体的边缘;航拍画面里,人很小,身体边缘在阳光下是一片模糊的过渡带,如果强行贴着视觉边缘去标,框的抖动会非常大。我最后定的规矩是:框住“头顶到肩部投影的明显区域”,再稍微往外放两个像素容忍度。更细一点说,如果一个人被篮球架或看台遮住了下半身,只要头顶和肩部轮廓能分辨,就标注完整的人体外接框;如果整个人只剩一个头部像素团,也照样标注。这保证了正样本的最大化,模型学到的是“航拍视角下只要有一个人形色块就输出目标框”,而不是只会检测完整的身体。标注完成后,通过一个自写的小脚本把XML统一转成YOLO格式的txt,同时顺手把所有类别名重置一遍,防止早期标注时误填了冗长类名导致训练报错。

2.3 数据划分与增强策略

数据划分这件事,我特别强调一点:不要随机划分。因为同一架次飞行拍摄的照片,时间、高度、光照几乎完全一致,如果把同一架次的图同时分进训练集和验证集,验证集分数会虚高,但模型换个时间再去飞就现出原形。正确做法是按“架次分组划分”:每一轮飞行单独一个文件夹,训练、验证、测试按照7:2:1分配,且同一架次的图不能同时出现在训练和验证里。这样验证集的mAP才有参考意义。

增强策略上,YOLO训练默认自带的Mosaic和MixUp在航拍任务里要小心用。Mosaic把四张图拼在一起,对普通目标检测效果很好,但如果是80米高度的航拍图,拼接之后目标会变得更小,模型容易学到“检测粘连在一起的模糊色块”。我在训练时把Mosaic概率降到了0.3,MixUp直接关掉。反而把水平翻转、垂直翻转都开到0.5,再补一个0.2概率的随机旋转90度和180度。操场是规则矩形,方向感很强,做这种方向增强能帮模型摆脱“看台总在画面下方”的偏置。

3. YOLO选型与超参数配置:从yolov8到yolo11

3.1 模型选型对比

YOLO版本选哪个,我的判断标准是:训练成本可控、部署不吃力、小目标不能太差。YOLOv8和YOLO11之间,我做了三轮对比。YOLOv8的n/s/m三个体量都属于成熟稳定型,资料多,社区踩坑记录全;YOLO11在C2PSA模块和检测头上有改动,理论推理速度更快,但对我来说,它在小目标上的提升主要依赖更多训练轮数,数据量偏小时容易不升反降。最后我实际选的是YOLO11s作为主模型,因为它在我的验证集上比v8s高了约2.2%的mAP50,同时保留YOLOv8s作为快速迭代的备选。

如果你显存或者算力有限,用nano版本跑也不是不行,但要有预期:nano在80米高度那种15像素小目标上,漏检率会明显高于s版本。我的看法是,在目标尺寸平均只有几十像素的场景里,模型参数量带来的小目标特征提取能力差异,比你在任何训练技巧上的努力都更明显。所以不要在这个项目里为了省显存强行上nano。

3.2 一个能跑通的训练参数

直接给一套能跑的配置,我最后用的训练设置大致是这样的:

  • 超参数配置文件:imgsz=1280,batch=8,epochs=200
  • 优化器:SGD,初始lr=0.01,最终lr=0.0001,weight_decay=0.0005
  • 预热轮数warmup_epochs=3
  • 关闭MixUp,Mosaic概率0.3,FlipUD和FlipLR保持0.5
  • 早停机制patience=30

为什么输入尺寸选1280而不是默认的640?这里有一个非常关键的计算逻辑:80米高度下一个成年人投影大约10至15像素,640分辨率下,这个人可能只有6至8像素,几乎接近特征图单格的极限,特征提取网络下采样32倍之后,到检测头只剩零点几个像素,等于直接消失。而imgsz提升到1280,目标在小特征图层的响应会明显增强。代价是显存上升明显,batch=8在单张24G显存的显卡上是安全的;如果只有16G显存,建议imgsz降到960或者batch降到4。

SGD和AdamW的选择,我给出一个个人偏好:在标注质量有波动、数据量又不大的项目里,SGD对噪声标签的容忍度比AdamW高,训练过程虽然慢一点,但收敛结果更稳。AdamW在这个场景里出现过几次“训练集loss猛降、验证集mAP不涨”的假象,换回SGD后问题消失。

3.3 训练动态怎么读

训练过程中千万别只看一两个指标。我每次训练都同时盯着三个loss:box_loss、cls_loss、dfl_loss,以及PR曲线和混淆矩阵。一个典型的健康曲线是:前30轮三个loss同时快速下降,mAP50在40轮左右开始抬头,到120轮之后提升变缓。如果box_loss降得正常、cls_loss一直横盘,那大概率是错标样本落在了训练集里,我会直接暂停训练,抽取错标样本重新检查。

特别提醒一个YOLO训练里的“过拟合信号”:如果在epoch 80以后验证集mAP开始波动甚至下降,但训练集mAP还在继续走高,说明模型在死记硬背数据里的布局特征,比如记住了“看台区域总有一排人”。解决方法是先把imgsz提升到1280再重训,或者把Mosaic概率关掉让它更关注单体特征。我自己的最终训练结果,在测试集上mAP50约0.94,mAP50-95约0.76,对一个单类别航拍小目标任务来说,已经足够支撑后续部署。

4. 部署与推理优化:从模型到可用的检测器

4.1 导出与转换

训练完的模型不能只在PyTorch环境里跑,真正要落地到无人机地面站或者Web服务里,需要导出。我个人习惯走一条固定路线:先用yolo export model=best.pt format=onnx opset=12导出ONNX,再用onnxruntime做CPU/GPU推理验证,如果要在嵌入式设备跑,再考虑用TensorRT的静态引擎,int8量化后单张1280分辨率的推理耗时能压缩到十几毫秒级别。

导出时有个坑:如果训练时用了1280输入,ONNX默认动态轴会带来额外的延迟,建议导出时直接固定dynamic=False,把输入尺寸写死成[1,3,1280,1280]。这样模型少了很多运行时shape推断的开销。

4.2 针对小目标的推理后处理

即使模型训练得不错,直接拿全图做推理,80米高度的小目标依然容易漏。这里我推荐一个非常实用的策略:推理时把原始航拍图切成四块,每块重叠约50像素分别检测,再通过坐标映射把检测框合并回原图坐标系。因为YOLO在小图上的目标会相对变大,检测置信度会明显上升。这种方法不需要重新训练模型,纯粹是推理策略优化,我的漏检率能再降2%左右。

实施时注意一点:切块后的重叠区域会出现同一个目标被检测两次的情况,合并时用NMS统一过滤一遍,IoU阈值设0.45。还有一个细节,因为操场里人在移动,视频切帧检测时要把同一目标的轨迹做时间平滑,否则检测框会一帧大、一帧小,影响计数准确性。这里可以直接用一个简单的轻量追踪器,比如ByteTrack,按检测框的IoU做跨帧关联,实测在人群密集但相对分散的操场上效果很不错。

4.3 部署到边缘设备的降级方案

如果你打算把检测服务部署在无人机机载板或者树莓派这类设备上,显存和算力会非常紧张。我的建议是准备两个模型:一个高精度YOLO11s用于地面站离线分析,一个YOLOv8n量化版本用于机载实时预警。量化采用FP16即可,INT8在小目标上损失有点大,不建议在航拍场景优先使用。如果机载端还是跑不动,可以退一步直接把输入分辨率降到960,把检测频率从30帧降到5帧,同时用追踪器补帧。这种“降分辨率+降频率+追踪器补位”的组合,实测能维持实时性,人员计数误差控制在5%以内。

5. 常见问题与排查技巧

5.1 漏检率高是新模型还是老问题

很多人训练完第一件事就是拿一段新视频去测,发现漏检率还是高,第一反应是训练失败。我建议冷静下来先区分原因:先看漏检的目标在画面里有多大,如果在1280分辨率下小于10像素,那是物理分辨率极限,换任何模型都难;如果目标有30像素以上还漏检,再怀疑模型问题。第二步是把漏检帧抽出来,看看这些目标所在的背景区域是不是训练集里没有的。比如训练数据全是绿茵场,测试突然出现一片红色的塑胶跑道,模型漏检很正常,不是bug,是缺数据,赶紧补拍补标才是正路。

5.2 训练过程中loss出现NaN

这个是真遇到过的。YOLO训练跑到100多轮,突然box_loss变成NaN,然后整个训练崩掉。排查之后发现原因是训练数据里有几张图存在全黑的帧,像素值全部为0,导致归一化除法异常。解决办法很简单:训练前写一个检查脚本,把所有图片的方差求一遍过滤掉全黑全白帧和纯色帧。顺带把那些体积为0的空txt标签文件也删掉,它们会让模型在那个位置上学习一个“无目标”的空梯度。

5.3 一个小技巧:用热力图和错误样本定位数据缺陷

我每次训练完,除了看mAP,一定会再跑一遍置信度分数分布:把所有预测框按置信度从高到低排序,然后把置信度在0.3到0.5之间的弱正样本框全部可视化保存。这能直观看出模型“犹豫”的地方在哪里。比如如果你的弱正样本大量集中在篮球架下和看台阴影里,说明训练集里这些区域的正样本背景太单一,后续补数据时就专门去不同光线条件下多拍这两块区域。这个技巧帮我节省了大量盲目的数据采集时间。

6. 一点实操体会和可以继续做的方向

这批数据和这个训练流程做完之后,我最大的体会是:航拍人体检测这个题目,80%的功夫都在数据视角和标注标准上,只有20%花在模型调参上。和通用目标检测不同,俯视场景里人体的信息量天然不足,你必须通过数据采集的高度分层、标注规则上的容错设计、推理时的切块策略,才能把YOLO这类模型的潜力挤出来。另外,数据集本身后续也可以继续扩展,比如加入不同季节的操场画面、雨天反光地面,或者把单类别扩展成人头/身体/团体三类,再配合计数和后端统计,直接就能变成一个操场人员密度预警的小系统。

最后分享一个小细节:校历和课表是这类项目一个常常被忽略的“额外信息源”。如果你能拿到不同时间段操场的实际使用情况,完全可以按时间段定向采集数据,比如课间操和体育课的人群分布差异巨大。把时间维度纳入数据规划,你的模型能学会的远不止“有人没人”,而是“这个时段操场上通常有多少人、分布如何”。这一点,是我在这次项目中觉得后劲最大、也最实用的一个扩展方向。

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

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

立即咨询