Visdrone数据集配YOLOv5权重:无人机小目标检测训练与调参实战
简介本资源面向无人机航拍目标检测的学习者与工程实践者提供基于Visdrone数据集的YOLOv5训练成果帮助解决小目标密集场景下模型训练与验证的复现难题。压缩包共126个文件约680.11MB涵盖yaml配置、py源码、pt权重、jpg与png图像、mp4测试视频、xml标注及sh脚本等结构完整便于直接部署与二次开发。资源内含YOLOv5s-visdrone.pt与yolov5m-visdrone.pt两个训练权重并附训练曲线、相关场景测试视频以及yolov5-5.0完整代码可直观对比不同规模模型在航拍视角下的检测表现。目前已有4358人学习下载适合希望快速验证算法、分析训练过程或搭建无人机视觉应用的中高级开发者参考。1. Visdrone 数据集配 YOLOv5 权重无人机视角检测到底难在哪Visdrone 数据集配上 YOLOv5 训练权重是无人机航拍目标检测里被问得最多的一套组合。Visdrone 由无人机在城区、广场、路口等场景拍摄标注了行人、车辆、三轮车、遮阳棚等十类目标特点是目标极小、密度极高、遮挡严重。用 COCO 预训练权重直接推理 Visdrone 图片行人往往只剩几个像素模型几乎全漏。所以拿到一份 yolov5-5.0-visdrone.zip 这类训练权重真正要搞清楚的是三件事它基于哪个 YOLOv5 版本、在什么数据划分上训的、推理时该配多大的输入尺寸。这篇笔记按「数据准备 → 权重加载 → 训练复现 → 调参避坑 → 进阶验证」的顺序讲透新手能照着跑通熟手能看清边界和参数取舍。2. Visdrone 数据集的标注格式与 YOLOv5 训练集转换2.1 Visdrone 原始标注长什么样Visdrone 官方给的是 MOT/检测两套标注检测任务里每个图片对应一个 txt每行格式是bbox_left,bbox_top,bbox_width,bbox_height,score,object_category,truncation,occlusion注意这是左上角坐标加宽高的绝对像素值不是归一化中心点格式。object_category 的取值是 0 到 11其中 0 和 11 是忽略区域1 到 10 才是有效类别。很多人第一次转数据就翻车在这里直接把 category 当类别索引减一结果 0 号忽略类混进了训练集模型学出一堆噪声框。YOLOv5 要的是每行class x_center y_center width height且全部归一化到 0 到 1。所以转换要做四件事过滤忽略类、坐标转中心点、除以图像宽高、类别索引重映射。2.2 转换脚本与四个边界坑下面这个脚本我一般直接放在数据集根目录跑输入是 Visdrone 的 annotations 目录和 images 目录import os import cv2 # Visdrone 有效类别索引 0 和 11 是忽略区域直接丢弃 VALID_CATS {1: 0, 2: 1, 3: 2, 4: 3, 5: 4, 6: 5, 7: 6, 8: 7, 9: 8, 10: 9} def convert(ann_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for name in os.listdir(ann_dir): if not name.endswith(.txt): continue img_path os.path.join(img_dir, name.replace(.txt, .jpg)) img cv2.imread(img_path) if img is None: continue # 图片缺失直接跳过别让脚本崩 h, w img.shape[:2] lines [] with open(os.path.join(ann_dir, name)) as f: for row in f: p row.strip().split(,) if len(p) 8: continue x, y, bw, bh map(float, p[:4]) cat int(p[5]) if cat not in VALID_CATS: continue # 丢弃忽略类和无效类 # 越界裁剪Visdrone 里有少量框超出图像边界 x1, y1 max(0, x), max(0, y) x2, y2 min(w, x bw), min(h, y bh) if x2 - x1 2 or y2 - y1 2: continue # 过滤掉裁剪后小于 2 像素的框 cx (x1 x2) / 2 / w cy (y1 y2) / 2 / h nw (x2 - x1) / w nh (y2 - y1) / h lines.append(f{VALID_CATS[cat]} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}) with open(os.path.join(out_dir, name), w) as f: f.write(\n.join(lines)) convert(annotations, images, labels)逻辑说明先读图拿真实宽高因为 Visdrone 不同序列分辨率不一致不能写死。类别映射用字典而不是减一是因为原始索引不连续。坐标裁剪这一步很关键Visdrone 标注里确实存在框超出边界的情况不裁剪归一化后会出负值YOLOv5 训练时 dataloader 会直接报错。参数说明VALID_CATS按你实际类别数改如果只做行人和车两类就只保留 1 和 4。2 像素这个阈值是经验值Visdrone 里大量目标本身就 5 到 10 像素阈值设太大反而把有效小目标删了。2.3 目录结构与 data.yaml转换完按 YOLOv5 的标准布局放visdrone/ images/train/ images/val/ labels/train/ labels/val/data.yaml 里写path: /data/visdrone train: images/train val: images/val nc: 10 names: [pedestrian,people,bicycle,car,van,truck,tricycle,awning-tricycle,bus,motor]提示names 的顺序必须和 VALID_CATS 的值一一对应顺序错了模型能训但类别全乱验证时 mAP 看着还行实际框全标错类。3. 加载 yolov5-5.0-visdrone 权重做推理与训练复现3.1 权重文件怎么用推理最小命令拿到 yolov5-5.0-visdrone.zip 解压后通常是一个 .pt 文件。YOLOv5 5.0 版本的权重加载方式和后续 6.x、7.x 有差异5.0 用的是models/yolov5s.yaml配--weights且torch.load默认走 pickle。先跑推理验证权重是否可用git clone -b v5.0 https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt python detect.py --weights yolov5-5.0-visdrone.pt \ --source /data/visdrone/images/val \ --img 1280 --conf-thres 0.25 --iou-thres 0.45 \ --device 0逻辑说明-b v5.0必须显式指定分支否则默认拉最新版模型定义对不上会报KeyError或unexpected key。--img 1280是 Visdrone 的关键官方默认 640 对无人机小目标太小1280 起步显存够就上 1536。参数说明--conf-thres在 Visdrone 上建议 0.25 到 0.3太低会出大量误检--iou-thres0.45 到 0.5密集场景 NMS 阈值调高能保住挨着的行人。3.2 用这份权重继续训练如果要在自己补充的数据上微调用--weights加载而不是--cfgpython train.py --weights yolov5-5.0-visdrone.pt \ --data data/visdrone.yaml \ --img 1280 --batch-size 8 --epochs 100 \ --hyp data/hyp.visdrone.yaml \ --device 0 --workers 8逻辑说明--weights会把骨干和检测头一起加载相当于在 Visdrone 预训练基础上继续学。如果只想冻结骨干加--freeze 10冻结前 10 层适合小数据集防过拟合。参数说明--batch-size 8是 1280 输入下 11G 显存的保守值24G 卡可以上 16。--workers按 CPU 核数给给太高反而因为 IO 争抢变慢。3.3 超参数文件里 Visdrone 必须改的几项YOLOv5 默认 hyp 是给 COCO 调的Visdrone 要动这几个参数默认值Visdrone 建议原因anchorsCOCO 三组重聚类小目标 anchor 要更小mosaic1.00.5~1.0增强小目标但过高会引入拼接伪影scale0.50.9多尺度缩放对小目标友好fl_gamma0.01.5焦点损失缓解正负样本失衡lr00.010.005微调时降学习率防震荡anchor 重聚类用 YOLOv5 自带的 kmeanspython utils/autoanchor.py --data data/visdrone.yaml --img 1280注意autoanchor 跑之前先把 data.yaml 的 nc 和 names 配对否则聚类出来的 anchor 数量对不上检测头。4. Visdrone 训练避坑五条血泪排查记录4.1 现象mAP 一直 0.1 以下loss 不降原因输入尺寸还是 640Visdrone 目标平均 20 像素以内640 下缩到 10 像素特征图根本提不出来。解决--img提到 1280 或 1536同时 batch 相应调小配合--rect减少 padding 浪费。4.2 现象训练几十轮后大量空框、误检原因忽略类没过滤干净或者类别索引映射错位。Visdrone 的 0 和 11 类如果混进去模型会学出无意义目标。解决回查转换脚本确认VALID_CATS只保留 1 到 10且 names 顺序和映射值一致。4.3 现象验证集 mAP 正常实际推理全是重叠框原因NMS 的 iou-thres 用了默认 0.45Visdrone 密集场景下相邻目标框重叠度高被误删或保留错误。解决推理时--iou-thres 0.6训练时--label-smoothing 0.1缓解。4.4 现象显存溢出batch 降到 2 还 OOM原因1280 输入下 YOLOv5 的中间特征图占用大加上 mosaic 增强会同时载入 4 张图。解决--img 1280 --batch-size 4配合--accumulate 4做梯度累积等效 batch 16显存只占 4 的量。4.5 现象加载权重报RuntimeError: Error(s) in loading state_dict原因权重是 5.0 版本代码拉成了 6.x 或 7.x模型结构变了。解决git checkout v5.0或git clone -b v5.0确认models/yolov5s.yaml的 anchor 数量和权重一致。5. 进阶用 TTA 和切片推理把 Visdrone 小目标 mAP 再抬一截Visdrone 的瓶颈始终在小目标。常规做法是加大输入但显存有上限。我一般会叠两个技巧TTA测试时增强和切片推理。TTA 在 YOLOv5 里直接开python detect.py --weights yolov5-5.0-visdrone.pt \ --source /data/visdrone/images/val \ --img 1536 --augment --conf-thres 0.3--augment会对每张图做翻转、缩放多尺度推理再融合mAP 通常能涨 1 到 2 个点代价是推理慢 3 倍左右。适合离线批量跑不适合实时。切片推理针对超大分辨率航拍图把图切成带重叠的小块分别推理再合并import cv2 import numpy as np def slice_infer(img, model, size1280, overlap200): h, w img.shape[:2] results [] step size - overlap for y in range(0, h, step): for x in range(0, w, step): patch img[y:ysize, x:xsize] if patch.shape[0] size or patch.shape[1] size: patch cv2.copyMakeBorder(patch, 0, size-patch.shape[0], 0, size-patch.shape[1], cv2.BORDER_CONSTANT, value(114,114,114)) pred model(patch) # 你的推理封装 # 把 patch 坐标映射回原图再做全局 NMS results.append((pred, x, y)) return results # 后续做坐标偏移 全局 NMS逻辑说明重叠 200 像素是为了避免目标正好被切在边界上合并时用全局 NMS 去重。参数说明size和训练输入保持一致overlap取目标平均尺寸的 2 到 3 倍Visdrone 上 200 够用。验证方法上别只看 mAP0.5Visdrone 更该盯 mAP0.5:0.95 和小目标子集的 AP。我习惯把验证集按目标面积分三档统计小目标档的 AP 才是这份权重真正的成色。跑完一轮如果小目标 AP 低于 0.15说明输入尺寸或 anchor 还没调到位别急着加 epoch。我自己踩过最深的坑是迷信大 epoch。Visdrone 上 300 epoch 和 100 epoch 的差距远不如把输入从 640 提到 1280 来得大。先把尺寸、anchor、忽略类这三件事做对再谈调参。希望帮到你。本文还有配套的精品资源点击获取