拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
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.5,center_y = (540 + 80/2) / 1080 = 0.5,width = 40/1920 = 0.0208,height = 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下batch=16大约占4GB显存,到1280下batch=16就要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_patches=3, max_size=100): 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:y1+size, x1:x1+size] = 0 return image

3.4 损失函数与正负样本分配

YOLOv8用的是TaskAlignedAssigner做正负样本分配,结合分类损失和回归损失。对于小目标检测,我建议关注两个点:

一是分类损失权重。小目标特征弱,分类容易出错,可以适当提高分类损失的权重。在YOLOv8的配置里,可以通过修改cls参数来调整,默认是0.5,我试过调到0.7,召回率有提升。

二是回归损失。YOLOv8用CIoU Loss,对小目标的定位精度还可以。如果发现定位偏差大,可以换成EIoU或者SIoU,但提升有限,不建议花太多时间。

实操心得:小目标检测的瓶颈往往不在损失函数,而在特征图分辨率。YOLOv8的P3特征图是80×80(输入640时),对应8倍下采样。如果输入1280,P3就是160×160,小目标特征保留得更好。所以提高输入分辨率比调损失函数更有效。

3.5 训练参数配置与调参记录

以下是我在V100上训练这个数据集的一套配置,基于YOLOv8s,输入1280,batch=8,训练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.6,50轮左右到0.85,100轮后基本稳定在0.90左右。如果100轮还没到0.85,大概率是学习率或者数据有问题,需要排查。

4. 推理部署与效果优化

4.1 从训练到推理的完整链路

训练完模型,得到best.pt,接下来就是推理。YOLOv8的推理接口很简单:

from ultralytics import YOLO model = YOLO("best.pt") results = model.predict( source="test_video.mp4", imgsz=1280, conf=0.25, iou=0.5, save=True )

但实际部署时,有几个参数需要仔细调。

conf阈值:默认0.25。航拍人体小,模型置信度普遍偏低,我试过0.15到0.3,最终定在0.2。太低误检多,太高漏检多。

iou阈值:NMS的IoU阈值,默认0.7。人群密集时,两个人体框可能重叠度很高,IoU阈值太高会误删。我调到0.5,效果更好。

max_det:单张图最大检测数,默认300。操场场景下人数可能上千,这个值要调大,我设成2000。

4.2 小目标检测的切片推理方案

如果显存不够跑1280,或者想进一步提升小目标召回率,可以用SAHI(Slicing Aided Hyper Inference)切片推理。原理是把大图切成重叠的小块,每块单独检测,最后合并结果。

from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model = AutoDetectionModel.from_pretrained( model_type="yolov8", model_path="best.pt", confidence_threshold=0.2, device="cuda:0" ) result = get_sliced_prediction( "test_image.jpg", detection_model, slice_height=640, slice_width=640, overlap_height_ratio=0.2, overlap_width_ratio=0.2 )

切片推理的代价是速度。一张1920×1080的图,切成640×640的块,大约需要6到9块,推理时间变成原来的6到9倍。如果对实时性要求高,不建议用;如果是离线分析,切片推理能明显提升小目标召回。

4.3 误检与漏检的针对性优化

实际跑下来,最常见的两类错误是:把跑道上的红色标记误检成人,以及人群密集处漏检。

误检优化:收集误检样本,加入训练集作为负样本。具体做法是把误检区域的图片裁出来,不标注任何目标,作为背景图加入训练。YOLO会把这类图的所有区域当负样本,学会抑制类似特征。

漏检优化:漏检通常发生在遮挡严重或者目标极小的区域。除了提高输入分辨率,还可以用测试时增强(TTA)。TTA对同一张图做多种变换(翻转、缩放)分别推理,再合并结果。YOLOv8支持TTA,在predict里加augment=True即可。代价是推理速度变成3倍左右。

4.4 模型量化与加速部署

如果要在边缘设备上部署,比如Jetson Nano或者树莓派,模型需要量化。YOLOv8支持导出ONNX和TensorRT。

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

half=True表示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 推理速度慢的优化路径

推理速度慢,按以下顺序排查:

  1. 输入分辨率是不是太高?1280降到960,速度提升约1.8倍。
  2. 模型是不是太大?YOLOv8s换YOLOv8n,速度提升约2倍。
  3. 有没有用TTA?关掉augment,速度提升3倍。
  4. 有没有用切片推理?关掉SAHI,速度提升6到9倍。
  5. 有没有导出TensorRT?导出后速度提升1.5到2倍。

5.4 常见问题速查表

问题现象可能原因排查方法解决方案
loss震荡不下降学习率太大观察loss曲线降低lr0到0.0005
mAP50高但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, persist=True, tracker="bytetrack.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个点。

第二,输入分辨率比模型结构重要。我做过对比实验,同样YOLOv8s,640输入mAP50是0.78,1280输入是0.91。提升非常明显。所以如果你的小目标检测效果不好,先别急着改模型结构,把输入分辨率提上去试试。

第三,验证集划分要按视频切。这个坑我踩得最惨。一开始随机划分,验证集mAP0.95,实际部署到新视频上只有0.6。后来按视频重新划分,验证集mAP降到0.88,但实际效果对上了。虚高的指标比低指标更害人。

第四,负样本很重要。操场上的篮球架、看台座椅、跑道标记,都容易被误检成人。我专门收集了200张只有这些物体的图片,不标注任何目标,加入训练集。误检率直接降了一半。

最后分享一个小技巧:如果训练资源有限,可以先在COCO上预训练的YOLOv8权重基础上,冻结主干网络,只训练检测头20轮,再解冻全部微调80轮。这样比从头训练收敛快,最终精度也差不多。我在只有一张V100的时候经常这么干,能省不少时间。

返回列表