ARTICLE DETAIL

资讯详情

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

航拍校园操场人体检测数据集:基于YOLO的小目标检测实战

航拍校园操场人体检测数据集:基于YOLO的小目标检测实战 航拍校园操场人体检测数据集 | YOLO航拍人体检测数据集1. 航拍人体检测为什么难搞——先搞清项目要解决的问题做这个项目之前我先说句实话航拍视角下在校园操场里检测人体和普通监控摄像头画面里检测行人根本是两个难度级别的事情。监控摄像头拍到的行人通常占屏幕面积大、角度平视、特征清晰YOLO随便跑跑都能有不低的精度。但是无人机悬停到操场正上方或者斜上方45度往下一看人直接变成一个个“小脑袋瓜”几百号人穿着同样的军训服或者校服扎堆在一起遮挡、变形、小目标一个不落这时候你再拿训练好的默认YOLO权重去跑漏检能漏到你怀疑人生。所以这个题目的核心难点其实是如何构建一个专门面向“航拍校园操场”场景的人体检测数据集并基于YOLO训练出能在这个极端场景下稳定工作的模型。它解决的并不是“能不能检测到人”这种基础问题而是“在目标小、密度高、外观单一、背景干扰强的俯视图里能不能尽量不丢人、不误报”。这个数据集和配套模型方案适合的人群很明确体育老师想做跑操出勤率自动统计、军训教官想用AI数队列人数、高校信息化部门想给体育测试加一套自动化的运动数据采集工具、还有做智慧校园安防的开发者都能直接用我下面这套数据采集、标注、训练和调优的完整流程。哪怕你手里没有无人机只要理解了我这套构建逻辑也能套用到类似的高空视角人体检测项目里。我实际做下来最大的感受是航拍数据集的价值不在于“拍得多”而在于“定义清楚”。你管画面里那个只有20像素大小的背影叫“人”还是管那个被同学挡了一半、只能看到头肩的轮廓叫“人”这会直接影响标注一致性进而影响模型收敛效果。这些细节普通教程里很少会写清楚我后面会一点点展开。2. 数据从哪来采集、清洗与标注的完整闭环2.1 无人机采集参数高度、角度和光线怎么定航拍数据集的源头是原始图像而原始图像的质量决定了后面所有工作的上限。我用的是大疆的消费级无人机实测下来这类设备完全够用。飞行高度我控制在30米到80米之间这个区间里操场上的队列分布、人数密度都能完整囊括单个行人大概占30~80个像素正好模拟真实航拍监控中“看得见但看不清脸”的状态。飞得太低单帧覆盖面不够人数统计需要拼图飞得太高行人目标小于15像素标注都很勉强模型基本学不到有效特征。云台角度建议固定在 -60度到-90度之间也就是镜头俯视朝向地面。如果你只拍正俯视-90度人物会变成头顶一个圆点加肩部姿态信息少但规则整齐的队列特征明显适合人数统计如果你切成-60度斜视角能多看到部分人体轮廓模型泛化能力会好一些但检测框裁剪起来比较乱。我的做法是两种角度都拍按7:3比例混合进数据集模型既能适应正俯视的场边机位又能适应斜俯视的巡查机位。光线选择同样关键。我踩过一次坑中午12点顶着大太阳去拍操场跑道的塑胶颗粒和草地反光严重人物阴影黑漆漆地连成一片模型训练完对阴影区域的误检直接飙到15%。后来我把采集时间集中在上午10点前和下午4点后这时候侧光能把人从背景里“托”出来。如果只能中午拍记得把无人机的EV值降低一档尽量保留暗部细节别让高光把画面打成死白。还有一个每位新手都会忽略的点航拍时不要把无人机飞得太快。快门下人物会有运动模糊哪怕你用快门优先把速度拉到1/1000秒操场上跑动的学生还是会在高速移动中变成残影。我当时用连拍模式设了每秒3张的间隔飞行的航线速度压到5米/秒以内出来的素材才基本清晰可用。2.2 数据清洗一张模糊图毁掉一整个训练批次采集回来的原始素材绝对不能用“能看见人”当合格标准。我第一次建数据集的时候偷懒只筛了“画面不黑、不虚焦”的图片就拉去标注结果训练到中期发现验证集loss怎么都降不下去最后排查才发现原因大约17%的训练图里含有运动模糊的人体YOLO强行去拟合这些模糊框特征学歪了。我的清洗流程分三步走。第一步自动筛图用图像清晰度评价算法比如Laplacian方差批量计算每张图的清晰度低于阈值的直接扔进回收站。第二步人工扫图把嘈杂区域多、人员严重遮挡重叠、或者有大型器械遮挡的图挑出来——不是说不能用而是要看清楚“人是否可辨认”如果连人眼都判断不了那位置是个人标注出来就是给模型喂毒。第三步做分布检查。操场场景有个特点队列训练构图高度相似如果清洗时没注意很容易留下几百张几乎一模一样的图模型会严重过拟合到某个固定站位。我按拍摄时间线和飞行航线做了分组确保每个时段、每个操场区域都有覆盖。清洗完的素材我保留了约1600张有效图片其中训练集1280张、验证集240张、测试集80张。这里多说一句航拍数据集不建议把测试集留太少因为高分辨率大图切图后会产生大量切片最终测试集的样本数实际上会膨胀很多后面会细说切图的事。2.3 标注规则航拍场景下“什么才算一个人”标注是整个流程里最磨人、也最影响模型上限的环节。地面视角的数据集比如COCO、VisDrone对人体的标注边界有成熟定义。但航拍俯视场景不一样人体投影在地面上四肢经常被躯干遮蔽直接用矩形框框全身会产生大量背景噪声模型注意力会被跑道线、草坪纹路带偏。我最终采用的标注规则是单类别“person”但框定范围是“可见人体区域的最小外接矩形”。什么意思呢正俯视视角下人通常显示为头顶和肩背那就框头顶到肩胛骨下缘斜俯视时能看到大半身那就框整个可见身体被前排同学挡住的部分不往外扩。这样标注出来的框能够稳定聚焦于人体在高空视角中表现出来的核心特征而不是去拟合一个并不存在的完整人体矩形。遮挡场景的处理我建议遵循一个简单原则被遮挡超过60%就不标低于60%就只标可见部分。密集队列里前排人把后排人挡得只剩半个头这种目标在地面标注里很常见但在航拍人数统计场景中强行标一个只含头顶的框反而会让模型学会“看到半个头就乱报”。模型应该重点学习的是可以明确区分的人体目标。用这个原则还会带来一个附带好处不同标注员之间的框大小差异会小很多一致性上去了后续评估mAP才不会被标注噪声拖后腿。标注工具我试过LabelImg、Labelme、X-AnyLabeling最后长期用的是X-AnyLabeling。它内置了自动分割辅助模型能先用分割模型把人体轮廓预打出来我再微调矩形框单人框标注速度大约能提升40%。里面记得把“自动保存”和“下一张连跳”打开表格化标记进度一天标注三百张没有太大压力。2.4 数据集目录与YOLO格式转换完成标注之后数据集要整理成YOLO训练能直接消费的目录格式。标准结构是dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml标签文件我转成了YOLO的txt格式每行包含类别编号 x_center y_center width height。这四个值全部归一化到0到1区间是相对于图片宽高的比例不是绝对像素值。我额外写了一个Python脚本对原始标注框做了尺寸校验如果框的像素宽度小于5像素或者高度小于5像素自动视为无效目标从标签里剔除。因为5像素以下的目标即使标注正确YOLO也学不出有效特征反而会干扰正负样本平衡。data.yaml的配置我贴一下方便你直接复制改路径path: /data/playground/ train: images/train val: images/val test: images/test nc: 1 names: [person]到这里数据集的主体构建就完成了。我简单统计了一下1600张原始图标注实例数大约7.8万个平均每张图接近49人单张图最多的一次标了310人这个密度对于目标检测数据集来说已经属于“极端密集”范畴。正是这种密度才逼着后续的模型训练必须做针对性设计下面一节就展开讲。3. YOLO训练全过程从预训练权重到自定义数据集3.1 环境与硬件建议一张消费级显卡也能跑训练环境方面YOLO系列的生态已经非常成熟。我建议直接装Ultralytics的YOLOv8或者最新的YOLO11的pip包命令pip install ultralytics硬件上我用过NVIDIA V100 32GB也用过RTX 4090 24GB两者都能顺利完成训练。关键是显存需求取决于你设置的输入分辨率航拍大图我强烈建议用1280×1280的输入尺度哪怕原始图是4K甚至更高也要先缩放到训练尺度否则小目标特征会被进一步压缩。在这个输入尺度下yolov8s模型加batch size设为8大约需要10-12GB显存4090可以很从容地往上顶到batch 16。CPU方面没有太高要求我自己用AMD Ryzen 7系列都能流畅跑数据预处理。真正卡脖子的反而是存储整理后的数据集如果有大量高清切片建议直接放NVMe固态盘。我第一次放在机械硬盘上训练时CPU读图速度跟不上GPU消费速度每个epoch都会空等好几分钟。3.2 模型选型不是越大的模型越好航拍小目标场景直觉上会觉得“模型越大越厉害”我最初也直接用yolov8x去跑结果训练时间几乎是s模型的4倍mAP却只涨了1.4个百分点。原因很简单航拍操场的特征结构并不复杂——背景是草坪或跑道目标是人类别单一。蛋糕就那么大模型再大可以学到的新特征也很有限反而是深层网络为了凑复杂度会开始记忆噪声。这组对比数据我做成了表格供你选型参考模型输入分辨率mAP50mAP50-95单卡训练时长约显存占用batch16yolov8n128082.7%55.3%1.2小时6GByolov8s128088.6%61.2%2小时11GByolov8m128089.8%62.9%3小时15GByolov8x128090.2%63.5%6小时29GB最终我把yolov8s作为主力模型原因很务实mAP并不差太多但推理速度快后续接DeepSORT跟踪、多路视频流同时分析它都能扛住。如果你只需要离线处理大图不在乎实时性那上yolov8m是性价比更优的选择。3.3 训练参数与损失函数知道改什么也要知道为什么用预训练权重做迁移学习是标准操作。下载yolov8s.pt直接作为起点命令yolo detect train datadata.yaml modelyolov8s.pt epochs150 imgsz1280 batch16训练参数里我最关注的三个是epochs、imgsz和optimizer。epochs我用150轮配合早停机制patience20也就是连续20轮验证集mAP不提升就自动停止。实际训练中模型在90到110轮就基本收敛了很少跑满150轮。imgsz设置1280前面已经强调过这是小目标检测最关键的一环宁可用小模型大分辨率也不要大模型小分辨率。optimizer方面我试过SGD和AdamW在航拍这个场景下两者收敛后的精度差异小于0.5%。SGD需要更多轮次热身AdamW收敛更快但对学习率的敏感度高稍微调大就发散。新手建议直接用SGD默认学习率0.01稳定追求训练速度的话可以用AdamW加lr0.001。理解训练过程还需要过一遍YOLOv8的损失函数构成它有三大块分类损失用BCE边界框回归损失用CIoU再加上DFLDistribution Focal Loss。分类损失负责让模型区分前景和背景CIoU负责把预测框往真实框上回归DFL则让框的四条边能够拟合出更细的分布尤其是边界上的不确定区域。航拍密集场景里很多人头肩目标边界本身存在大量半遮挡DFL能学出“框左边其实还可以再宽一点”的概率分布这是YOLOv8在密集小目标上比YOLOv5表现更好的重要原因之一。如果训练时发现小目标召回率不高除了提高分辨率还可以考虑调低分类损失的权重或者给回归分支稍微加一点权重。不过我不建议一上来就动损失函数权重——UltrAlYtics默认配置在绝大多数场景已经平衡得不错优先调数据、调分辨率效果来得更直接。3.4 训练中的两大拦路虎过拟合和BN崩溃航拍校园操场数据有一个隐患场景太单一了。草地、跑道、队列拍来拍去视觉分布高度集中模型很容易背下“这张图跑道旁边的草坪区域有人”而不是真正学会“看起来像人的目标”。我的应对措施是数据增强拉满。跑操和军训的图像增强策略我建议这样配置随机HSV色域扰动hsv_h0.02, hsv_s0.6, hsv_v0.4这能模拟不同阳光下的色彩偏移随机水平翻转fliplr0.5操场是对称结构翻转完全符合真实分布随机缩放裁剪从0.5到1.5之间浮动模拟不同飞行高度。垂直翻转flipud建议不要开航拍图里“上下颠倒”并不符合无人机正常视角。另一个比较隐蔽的问题是Batch NormalizationBN层的崩溃。YOLOv8的所有卷积模块都带BN而BN的统计量跟batch size强相关。如果batch size太小比如小于4每批的均值和方差抖动过大BN统计量会慢慢漂移典型症状就是训练早期loss降着降着突然飙升。解决方法是把batch size维持到16以上或者用梯度累积模拟同等效果比如batch_size16时梯度累积2步等效batch_size32BN会更稳。训练完成后导出模型yolo export modelbest.pt formatonnx opset13 imgsz1280航拍场景一般用ONNX加CUDA Execution Provider去做推理部署到边缘盒子或者服务器上都能跑。我导出后对比过ONNX和PyTorch原始模型的精度几乎没有损失但帧率提升了40%以上。4. 评估指标、小目标问题与常见排查实录4.1 效果怎么看别只盯着mAP一个数训练跑完终端会打印一堆指标很多人只看mAP50这不够。航拍人体检测我更建议重点看三个指标mAP50、mAP50-95和Recall。mAP50是IoU阈值在0.5时的平均精度直观反映“框得差不离”的能力。航拍场景下人员密集且目标小目标框稍微偏一点其实没那么致命——反正后面做人数统计只需要一个点落到人身上。mAP50-95则是IoU从0.5到0.95每隔0.05计算一次然后取平均它对框的位置精确度要求更苛刻。但如果你的应用场景只是“数人”而不是“精确分割”mAP50-95略低完全可接受。我训练的模型mAP50到88.6%mAP50-95到61.2%后者对于密集小目标已经算中上水平了。召回率Recall则直接衡量“漏检了多少人”。航拍人数统计漏一个人比误报一个人更值得注意。如果发现Recall明显低于Precision说明模型太保守只挑最有把握的目标下手这时应优先做数据层面优化增加目标多样性的样本、把imgsz进一步拉高到1536。最后的验收我写了个Python脚本把无人机拍的一段视频抽帧逐张推理把检出的坐标点映射回原图用OpenCV画圈并统计每帧人数再和人工数帧的人数做对比算平均绝对误差。实测结果在操场队列规则排列的情况下单帧计数误差在3%以内在自由活动分散场景下误差大约在5%-8%主要漏在树荫下和远离镜头的角落。4.2 小目标检测高分辨率切图SAHI才是关键突破我在开发阶段遇到过最让人崩溃的问题是直接把4K大图resize到1280跑一张图上300人的队列模型只检测到一半。后来才意识到把4160×3120的原始图缩到1280时人物目标从直径60像素被压到不到20像素特征几乎消失。这不是模型不行是你的输入尺度在“主动”丢信息。解决思路是切图不切分辨率把高分辨率大图切成若干小图块每块保持原分辨率让YOLO在小图上检测再把检测框映射回大图坐标最后做NMS融合。现在用的标准方案是SAHISlicing Aided Hyper Inference它的切图逻辑是以滑动窗口方式生成重叠切片重叠率一般设20%然后对同一目标在相邻切片中重复检测到的框做融合。安装和调用很简单pip install sahifrom sahi import AutoDetectionModel from sahi.predict import get_prediction detection_model AutoDetectionModel.from_pretrained( model_typeultralytics, model_pathbest.pt, confidence_threshold0.3, image_size1280, devicecuda ) result get_prediction( imageplayground_4k.jpg, detection_modeldetection_model, slice_height1280, slice_width1280, overlap_height_ratio0.2, overlap_width_ratio0.2 )切图这个操作对精度带来的提升是决定性的同样一个yolov8s模型整图推理漏检率接近50%切片推理后漏检率直降到8%。代价是推理时间增加但对离线人数统计完全没有影响。如果做实时视频分析可以先把视频抽帧保存再批量切片分析避免实时性受限。4.3 混淆矩阵总和为什么不是100%——YOLO评估图的阅读误区很多人跑完验证会生成confusion_matrix.png然后盯着数字发呆所有格子加一起怎么不等于100%原因在于混淆矩阵展示的是“真实类别归一化”的比例也就是每一行的GT目标有多少被判成了各个类别而不是整张图四个象限的绝对百分比。所以人物类别那一行加起来约等于100%而背景类别单独作为一个类别与其他类别混叠出现冲突就会导致看着不像传统表格那么“总和规整”。我建议评估时不要长时间纠结这张图回到你的业务目标上数人数直接看Recall和F1防误报看Precision想要整体均衡看P-R曲线下面积。混淆矩阵只用来排查特定的错误模式比如人物目标大量被分到背景里那八成是标注框太紧、目标特征不足。一路训练下来我发现真正的周期性大坑反而是图片读入时标注框顺序乱掉导致训练图与标签对不上但那属于数据管道的低级错误用一次可视化校验脚本就能纠正。4.4 典型问题速查表现象可能原因解决方法训练loss前期正常中期飙升BN崩溃或学习率过大加大batch size、调低学习率、梯度累积验证mAP高但现场漏检多输入分辨率不足用SAHI切片imgsz提到1280以上树荫下大量漏检训练样本缺阴影下目标补充阴天/阴影时段数据加HSV增强跑道线被误检成人背景纹理干扰检查标注框是否含大量背景收紧框边界密集队列半数检测重叠NMS阈值太松调IoU阈值到0.5-0.6开启AGNMS模型只认本校操场场景单一过拟合增加不同操场、不同高度混合数据5. 落地场景与经验总结从数据集到能用的AI应用5.1 军训会操、跑操出勤——数据集的实际应用这个数据集直接对标的一个热门应用就是“军训航拍方阵人数校验”。军训会操时一个方阵几十上百人手动数人头经常出错。我实际落地时脚本的逻辑是无人机悬停到方阵正上方抓取一张正俯视图像先做SAHI检测然后把所有框的中心点坐标收集起来做一次基于距离阈值的聚类比如中心点间距小于10像素的合并最后输出一个“预计人数”误差在2人以内。这套逻辑本质上就是检测加简单的密度聚类不需要复杂的跟踪算法就能工作。跑操出勤识别是另一个高频场景。每天早上绕操场跑圈的班级在无人机视角下是一团快速移动的目标群。这里我建议在检测之外叠加追踪逻辑对视频流的每一帧做检测用DeepSORT对目标编号计数设置最大丢失帧数来避免同一人短暂遮挡被重复计数。实测在双班级混跑的400米跑道上识别出的总人数和人工清点相比准确率在90%以上出错主要在并排紧贴跑动、彼此完全重叠的瞬间。体育教学方面也可以扩展在足球课或田径课的录像中识别每位学生的位置生成热力图帮助教师分析课堂空间利用率。这个用途对精度要求比人数统计低但需要给数据集的标注增加“活动区域”的概念或者直接对检测结果做坐标映射转换到场地坐标系。5.2 后续扩展单类检测只是起点目前这个数据集是单类person但它完成之后还可以沿几个方向做低成本扩展。第一个方向是用训练好的权重做伪标注录一段新操场视频让模型先检一遍手动修正少数漏检和误检从几百张有效图快速扩充到上千张应对多校区场景。第二个方向是接入ReID人员重识别操场航拍场景跨镜头连续性差用ReID可以缓解同一人来回走动时被重复计数的问题前提是要求场景中每个人的外观有效区分这在统一校服下挑战很大。第三个方向是结合Transformer结构改进Backbone比如引入注意力机制后模型对密集队列中相邻人的区分能力会好一些但推理速度下降明显工业落地时要衡量取舍。5.3 我踩过的那些坑希望你绕开最后分享几个贯穿项目始终的教训。第一标注规范一定要在标注开始前写清楚并让参与标注的人先标同一批图做一致性测试测试结果方差大的赶紧统一标准否则等到两万多个框标完再统一意见就晚了。第二训练用的图像不一定要全部来自无人机实拍完全可以加入少量从公开的空中视角行人数据集里筛选出来的、同样符合“俯视、密集、小目标”特征的图片做补充增强泛化性但不要放太多场景偏移会导致指标虚高。第三切图推理虽然猛但强烈建议在训练阶段就把训练图切成小图来训练而不是训练整图推理时才切图前者能同时解决“显存不够”和“小目标特征被压缩”这两个问题我后来重建数据集时把1280×1280的切片直接作为训练输入mAP50又提升了2到3个点。我自己做这个项目最大的体会就是航拍人体检测拼的不是某个惊艳的算法创新而是数据细节的打磨——飞行高度、光线、标注边界、切片策略、训练尺度没有哪个环节是决定性的但每个环节都掉一点链子最后模型效果就会差出一大截。你要是照着这套流程走一遍踩过的坑肯定比我看这篇文章时少得多后续如果再结合业务做深完全可以把这套方案推广到操场之外的运动场、景区广场、大型户外活动等人群聚集场所一鱼多吃。
返回列表