拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于VisDrone的农业机械目标检测:YOLO数据集训练与调参实战

简介这份资源是面向无人机俯视视角农业场景的目标检测数据集适合从事智慧农业、农机识别、行人检测等方向的研究者与算法工程师使用。数据集包含1000余张农场航拍图像标注类别涵盖car、people、tractor、van四类目录已按train、val、test划分完毕并附带data.yaml配置文件yolov5、yolov7、yolov8等主流框架可直接加载训练省去自行整理与划分数据的时间成本。压缩包共2000个文件其中497张jpg图像、1502个txt标注文件及1个yaml配置整体约522.36MB结构清晰便于快速接入训练流程。目前已有451人学习下载可作为农业机械与行人检测任务的基线数据帮助读者验证模型在俯视小目标场景下的表现并对照检测结果进行调优与复现。1. 农场里的农机检测VisDrone 数据集为什么值得单独拎出来做无人机在农田上空飞一圈回来把视频拆帧、跑一遍检测把拖拉机、收割机、播种机这些农业机械框出来——这件事听起来简单真正动手的人第一周就会卡在数据上。公开的通用检测数据集里农田场景的农机样本少得可怜COCO 里带 tractor 标签的图不到千张而且大多是欧洲公路边的摆拍跟国内农场那种地块零碎、机具遮挡、航拍俯视的视角完全对不上。VisDrone 系列本来就是无人机视角的数据集标注密度高、小目标多把它的标注体系迁移到农业机械上是目前做农机检测最省事的一条路。这个标题里的 yolo-1.zip 指向的是一份已经整理成 YOLO 训练格式的数据包省掉了从原始标注转换的那一步。它解决的核心问题是让你在半天内跑通一个能识别农场农机的检测器而不是花两周去凑数据。适合两类人——一类是想快速验证农机检测可行性的算法同学一类是手里有无人机、想给自家农场做机具统计的工程人员。下面从数据长什么样、怎么配环境、怎么训练、怎么调参、坑在哪一步步讲清楚。2. 拆开这份农机数据集目录结构、类别定义与标注质量2.1 YOLO 格式数据集的目录长什么样拿到一个 YOLO 格式的数据包第一件事不是急着训练而是把目录结构看清楚。标准结构是 images 和 labels 两个平行目录各自再分 train、val、test 三个子集图片和标注文件同名只是扩展名不同。VisDrone 原始数据是 MOT 风格的 txt 标注转成 YOLO 格式后每行是class_id x_center y_center width height坐标全部归一化到 0 到 1 之间。# 典型的 YOLO 数据集目录结构先 tree 一下看清楚 dataset/ ├── images/ │ ├── train/ # 训练集图片jpg 或 png │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片 ├── labels/ │ ├── train/ # 与 images/train 一一对应的 txt │ ├── val/ │ └── test/ └── data.yaml # 类别名和路径配置这个结构不是随便定的Ultralytics 的 YOLOv8 默认就按这个约定去找文件。如果你把 labels 和 images 混在一起训练脚本会在第一个 epoch 报 No labels found而且不会告诉你具体缺哪个文件只会给一个笼统的警告。我一般会先跑一段脚本核对图片和标注的数量是否一致不一致的直接定位出来。import os img_dir dataset/images/train lbl_dir dataset/labels/train imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir)} lbls {os.path.splitext(f)[0] for f in os.listdir(lbl_dir)} print(图片数:, len(imgs), 标注数:, len(lbls)) print(有图无标注:, imgs - lbls) # 这些图会被当成负样本通常要删掉 print(有标注无图:, lbls - imgs) # 这些标注是脏数据必须删逻辑说明用集合差集找出不匹配的文件。参数上没什么可调的关键是看输出——如果 有图无标注 数量超过总数的 5%说明数据整理环节出了问题可能是某批图漏标了直接拿去训练会让模型学到错误的背景。VisDrone 原始数据里有些帧是纯背景转换时容易被误删或误留这一步必须人工确认。2.2 类别定义农业机械到底分几类VisDrone 原始类别是 pedestrian、people、bicycle、car、van、truck、tricycle、awning-tricycle、bus、motor 这十类里面没有专门的农业机械。做农机检测时常见的做法是把 car、van、truck 这三类合并或重映射再补上 tractor、harvester、seeder 这些农机类别。这份数据包既然叫 农业机械目标检测数据集说明类别已经重定义过了你需要打开 data.yaml 确认。# data.yaml 示例类别顺序决定 class_id path: ./dataset train: images/train val: images/val test: images/test nc: 4 # 类别数量必须和 names 长度一致 names: 0: tractor # 拖拉机 1: harvester # 收割机 2: seeder # 播种机 3: other_machinery # 其他农机参数说明nc 是类别数names 的键必须从 0 连续编号中间不能跳号。我见过有人把 names 写成0: tractor, 2: harvester训练不报错但 harvester 永远检测不出来因为模型输出的 class_id 是连续的跳号会导致标签错位。类别顺序一旦定下来后面所有标注、训练、推理都要一致中途改类别顺序等于把之前训的权重全废掉。类别粒度是个需要权衡的点。分得太细比如把 轮式拖拉机 和 履带拖拉机 分开样本量不够模型学不动分得太粗全归成 machine那检测出来也没法做机具统计。我的经验是农机检测分 3 到 5 类比较合适覆盖主要机具类型剩下的归到 other。VisDrone 的标注密度高一张图里可能有几十个目标类别合并后小目标之间的区分度反而更好。2.3 标注质量怎么快速抽查数据包里的标注不一定干净尤其是从 VisDrone 迁移过来的框的位置和类别都可能有问题。训练前花二十分钟抽查比训到一半发现 loss 不降要划算得多。最直接的办法是把标注画回图上肉眼扫一遍。import cv2 import os def draw_yolo_label(img_path, lbl_path, names): img cv2.imread(img_path) h, w img.shape[:2] with open(lbl_path) as f: for line in f: cid, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, names[int(cid)], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) return img names [tractor, harvester, seeder, other_machinery] img draw_yolo_label(dataset/images/train/0001.jpg, dataset/labels/train/0001.txt, names) cv2.imwrite(check_0001.jpg, img)逻辑说明把归一化坐标还原成像素坐标画框并标类别名。参数上注意bw和bh是宽高而不是右下角坐标这是 YOLO 格式和 VOC 格式最容易搞混的地方。抽查时重点看三类问题框是否贴紧目标、类别是否标错、有没有漏标的小目标。VisDrone 的航拍图里农机经常被树冠或建筑遮挡标注时容易漏漏标比错标危害更大因为模型会把漏标的目标当成背景来学。3. 从零配环境到跑通第一次训练3.1 环境配置Anaconda 加 Ultralytics 的最小依赖YOLO 环境搭建的坑主要集中在 CUDA 版本和 PyTorch 版本的匹配上。我一般用 Anaconda 建独立环境避免和系统里的其他 Python 包打架。YOLOv8 对 PyTorch 版本不算挑剔但 CUDA 版本必须和显卡驱动对得上这一步错了后面全是玄学报错。# 创建环境Python 版本选 3.9 或 3.10 都行 conda create -n farm_yolo python3.10 -y conda activate farm_yolo # 装 PyTorchcu118 对应 CUDA 11.8按自己显卡驱动选 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 装 ultralytics它会自动带上 opencv、numpy 等依赖 pip install ultralytics # 验证 GPU 是否可用 python -c import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))参数说明--index-url指定 PyTorch 官方源比默认源快很多。如果输出是True加显卡型号说明环境通了如果是False先别急着训去查显卡驱动版本和 CUDA 版本是否匹配。我踩过的坑是驱动太老CUDA 11.8 装上了但is_available()返回 False升级驱动后解决。这一步没有后悔药环境不通就往下走训练时会报一堆看不懂的错。3.2 用命令行跑通第一次训练环境通了之后第一次训练不要一上来就调参先用默认配置跑 10 个 epoch确认整条链路能走通。Ultralytics 的命令行接口很直接指定 data.yaml、模型和轮数就行。# 用 yolov8n 预训练权重跑 10 轮先验证流程 yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ epochs10 \ imgsz640 \ batch16 \ device0 \ projectruns/farm \ namebaseline参数说明modelyolov8n.pt是 nano 版本参数量最小适合先跑通流程imgsz640是输入分辨率VisDrone 的小目标多后面可以提到 1280batch16看显存调8G 显存跑 640 分辨率大概能到 16跑 1280 就得降到 4device0指定第一块 GPU。训练日志会实时打印 box_loss、cls_loss、mAP50 这些指标第一次跑重点看 loss 有没有下降趋势mAP 有没有从 0 往上走。如果 10 轮下来 mAP 一直是 0八成是 data.yaml 路径写错了或者类别对不上。3.3 训练日志里该盯哪几个数训练跑起来之后日志刷得很快但真正需要盯的就几个数。box_loss 是边界框回归损失cls_loss 是分类损失dfl_loss 是分布焦点损失这三个加起来是总损失。正常情况下三个 loss 都应该是下降的如果 cls_loss 不降反升通常是类别标注有问题或者类别不平衡太严重。mAP50 和 mAP50-95 是评估指标前者是 IoU 阈值 0.5 时的平均精度后者是 0.5 到 0.95 每隔 0.05 取一次再平均。农机检测里 mAP50 能到 0.7 以上就算可用mAP50-95 一般会低不少因为小目标的框位置很难卡得特别准。VisDrone 这类航拍数据小目标占比高mAP50-95 偏低是正常的不用因为这个就怀疑模型有问题。还有一个容易被忽略的数是 instances表示每个 batch 里的目标数量。如果这个数波动特别大比如一个 batch 有 200 个目标下一个只有 5 个说明数据里长尾分布严重训练会不稳定。常见做法是调整采样策略或者对稀疏样本做增强但第一次训练先不用管跑通再说。4. 参数怎么调让小目标农机检测真正可用4.1 输入分辨率与 batch 的取舍VisDrone 的图是无人机拍的单张图里农机可能只占几十个像素640 分辨率下这些目标缩到更小模型很难学到特征。把 imgsz 提到 1280 甚至 1536小目标的召回率会有明显提升代价是显存占用翻倍、训练速度变慢。# 提高分辨率重训batch 相应调小 yolo detect train \ datadataset/data.yaml \ modelyolov8s.pt \ epochs100 \ imgsz1280 \ batch4 \ device0 \ projectruns/farm \ namehighres参数说明model从 n 换成 s参数量大一些对小目标的表达能力更强imgsz1280是权衡后的值再往上显存吃不消batch4是 8G 显存跑 1280 的极限显存更大的可以往上加。这里有个血泪经验batch 太小会导致 BatchNorm 统计不准训练不稳定如果显存允许尽量把 batch 保持在 8 以上实在不行就换更小的模型或者降分辨率。4.2 置信度门限与 NMS 的调整训练完推理时置信度门限conf和 NMS 的 IoU 门限iou直接决定检测结果。默认 conf 是 0.25iou 是 0.7但农机检测里这两个值需要根据场景调。农场场景里农机经常挨在一起比如收割机和运粮车并排iou 设太高会把其中一个框吞掉。# 推理时调整门限 yolo detect predict \ modelruns/farm/highres/weights/best.pt \ sourcetest_images/ \ conf0.35 \ iou0.5 \ saveTrue参数说明conf0.35比默认高是为了压掉背景误检农场里田埂、水渠这些纹理容易被误判成农机iou0.5比默认低是为了保留挨在一起的目标。这两个值没有标准答案得拿一批测试图反复试。我一般会先固定 iou 调 conf看误检和漏检的平衡点再微调 iou 处理密集目标。边缘部署时误检率高很多时候不是模型的问题而是这两个门限没调对。4.3 数据增强针对航拍农机的几个开关YOLO 默认开了一堆数据增强但有些增强对航拍农机是负作用。比如 mosaic 增强会把四张图拼成一张航拍图拼完之后地块边界错乱模型可能学到错误的上下文。flipud 是上下翻转航拍图上下翻转后视角就不对了农机该有的俯视特征被破坏。# 在 data.yaml 同级建一个 hyps.yaml覆盖默认增强参数 mosaic: 0.5 # 降低 mosaic 概率默认 1.0 太激进 flipud: 0.0 # 关掉上下翻转航拍图不适用 fliplr: 0.5 # 左右翻转保留航拍图左右对称合理 scale: 0.3 # 缩放幅度小目标多可以适当加大 hsv_h: 0.015 # 色调扰动农田光照变化大保留 hsv_s: 0.7 # 饱和度扰动 hsv_v: 0.4 # 明度扰动参数说明这些值不是拍脑袋定的mosaic 降到 0.5 是因为航拍图拼接后语义混乱flipud 关掉是因为俯视视角翻转后不符合物理规律scale 加大是为了让模型适应不同飞行高度下的目标尺度变化。改完这些参数重新训练小目标的召回率通常能涨几个点。注意 hyps.yaml 要通过hyphyps.yaml传给训练命令不传的话还是用默认值。5. 避坑与排查农机检测训练里最容易翻车的几件事5.1 现象训练 loss 正常下降但 mAP 一直是 0原因data.yaml 里的路径是相对路径而训练命令的工作目录和 data.yaml 所在目录不一致导致模型读到了空的验证集。或者 names 的类别数和 nc 对不上标签里的 class_id 超出范围被静默丢弃。解决把 data.yaml 里的 path 改成绝对路径或者训练前cd到 data.yaml 所在目录。用一段脚本检查所有标签文件里的 class_id 最大值是否小于 nc。import os lbl_dir dataset/labels/train max_cid 0 for f in os.listdir(lbl_dir): with open(os.path.join(lbl_dir, f)) as fp: for line in fp: cid int(line.split()[0]) max_cid max(max_cid, cid) print(最大 class_id:, max_cid, nc 应大于:, max_cid)5.2 现象模型在验证集上表现好实际推理时漏检严重原因验证集和实际场景的分布不一致。VisDrone 的验证集可能来自同一批飞行任务光照、高度、地块类型都相似而实际推理的图来自不同时间、不同区域模型没见过的分布就漏检。解决从实际场景里挑一批图人工标一小部分做测试集不要只用数据包自带的 val。如果漏检集中在某个尺度考虑提高输入分辨率或者用 SAHI 这类切片推理方法把大图切成小块分别检测再合并。5.3 现象训练到一半 loss 突然变成 nan原因学习率太大或者 batch 太小导致梯度爆炸。YOLO 默认用 SGD 加余弦退火如果数据里有个别标注框宽高是 0 或者负数计算 loss 时会出现除零。解决先检查标注文件里有没有宽高为 0 的行有就删掉。然后把学习率调小或者把优化器换成 AdamW它对异常梯度的容忍度更高。训练命令加lr00.001显式指定初始学习率。5.4 现象显存溢出报 CUDA out of memory原因imgsz 和 batch 的乘积超过了显存容量。1280 分辨率下 batch8 在 8G 显存上基本必炸。解决优先降 batchbatch 降到 1 还炸就降 imgsz。也可以用ampTrue开混合精度训练显存占用能降三成左右。如果都不想降换 yolov8n 这种小模型参数量少显存需求也低。5.5 现象同一张图多次推理结果不一致原因推理时没有固定随机种子数据增强里的随机部分在推理时仍然生效。或者用了 TTA测试时增强多次推理结果本来就会不同。解决推理时加augmentFalse关掉 TTA并在脚本开头固定torch.manual_seed(42)。如果还是不一致检查是不是开了halfTrue半精度推理在某些显卡上会有数值抖动对精度要求高的场景关掉它。6. 把训练好的农机检测器推到边缘设备上跑训练完拿到 best.pt 只是第一步真正落地得把它推到无人机机载设备或者农场的边缘盒子上。目前常见做法是用 TensorRT 做加速把 PyTorch 权重转成 engine 文件推理速度能翻几倍。转换本身不复杂但版本匹配是个大坑TensorRT 的版本必须和 CUDA、PyTorch 对得上错一个就转不出来。# 导出 ONNX再用 trtexec 转 TensorRT engine yolo export modelruns/farm/highres/weights/best.pt formatonnx opset12 imgsz1280 # 用 TensorRT 自带的 trtexec 转换fp16 精度 trtexec --onnxbest.onnx --saveEnginebest.engine --fp16 --workspace4096参数说明opset12是 ONNX 的算子集版本太低不支持某些算子太高 TensorRT 可能不认--fp16开半精度速度更快但精度略降农机检测里通常可以接受--workspace4096是显存工作空间单位 MB太小会转换失败。转完之后用trtexec --loadEnginebest.engine --shapesimages:1x3x1280x1280跑一下 benchmark看单帧推理耗时。边缘部署时误检率高是另一个常见问题。机载设备算力有限模型可能被量化成 int8精度损失比 fp16 大。我的习惯是先在边缘设备上跑一批测试图把 conf 门限往上提 0.1 到 0.15宁可漏检也别误检因为农场场景里误检一个农机可能触发错误的统计报表比漏检更麻烦。验证方法很简单拿同一批图在服务器和边缘设备上各跑一遍对比检测框数量和类别分布差异超过 10% 就说明量化损失太大得换量化策略或者退回 fp16。这套流程走下来从数据包到能用的农机检测器顺利的话两三天踩坑的话一周。我自己的习惯是每换一个数据集先花半天把数据看透再花半天跑通 baseline剩下的时间全花在调参和验证上。数据质量决定上限参数只决定你能不能摸到那个上限。希望帮到你。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门