ARTICLE DETAIL

资讯详情

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

航拍校园操场人体检测数据集:YOLO训练与部署实战指南

航拍校园操场人体检测数据集:YOLO训练与部署实战指南 1. 航拍人体检测到底在解决什么问题1.1 从一段真实的踩坑经历说起去年秋天一个做体育赛事分析的朋友找到我说想统计一场校级运动会上各学院方阵的人数和队形变化。他一开始的想法很朴素架一台无人机录一段4K视频然后人工数人头。结果一场开幕式录下来视频时长接近40分钟他盯着屏幕数了不到5分钟就放弃了——画面里几百号人穿着相似的衣服队形还在不断变化人工统计不仅慢而且误差极大。这个场景其实非常典型。航拍视角下的人体检测和我们在常规监控摄像头里做人脸识别、行人检测完全不是一回事。监控视角通常是平视或者略微俯视人体在画面中占据的像素比例大特征清晰而航拍视角是高空俯视一个成年人在画面里可能只有十几个像素高加上光照变化、阴影干扰、人群遮挡检测难度直接上了一个台阶。这就是航拍校园操场人体检测数据集存在的意义。它专门针对无人机、高空摄像头等俯视视角采集校园操场场景下的人体目标标注格式适配YOLO系列目标检测框架拿来就能训练。说白了它解决的是“高空俯视小目标人体检测”这个细分问题而不是通用的行人检测。1.2 这个数据集适合谁用我把这个数据集推荐给了几类人反馈都不错。第一类是做校园安全管理的技术团队他们需要在课间操、运动会等场景下快速统计操场人数判断是否存在异常聚集。第二类是体育科研方向的研究生需要分析队形变换、运动轨迹人体检测是上游任务。第三类是目标检测初学者想找一个场景明确、标注规范的数据集来练手YOLO训练全流程。如果你属于以上任何一类这个数据集都值得花时间研究。但如果你要做的是城市道路行人检测、室内密集人群计数那这个数据集的场景匹配度就不够高需要额外补充数据。1.3 航拍人体检测的核心技术难点在展开实操之前有必要先把技术难点讲清楚这样后面调参的时候你才知道为什么要那么做。难点一目标尺度极小。在120米飞行高度下一台普通无人机拍摄的1080P画面中一个站立的人体大约只占12×30像素。YOLO默认的输入尺寸是640×640如果原图是1920×1080缩放到640之后人体可能只剩4×10像素特征几乎消失。这是航拍人体检测最核心的矛盾。难点二背景干扰强。校园操场的背景包括塑胶跑道、草坪、看台、篮球架等颜色和纹理复杂。尤其是红色跑道和人体肤色在色彩空间上有一定重叠容易造成误检。难点三人群遮挡严重。操场场景下人体经常成群出现前后遮挡导致部分目标只有半个身子甚至只露出头部标注和检测都很困难。难点四光照和阴影变化。航拍时间跨度大从早晨到傍晚光照角度和强度不断变化人体投射的阴影有时比人体本身还显眼模型容易把阴影当成目标。理解了这四个难点后面的数据增强策略、模型选型、训练参数设置就有了明确的针对性。2. 数据集结构与标注格式深度拆解2.1 目录组织与文件命名规范拿到一个数据集第一件事不是急着跑训练而是先把目录结构摸清楚。这个航拍校园操场人体检测数据集通常采用以下组织方式dataset/ ├── images/ │ ├── train/ │ │ ├── campus_001.jpg │ │ ├── campus_002.jpg │ │ └── ... │ ├── val/ │ │ ├── campus_101.jpg │ │ └── ... │ └── test/ │ └── ... ├── labels/ │ ├── train/ │ │ ├── campus_001.txt │ │ └── ... │ ├── val/ │ │ └── ... │ └── test/ │ └── ... └── data.yaml图片和标签文件一一对应文件名相同只是扩展名不同。这种结构是YOLO训练的标准格式Ultralytics的YOLOv5/v8/v11都直接支持。注意有些数据集会把所有图片放在一个文件夹里用txt文件划分训练集和验证集。两种方式都可以但目录分离的方式更直观不容易出错。2.2 YOLO标注格式详解YOLO的标注文件是纯文本每行代表一个目标格式为class_id center_x center_y width height其中所有坐标都是归一化到0到1之间的浮点数。举个例子如果一张图片是1920×1080某个人体的边界框左上角在(960, 540)宽40像素高80像素那么标注行就是0 0.5 0.5 0.0208 0.0741计算过程center_x (960 40/2) / 1920 0.5center_y (540 80/2) / 1080 0.5width 40/1920 0.0208height 80/1080 0.0741。这个数据集通常只有一个类别class_id为0代表“person”。有些版本会区分“站立”和“倒地”两种状态但校园操场场景下一般不需要。2.3 标注质量检查的四个关键点标注质量直接决定模型上限。我在使用这个数据集之前习惯做四件事第一检查边界框是否贴合。用脚本把标注框画到原图上随机抽50张看看。航拍人体小标注时容易框大或者框偏。如果发现系统性偏移说明标注规范有问题。第二检查是否有漏标。操场场景下人体密集漏标很常见。漏标会导致模型学到“有些人不是人”的错误特征降低召回率。第三检查类别一致性。确认所有人体都标成了同一个类别没有把阴影、篮球架误标进去。第四统计目标尺寸分布。写个脚本统计所有边界框的宽高分布如果大部分目标宽度小于0.02归一化后说明小目标占比极高训练时需要特别处理。import os import numpy as np label_dir dataset/labels/train widths, heights [], [] for f in os.listdir(label_dir): with open(os.path.join(label_dir, f)) as file: for line in file: parts line.strip().split() if len(parts) 5: widths.append(float(parts[3])) heights.append(float(parts[4])) widths np.array(widths) heights np.array(heights) print(f目标总数: {len(widths)}) print(f宽度中位数: {np.median(widths):.4f}) print(f高度中位数: {np.median(heights):.4f}) print(f宽度小于0.02的比例: {(widths 0.02).mean():.2%})这段脚本跑下来如果宽度小于0.02的比例超过60%那这个数据集就是典型的小目标检测任务后面模型选型和训练策略都要围绕这个特点来。2.4 数据集划分的讲究训练集、验证集、测试集的划分不是随便切一刀就行。航拍数据有个特点同一段视频抽帧得到的图片高度相似。如果随机划分训练集和验证集里可能出现几乎一样的图片导致验证指标虚高。正确的做法是按视频片段划分。比如有10段航拍视频用7段做训练2段做验证1段做测试。这样验证集才能真正反映模型在未见过的场景下的表现。如果数据集已经划分好了你可以检查一下训练集和验证集的图片文件名是否有连续性。如果文件名是campus_001到campus_800做训练campus_801到campus_1000做验证那大概率是按时间顺序切的问题不大。但如果是随机打乱的就要留个心眼。3. 模型选型与训练策略实战3.1 为什么选YOLO而不是Faster R-CNN航拍人体检测这个任务我对模型的要求排序是速度快 小目标召回率高 精度高。原因很简单实际部署场景下无人机图传是实时的你不可能用两阶段检测器慢慢跑。YOLO系列是单阶段检测器一次前向传播就出结果。YOLOv8n在V100上跑640×640输入推理速度可以到300FPS以上完全满足实时需求。Faster R-CNN虽然精度可能略高但速度只有YOLO的十分之一工程上不划算。具体选哪个版本我的建议是新手从YOLOv8n或YOLOv8s开始模型小、训练快、社区资源多。如果精度不够再往上换YOLOv8m或YOLOv11m。不建议一上来就用YOLOv8x参数量太大小数据集容易过拟合。3.2 输入分辨率的关键抉择前面说过航拍人体目标极小。YOLO默认输入640×640对于这个任务来说太小了。我的经验是至少用1280×1280如果显存允许1536×1536更好。但分辨率提高会带来显存和速度的压力。这里有个计算公式显存占用大致与输入分辨率的平方成正比。640到1280面积变成4倍显存也接近4倍。YOLOv8n在640下batch16大约占4GB显存到1280下batch16就要16GB左右。V100有32GB显存可以承受。如果显存不够有两个折中方案一是降低batch size用梯度累积模拟大batch二是用切片推理SAHI把大图切成小块分别检测再合并。切片推理对小目标效果很好但推理速度会下降。3.3 数据增强策略的针对性设计通用的YOLO数据增强包括马赛克、随机缩放、随机裁剪、色彩抖动等。但航拍人体检测需要做一些调整。马赛克增强要慎用。马赛克把四张图拼成一张会让原本就小的人体变得更小。我通常把马赛克概率从默认的1.0降到0.5或者干脆关掉。随机缩放要加大范围。默认的缩放范围是0.5到1.5我改成0.8到1.2。因为航拍高度相对固定人体尺度变化不会太剧烈过度缩放反而引入噪声。色彩抖动可以加强。航拍光照变化大我把HSV的色调、饱和度、亮度扰动范围都调大了一些让模型对光照变化更鲁棒。加一个随机遮挡增强。自己写一个增强在图片上随机画几个黑色矩形模拟云层遮挡或者建筑阴影。这个增强对提升模型鲁棒性很有帮助。import random import cv2 import numpy as np def random_occlusion(image, num_patches3, max_size100): h, w image.shape[:2] for _ in range(num_patches): x1 random.randint(0, w - max_size) y1 random.randint(0, h - max_size) size random.randint(20, max_size) image[y1:y1size, x1:x1size] 0 return image3.4 损失函数与正负样本分配YOLOv8用的是TaskAlignedAssigner做正负样本分配结合分类损失和回归损失。对于小目标检测我建议关注两个点一是分类损失权重。小目标特征弱分类容易出错可以适当提高分类损失的权重。在YOLOv8的配置里可以通过修改cls参数来调整默认是0.5我试过调到0.7召回率有提升。二是回归损失。YOLOv8用CIoU Loss对小目标的定位精度还可以。如果发现定位偏差大可以换成EIoU或者SIoU但提升有限不建议花太多时间。实操心得小目标检测的瓶颈往往不在损失函数而在特征图分辨率。YOLOv8的P3特征图是80×80输入640时对应8倍下采样。如果输入1280P3就是160×160小目标特征保留得更好。所以提高输入分辨率比调损失函数更有效。3.5 训练参数配置与调参记录以下是我在V100上训练这个数据集的一套配置基于YOLOv8s输入1280batch8训练200轮model: yolov8s.yaml data: campus_person.yaml epochs: 200 imgsz: 1280 batch: 8 workers: 8 optimizer: AdamW lr0: 0.001 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3 mosaic: 0.5 scale: 0.2 hsv_h: 0.02 hsv_s: 0.8 hsv_v: 0.5 fliplr: 0.5 flipud: 0.0几个关键参数的解释lr0: 0.001初始学习率。AdamW优化器下0.001比SGD的0.01更稳小数据集不容易震荡。lrf: 0.01最终学习率是初始的1%余弦退火到很小帮助收敛。warmup_epochs: 3前3轮预热学习率从0慢慢升到0.001避免一开始就大步长破坏预训练权重。mosaic: 0.5马赛克概率减半原因前面说了。scale: 0.2缩放范围0.8到1.2比默认的0.5小。flipud: 0.0关闭上下翻转。航拍视角下人体上下翻转不符合物理规律开了反而有害。训练过程中我记录了每轮的mAP50和mAP50-95。前20轮mAP50从0.1涨到0.650轮左右到0.85100轮后基本稳定在0.90左右。如果100轮还没到0.85大概率是学习率或者数据有问题需要排查。4. 推理部署与效果优化4.1 从训练到推理的完整链路训练完模型得到best.pt接下来就是推理。YOLOv8的推理接口很简单from ultralytics import YOLO model YOLO(best.pt) results model.predict( sourcetest_video.mp4, imgsz1280, conf0.25, iou0.5, saveTrue )但实际部署时有几个参数需要仔细调。conf阈值默认0.25。航拍人体小模型置信度普遍偏低我试过0.15到0.3最终定在0.2。太低误检多太高漏检多。iou阈值NMS的IoU阈值默认0.7。人群密集时两个人体框可能重叠度很高IoU阈值太高会误删。我调到0.5效果更好。max_det单张图最大检测数默认300。操场场景下人数可能上千这个值要调大我设成2000。4.2 小目标检测的切片推理方案如果显存不够跑1280或者想进一步提升小目标召回率可以用SAHISlicing Aided Hyper Inference切片推理。原理是把大图切成重叠的小块每块单独检测最后合并结果。from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathbest.pt, confidence_threshold0.2, devicecuda:0 ) result get_sliced_prediction( test_image.jpg, detection_model, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2 )切片推理的代价是速度。一张1920×1080的图切成640×640的块大约需要6到9块推理时间变成原来的6到9倍。如果对实时性要求高不建议用如果是离线分析切片推理能明显提升小目标召回。4.3 误检与漏检的针对性优化实际跑下来最常见的两类错误是把跑道上的红色标记误检成人以及人群密集处漏检。误检优化收集误检样本加入训练集作为负样本。具体做法是把误检区域的图片裁出来不标注任何目标作为背景图加入训练。YOLO会把这类图的所有区域当负样本学会抑制类似特征。漏检优化漏检通常发生在遮挡严重或者目标极小的区域。除了提高输入分辨率还可以用测试时增强TTA。TTA对同一张图做多种变换翻转、缩放分别推理再合并结果。YOLOv8支持TTA在predict里加augmentTrue即可。代价是推理速度变成3倍左右。4.4 模型量化与加速部署如果要在边缘设备上部署比如Jetson Nano或者树莓派模型需要量化。YOLOv8支持导出ONNX和TensorRT。yolo export modelbest.pt formatengine halfTrue device0halfTrue表示FP16量化速度提升约1.5倍精度损失很小。如果要INT8量化需要提供校准数据集精度损失会大一些但速度提升更明显。注意量化后的模型在小目标检测上精度下降比大目标更明显。如果发现量化后漏检严重建议回退到FP16或者FP32。5. 常见问题排查与避坑指南5.1 训练不收敛的五个原因原因一学习率太大。表现是loss剧烈震荡mAP不升反降。解决方法是把lr0降到0.0005或者0.0001。原因二数据标注有问题。表现是loss缓慢下降但mAP一直很低。解决方法是可视化标注框检查是否有大量漏标或错标。原因三batch size太小。表现是loss震荡BN层统计不稳定。解决方法是增大batch或者用梯度累积。原因四预训练权重不匹配。如果用了COCO预训练的YOLOv8但数据集类别数不同需要确保模型正确加载。YOLOv8会自动处理但如果你手动改过配置文件要检查nc参数。原因五数据增强太激进。马赛克、缩放、色彩抖动同时开很大模型学不到稳定特征。解决方法是逐步降低增强强度观察mAP变化。5.2 验证集mAP高但实际效果差这是典型的数据泄漏问题。前面说过航拍视频抽帧的图片高度相似。如果训练集和验证集里有同一段视频的相邻帧验证集mAP会虚高。排查方法计算训练集和验证集图片的相似度。用感知哈希或者简单的像素差如果发现大量高相似度对说明划分有问题。解决方法是按视频重新划分。5.3 推理速度慢的优化路径推理速度慢按以下顺序排查输入分辨率是不是太高1280降到960速度提升约1.8倍。模型是不是太大YOLOv8s换YOLOv8n速度提升约2倍。有没有用TTA关掉augment速度提升3倍。有没有用切片推理关掉SAHI速度提升6到9倍。有没有导出TensorRT导出后速度提升1.5到2倍。5.4 常见问题速查表问题现象可能原因排查方法解决方案loss震荡不下降学习率太大观察loss曲线降低lr0到0.0005mAP50高但mAP50-95低定位精度差可视化预测框提高输入分辨率验证集mAP虚高数据泄漏检查图片相似度按视频重新划分小目标漏检严重输入分辨率低统计目标尺寸用1280或切片推理误检多负样本不足收集误检样本加入背景图训练推理速度慢模型大/分辨率高计时各环节量化或换小模型训练中断显存不足看OOM报错降batch或分辨率模型不收敛标注错误可视化标注修正标注5.5 几个容易被忽略的细节细节一图片格式统一。数据集里可能混有jpg和png训练时读取速度不一致。建议统一转成jpg减少IO开销。细节二EXIF方向。有些航拍图片带EXIF旋转信息用OpenCV读取时不会自动旋转导致图片和标注不对应。用PIL读取并应用EXIF旋转或者批量去除EXIF。细节三标签文件编码。YOLO标签是纯文本但有些系统保存时带了BOM头导致解析失败。用utf-8-sig编码读取可以避免。细节四类别名称映射。data.yaml里的names要和标注的class_id对应。如果标注只有0类names就写[person]不要多写。6. 数据集扩展与迁移应用6.1 从校园操场到其他场景的迁移这个数据集训练出来的模型直接用到其他航拍场景效果会打折扣。但通过微调可以快速迁移。迁移到广场人群检测广场地面材质和操场不同但人体尺度接近。用500张广场图片微调50轮mAP能恢复到0.85以上。迁移到海滩人体检测海滩背景单一但人体姿态多样躺、坐、跑。需要补充大量躺姿样本否则漏检严重。迁移到交通路口行人检测视角从俯视变成斜视人体尺度变大但遮挡更严重。建议重新训练而不是微调。6.2 结合其他数据集提升泛化性单一数据集训练容易过拟合。我通常会把航拍人体数据集和以下数据集混合训练VisDrone无人机视角目标检测数据集包含行人、车辆等类别。UAVDT无人机目标检测数据集场景多样。COCO通用目标检测数据集提供丰富的背景和姿态。混合比例建议是航拍人体数据集占60%其他占40%。这样模型既能学到航拍小目标的特征又能保持对多样场景的泛化能力。6.3 从检测到跟踪的扩展人体检测是上游任务下游可以做多目标跟踪。用YOLO检测每一帧的人体再用ByteTrack或者OC-SORT做帧间关联就能得到每个人的运动轨迹。from ultralytics import YOLO import cv2 model YOLO(best.pt) cap cv2.VideoCapture(campus.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break results model.track(frame, persistTrue, trackerbytetrack.yaml) annotated results[0].plot() cv2.imshow(track, annotated) if cv2.waitKey(1) 0xFF ord(q): break跟踪稳定后可以进一步做人数统计、轨迹分析、异常行为检测。这些应用在校园安全管理中很有价值。6.4 数据标注的自动化辅助如果要把这个数据集扩展到新场景标注是个体力活。可以用训练好的模型做预标注人工修正能省70%以上的时间。流程是用当前模型推理新图片导出YOLO格式的预测结果导入标注工具如LabelImg、CVAT人工调整。模型预测的框虽然不完美但比从零画框快得多。实操心得预标注的置信度阈值设低一点比如0.1宁可多框一些人工删比人工画快。另外预标注结果要按置信度排序优先修正高置信度的错误低置信度的直接删掉重画。7. 我个人的一些实操体会这个数据集我前前后后用了大半年踩过的坑不少有几个体会比较深。第一不要迷信大模型。我一开始用YOLOv8x想着模型大精度高结果训练了300轮mAP还不如YOLOv8s。后来分析发现数据集只有几千张图大模型参数量太大严重过拟合。换回YOLOv8s加了点数据增强mAP反而涨了3个点。第二输入分辨率比模型结构重要。我做过对比实验同样YOLOv8s640输入mAP50是0.781280输入是0.91。提升非常明显。所以如果你的小目标检测效果不好先别急着改模型结构把输入分辨率提上去试试。第三验证集划分要按视频切。这个坑我踩得最惨。一开始随机划分验证集mAP0.95实际部署到新视频上只有0.6。后来按视频重新划分验证集mAP降到0.88但实际效果对上了。虚高的指标比低指标更害人。第四负样本很重要。操场上的篮球架、看台座椅、跑道标记都容易被误检成人。我专门收集了200张只有这些物体的图片不标注任何目标加入训练集。误检率直接降了一半。最后分享一个小技巧如果训练资源有限可以先在COCO上预训练的YOLOv8权重基础上冻结主干网络只训练检测头20轮再解冻全部微调80轮。这样比从头训练收敛快最终精度也差不多。我在只有一张V100的时候经常这么干能省不少时间。
返回列表