1. 为什么选择YOLOv5处理VisDrone数据集VisDrone作为目前最大的公开无人机航拍数据集包含了各种复杂场景下的目标检测任务。但直接将YOLOv5用于VisDrone会遇到几个典型问题首先是数据格式差异VisDrone采用类似PASCAL VOC的标注方式而YOLOv5需要特定的txt格式其次是目标尺度变化大无人机俯拍视角下的小目标检测是个挑战最后是类别定义不同需要重新映射。我在实际项目中测试过YOLOv5的轻量级版本在VisDrone上能达到不错的平衡。比如YOLOv5s模型在Titan Xp显卡上训练时batch_size16的情况下显存占用不到8GB推理速度能达到45FPS这对无人机端侧部署很友好。下面这张表格对比了几个常用模型在VisDrone验证集上的表现模型mAP0.5参数量(M)推理速度(FPS)YOLOv5s0.3127.245YOLOv5m0.35621.232Faster R-CNN0.298136.512从数据可以看出YOLOv5在精度和速度上都有优势。特别是考虑到无人机平台的算力限制YOLOv5s/m版本是更实用的选择。2. 数据准备与格式转换2.1 下载和解压原始数据集VisDrone数据集官网提供了完整的下载包包含训练集6,471张、验证集548张和测试集1,610张。我建议新建一个标准化的目录结构VisDrone/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/解压后你会发现标注文件是.txt格式但内容与YOLOv5要求的格式不同。VisDrone的原始标注每行包含bbox_left,bbox_top,bbox_width,bbox_height,score,category,truncation,occlusion2.2 编写转换脚本我们需要将原始标注转换为YOLOv5格式category_id x_center y_center width height这里有个坑要注意VisDrone有10个原始类别但YOLOv5默认使用COCO的80类。我们需要建立映射关系。以下是我使用的Python转换脚本核心部分import os from pathlib import Path def convert(size, box): dw 1./size[0] dh 1./size[1] x (box[0] box[2]/2.) * dw y (box[1] box[3]/2.) * dh w box[2] * dw h box[3] * dh return (x,y,w,h) # 类别映射表 category_map { 1: 0, # pedestrian - person 2: 0, # person - person 3: 1, # bicycle 4: 2, # car # 其他类别映射... } for img_file in Path(VisDrone/images/train).glob(*.jpg): txt_path fVisDrone/labels/train/{img_file.stem}.txt with open(txt_path, w) as out_file: # 处理每个标注框...注意VisDrone中ignored regionsscore0应该被过滤掉否则会影响训练效果。3. 模型配置与训练3.1 修改YOLOv5配置文件首先克隆最新版YOLOv5仓库git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt然后需要修改两个关键文件data/visdrone.yaml新建# VisDrone数据集配置 train: ../VisDrone/images/train val: ../VisDrone/images/val # 类别数和名称 nc: 8 # 根据你的映射结果调整 names: [person, bicycle, car, van, truck, tricycle, awning-tricycle, bus]models/yolov5s.yaml复制后修改# 主要调整anchor尺寸因为无人机视角下目标较小 anchors: - [5,6, 8,14, 15,11] # P3/8 - [10,13, 16,30, 33,23] # P4/16 - [30,61, 62,45, 59,119] # P5/323.2 启动训练使用以下命令开始训练python train.py --img 640 --batch 16 --epochs 100 --data data/visdrone.yaml \ --cfg models/yolov5s.yaml --weights yolov5s.pt --name visdrone_exp几个关键参数说明--img 640输入图像尺寸无人机图像通常较大可以尝试增大到1024--batch 16根据显存调整11G显存建议1624G可以尝试32--epochs 100VisDrone数据量较大建议至少50个epoch训练过程中如果出现显存不足可以尝试减小batch_size使用--multi-scale参数启用多尺度训练添加--adam使用Adam优化器替代SGD4. 模型优化技巧4.1 小目标检测增强无人机图像中小目标占比很高我推荐以下几种优化方法多尺度训练python train.py --multi-scale --img 640-1024修改检测头 在模型配置中增加小目标检测层head: [[-1, 1, Conv, [256, 1, 1]], [-1, 1, nn.Upsample, [None, 2, nearest]], [[-1, 6], 1, Concat, [1]], # cat backbone P4 [-1, 3, C3, [256, False]], # 新增的小目标检测层 [-1, 1, Conv, [256, 3, 2]], [[-1, 4], 1, Concat, [1]], # cat head P5 [-1, 3, C3, [512, False]], ...]数据增强策略 在data/hyps/hyp.scratch-low.yaml中调整mosaic: 1.0 # 马赛克增强保持开启 mixup: 0.1 # 适当降低mixup比例 hsv_h: 0.015 # 色相增强 hsv_s: 0.7 # 饱和度增强 hsv_v: 0.4 # 明度增强4.2 模型量化与部署为了在无人机嵌入式设备上部署可以使用PyTorch的量化功能import torch from torch.quantization import quantize_dynamic model torch.load(yolov5s_visdrone.pt) model.eval() # 动态量化 quantized_model quantize_dynamic( model, {torch.nn.Linear, torch.nn.Conv2d}, dtypetorch.qint8 ) torch.save(quantized_model, yolov5s_visdrone_quant.pt)实测下来量化后的模型在Jetson Xavier NX上推理速度能提升35%而精度损失不到2%。如果使用TensorRT进一步优化FPS还能再提升50%以上。5. 常见问题排查在适配VisDrone过程中我遇到过几个典型问题标注偏移由于原始标注的bbox_left/top是绝对坐标而YOLOv5需要归一化中心坐标。检查转换脚本时发现有个别图像尺寸读取错误导致标注框偏移。解决方法是在转换前先验证图像尺寸from PIL import Image img Image.open(img_path) width, height img.size # 确保使用实际图像尺寸类别不平衡VisDrone中行人和车辆占比很高其他类别样本较少。我采用了两种策略过采样少数类别使用focal loss修改分类损失权重显存不足当图像尺寸较大时容易出现OOM。除了减小batch_size还可以python train.py --img 1024 --batch 8 --multi-scale --rect使用矩形训练(--rect)能减少padding带来的显存浪费。验证指标异常有时验证mAP会突然下降。这通常是学习率过高或数据增强太强导致的。我的经验是初始学习率设为0.01而不是默认的0.1逐步增加数据增强强度使用--evolve参数进行超参数进化6. 效果评估与可视化训练完成后使用以下命令评估模型python val.py --data data/visdrone.yaml --weights runs/train/visdrone_exp/weights/best.pt对于可视化YOLOv5提供了detect.py脚本python detect.py --source ../VisDrone/images/val/ --weights runs/train/visdrone_exp/weights/best.pt我习惯用以下方法分析结果混淆矩阵查看各类别的混淆情况PR曲线分析不同置信度阈值下的表现目标尺寸分布统计不同尺度目标的检测效果在VisDrone上小目标32x32像素的检测AP通常比大目标低15-20个百分点。针对这个问题可以专门用小目标样本进行微调python train.py --img 1024 --batch 8 --epochs 20 --data data/visdrone.yaml \ --weights runs/train/visdrone_exp/weights/best.pt --name visdrone_small \ --cache ram --obj 0.5 --cls 1.0 --small-only这里的--small-only是我自定义的选项只选择标注框面积小于1024像素的图像进行训练。