YOLOv8无人机航拍牧羊识别:从训练到部署全流程实战

发布时间:2026/10/2 18:46:55
YOLOv8无人机航拍牧羊识别:从训练到部署全流程实战 简介本资源为基于YOLOv8的无人机航拍牧羊目标检测项目代码面向深度学习与计算机视觉方向的学习者、研究者及需要落地航拍牲畜识别方案的开发者。项目围绕无人机视角下的羊群检测任务提供从数据配置、模型训练到推理部署的完整工程结构适合具备一定Python与PyTorch基础的中高级读者参考复现。压缩包共468个文件约26.23MB以227个md说明文档、130个py源码、43个yaml与12个yml配置为主另含pt权重、cpp推理示例、sh脚本、ipynb笔记及少量图片与csv结果文件覆盖训练、验证、导出与多平台部署等环节。按requirements.txt配置环境即可运行。目前已有85人学习关注。读者可据此掌握航拍小目标检测的数据组织方式、YOLOv8训练调参流程、模型推理与C部署思路并借助文档与配置快速搭建可复现的牧羊识别实验环境。1. 无人机航拍牧羊识别这套 YOLOv8 代码到底能解决什么牧区找羊这件事靠人骑马巡山效率极低一片草场转下来大半天羊群散进灌木丛或山坳里肉眼根本数不清。换成无人机航拍单架次覆盖几平方公里但新的问题来了拍回来的视频几百上千帧靠人一帧帧看眼睛看花了也容易漏。这套 YOLOv8 无人机航拍牧羊识别项目代码解决的就是从「航拍画面」到「羊只位置」这一步自动化。它基于 YOLOv8 目标检测框架针对航拍视角下的羊只目标做训练和推理输出每只羊的边界框和置信度。适合两类人一是做智慧牧场、草原巡检的工程团队需要快速搭一个可用的检测基线二是正在学 YOLOv8 落地流程的开发者想拿一个真实场景的数据集和训练脚本跑通全链路。代码包里通常包含数据集配置文件、训练脚本、推理脚本和权重文件拿到手改改路径就能跑。2. 航拍牧羊检测的技术选型为什么是 YOLOv8 而不是别的2.1 航拍场景对检测器的三个硬要求无人机航拍牧羊识别和普通地面拍摄的目标检测有本质区别。第一目标尺度小。无人机飞行高度通常在 30 到 120 米一只羊在 4K 画面里可能只占 40 到 80 像素YOLOv8 的 P3 特征层stride 8刚好能覆盖这个尺度范围再小的目标就得靠 P2 层但 P2 会显著增加计算量。第二背景干扰强。草原纹理、灌木阴影、石头都容易和羊只混淆尤其白羊在枯草背景下的对比度很低。第三实时性要求。无人机图传链路带宽有限检测模型不能太重YOLOv8n 或 YOLOv8s 是比较平衡的选择参数量分别在 3.2M 和 11.2M 左右。YOLOv8 相比 YOLOv5 的核心改动在于C2f 模块替换了 C3 模块梯度分流更充分Anchor-Free 解耦头省去了聚类先验框的步骤对小目标密集场景更友好损失函数用 TaskAlignedAssigner 做正负样本分配训练收敛更稳。这些改动在航拍小目标场景下带来的实际收益是同等参数量下 mAP 通常有 1 到 3 个点的提升而且不需要针对数据集重新聚类 anchor。2.2 模型规格选择与参数对照项目代码一般会提供多个规格的配置选哪个取决于你的部署平台和精度要求。下面这张表是我在实际项目里总结的选型参考模型规格参数量输入尺寸适合场景推理设备参考YOLOv8n3.2M640机载实时推理Jetson Orin NanoYOLOv8s11.2M640地面站后处理GTX 1660 TiYOLOv8m25.9M640/1280高精度离线分析RTX 3060 及以上YOLOv8l43.7M1280科研级精度RTX 3090如果只是跑通流程验证效果建议从 YOLOv8n 加 640 输入尺寸起步训练一轮大概几分钟就能看到 loss 下降。如果追求召回率把输入尺寸提到 1280 再配合 YOLOv8s小目标召回会有明显改善但显存占用大概翻倍。2.3 环境搭建从零到能跑训练项目代码通常要求 Python 3.8 以上、PyTorch 1.8 以上。下面是我在 Ubuntu 20.04 上验证过的环境搭建步骤CPU 版本也能跑推理只是训练会慢很多# 创建虚拟环境避免和系统 Python 冲突 conda create -n yolov8_sheep python3.10 -y conda activate yolov8_sheep # 安装 PyTorch有 GPU 的按 CUDA 版本选没有就用 CPU 版 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装 ultralytics 和项目依赖 pip install ultralytics opencv-python numpy pyyaml tqdm这里有几个参数值得注意。cu118对应 CUDA 11.8如果你的驱动版本较低换成cu117或cu116。ultralytics包自带 YOLOv8 的完整实现不需要单独克隆仓库。安装完成后用yolo checks命令可以验证环境是否正常它会输出 PyTorch 版本、CUDA 可用性和设备信息。提示如果yolo checks报错找不到命令说明 ultralytics 没装进当前环境检查 conda 环境是否激活。3. 数据集准备与标注航拍羊只数据的处理流程3.1 数据采集与标注工具选择航拍牧羊数据集一般来自无人机挂载的可见光相机常见分辨率是 3840×2160 或 1920×1080。采集时建议覆盖不同时间段和光照条件清晨、正午、傍晚各拍一些顺光和逆光都要有这样训练出来的模型泛化能力更强。飞行高度也尽量多样化30 米、60 米、100 米各飞几个架次让模型适应不同尺度的羊只。标注工具用 LabelImg 或 Labelme 都行YOLOv8 需要的是 YOLO 格式的 txt 标注文件每行格式是类别编号 中心x 中心y 宽度 高度坐标全部归一化到 0 到 1 之间。如果手头是 Labelme 的 JSON 格式需要转一道import json import os def labelme_to_yolo(json_path, output_dir, class_names): 将 Labelme JSON 转为 YOLO txt 格式 with open(json_path, r, encodingutf-8) as f: data json.load(f) img_w data[imageWidth] img_h data[imageHeight] lines [] for shape in data[shapes]: label shape[label] if label not in class_names: continue cls_id class_names.index(label) points shape[points] xs [p[0] for p in points] ys [p[1] for p in points] # 计算归一化中心点和宽高 cx (min(xs) max(xs)) / 2.0 / img_w cy (min(ys) max(ys)) / 2.0 / img_h w (max(xs) - min(xs)) / img_w h (max(ys) - min(ys)) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) base os.path.splitext(os.path.basename(json_path))[0] with open(os.path.join(output_dir, base .txt), w) as f: f.write(\n.join(lines))这段代码的逻辑是读取 Labelme 的 JSON 文件提取每个标注框的四个顶点坐标取最小外接矩形再归一化。class_names是类别列表牧羊场景通常只有「sheep」一个类如果还要区分羊羔和成年羊就加两个类别。转换完成后每张图片对应一个同名 txt 文件放在labels目录下。3.2 数据集目录结构与 YAML 配置YOLOv8 要求的数据集目录结构是固定的不能随意改sheep_dataset/ ├── images/ │ ├── train/ # 训练集图片 │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片可选 ├── labels/ │ ├── train/ # 训练集标注 │ ├── val/ # 验证集标注 │ └── test/ # 测试集标注 └── sheep.yaml # 数据集配置文件sheep.yaml的内容如下path: /home/user/sheep_dataset # 数据集根目录 train: images/train # 训练集相对路径 val: images/val # 验证集相对路径 test: images/test # 测试集相对路径 nc: 1 # 类别数量 names: # 类别名称 0: sheep这里path用绝对路径最稳妥相对路径容易因为工作目录变化而找不到文件。nc和names必须对应如果只有羊一个类nc: 1names里只写0: sheep。如果数据集里还有牧羊犬或其他动物按需增加类别编号。3.3 数据增强策略与参数设置航拍数据天然存在样本不均衡问题晴天多、阴天少顺光多、逆光少。YOLOv8 内置了多种数据增强训练时通过参数控制from ultralytics import YOLO model YOLO(yolov8n.pt) model.train( datasheep.yaml, epochs100, imgsz640, batch16, hsv_h0.015, # 色调抖动模拟不同光照 hsv_s0.7, # 饱和度抖动 hsv_v0.4, # 亮度抖动 degrees10.0, # 随机旋转角度 translate0.1, # 随机平移比例 scale0.5, # 随机缩放比例 fliplr0.5, # 水平翻转概率 mosaic1.0, # Mosaic 增强概率 mixup0.1, # Mixup 增强概率 patience20, # 早停耐心值 device0 # GPU 编号CPU 填 cpu )hsv_h、hsv_s、hsv_v这三个参数对航拍场景特别重要因为无人机在不同时间段拍摄的画面色温差异很大。mosaic1.0表示每张图都做 Mosaic 拼接这对小目标检测有好处但训练后期可以降到 0.5 让模型更关注单图特征。patience20表示 20 轮验证集指标不提升就停止训练避免过拟合。4. 训练与推理从权重文件到实际检测效果4.1 训练过程监控与损失曲线解读训练启动后终端会实时输出每轮的 box_loss、cls_loss、dfl_loss 和 mAP 指标。box_loss 是边界框回归损失cls_loss 是分类损失dfl_loss 是分布焦点损失。正常情况下三个 loss 都应该稳步下降如果 cls_loss 震荡剧烈可能是学习率偏大或 batch size 太小。训练完成后runs/detect/train/目录下会生成results.csv和weights/best.pt。用下面的代码画损失曲线import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) df.columns df.columns.str.strip() # 去除列名空格 fig, axes plt.subplots(1, 2, figsize(12, 4)) axes[0].plot(df[epoch], df[train/box_loss], labelbox_loss) axes[0].plot(df[epoch], df[train/cls_loss], labelcls_loss) axes[0].set_xlabel(Epoch) axes[0].set_ylabel(Loss) axes[0].legend() axes[0].set_title(Training Loss) axes[1].plot(df[epoch], df[metrics/mAP50(B)], labelmAP50) axes[1].plot(df[epoch], df[metrics/mAP50-95(B)], labelmAP50-95) axes[1].set_xlabel(Epoch) axes[1].set_ylabel(mAP) axes[1].legend() axes[1].set_title(Validation mAP) plt.tight_layout() plt.savefig(training_curves.png, dpi150)这段代码读取训练日志 CSV分别画损失曲线和 mAP 曲线。重点看 mAP50 是否在后期趋于平稳如果还在上升就说明训练轮数不够可以加大 epochs 继续训。如果 mAP50 很高但 mAP50-95 很低说明框的位置不够准可以适当调高 box_loss 的权重。4.2 推理脚本与批量检测训练好的权重用best.pt推理代码很简洁from ultralytics import YOLO import cv2 model YOLO(runs/detect/train/weights/best.pt) # 单张图片推理 results model(test_image.jpg, conf0.25, iou0.45, imgsz640) for r in results: boxes r.boxes for box in boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() cls int(box.cls[0].item()) print(f类别: {cls}, 置信度: {conf:.2f}, 位置: ({x1:.0f},{y1:.0f})-({x2:.0f},{y2:.0f})) # 保存带标注的结果图 annotated r.plot() cv2.imwrite(result.jpg, annotated)conf0.25是置信度阈值低于这个值的检测框会被过滤。航拍场景下如果羊只密集可以适当降低到 0.15 提高召回但误检也会增加。iou0.45是 NMS 的 IoU 阈值控制重叠框的合并程度。imgsz640要和训练时保持一致否则精度会下降。批量处理视频或图片文件夹时把路径换成文件夹或视频文件即可YOLOv8 会自动逐帧处理# 处理整个文件夹 results model(path/to/images/, conf0.25, saveTrue) # 处理视频 results model(drone_video.mp4, conf0.25, saveTrue, streamTrue) for r in results: pass # 每帧结果自动保存4.3 模型导出与部署格式选择如果要把模型部署到边缘设备需要导出成对应格式。常见的有 ONNX、TensorRT、OpenVINO# 导出 ONNX通用性最好 yolo export modelbest.pt formatonnx opset12 simplifyTrue # 导出 TensorRTNVIDIA 设备上推理最快 yolo export modelbest.pt formatengine halfTrue device0 # 导出 OpenVINOIntel CPU 上加速 yolo export modelbest.pt formatopenvino halfTrueopset12是 ONNX 算子集版本太低会缺算子太高某些推理引擎不支持。halfTrue表示 FP16 半精度速度大概提升 30% 到 50%精度损失通常在 1 个点以内。导出后的模型文件在best.pt同目录下文件名后缀对应格式。5. 避坑与排查航拍牧羊检测的五个血泪教训5.1 现象训练 loss 正常下降但 mAP 始终为 0原因标注文件的坐标没有归一化或者类别编号从 1 开始而不是从 0 开始。YOLOv8 要求类别编号从 0 起坐标必须在 0 到 1 之间。解决用脚本检查所有 txt 文件确认每行第一个数字是 0后面四个数字都小于等于 1。如果坐标是像素值除以图片宽高重新生成。5.2 现象推理时检测框大量重叠同一只羊被框了三四次原因NMS 的 IoU 阈值设得太高或者模型训练时正样本分配过于宽松。解决推理时把iou从默认 0.7 降到 0.45 到 0.5 之间。如果仍然重叠严重检查训练时overlap_mask和mask_ratio参数分割任务才需要调这两个检测任务保持默认即可。5.3 现象模型在验证集上表现很好但换一片草场就大量漏检原因数据集多样性不足训练集的草场纹理、光照条件和实际部署场景差异太大。航拍数据尤其容易过拟合到某一种背景。解决补充不同草场、不同季节、不同飞行高度的数据。如果没法重新采集用更强的数据增强把hsv_h提到 0.03hsv_v提到 0.6degrees提到 15模拟更极端的光照和角度变化。5.4 现象训练到一半突然报 CUDA out of memory原因batch size 太大或者输入尺寸从 640 提到 1280 后显存翻倍。GTX 1660 Ti 只有 6GB 显存跑 YOLOv8s 加 1280 输入很容易爆。解决把 batch 降到 8 或 4或者用梯度累积模拟大 batch。YOLOv8 支持batch-1自动选择但自动值往往偏大建议手动设。如果显存实在不够用imgsz640训练推理时再放大输入。5.5 现象导出的 ONNX 模型推理结果和 PyTorch 不一致原因导出时没有加simplifyTrue或者 opset 版本和推理引擎不匹配。另外YOLOv8 的输出格式在导出前后可能有维度顺序变化。解决导出时固定用opset12加simplifyTrue。导出后用 ONNX Runtime 跑一张测试图和 PyTorch 结果对比如果框的位置有偏移检查预处理是否一致——PyTorch 推理时 YOLOv8 内部做了 letterbox 缩放ONNX 推理需要手动实现同样的预处理。6. 进阶技巧用 TTA 和切片推理把航拍小目标召回拉满航拍牧羊检测最头疼的就是小目标漏检。一只 60 米高度拍摄的羊可能只有 50 像素宽YOLOv8n 在 640 输入下 P3 层感受野勉强覆盖再小就力不从心了。除了换更大的模型还有两个不增加训练成本但能显著提升召回的手段TTA测试时增强和切片推理SAHI。TTA 的思路是推理时对同一张图做多种变换——水平翻转、多尺度缩放——分别推理后再把结果融合。YOLOv8 内置了 TTA 支持from ultralytics import YOLO model YOLO(best.pt) # 开启 TTA 推理 results model(test_image.jpg, augmentTrue, conf0.2, iou0.5)augmentTrue就是开启 TTA它会对每张图做水平翻转和三个尺度的缩放推理时间大概变成原来的 3 到 4 倍但 mAP 通常能提升 1 到 2 个点。如果部署平台算力充裕这个开销值得。切片推理更适合超大分辨率航拍图。把 4K 图切成 640×640 的小块分别检测再把结果拼回去小目标在切片里就变成了「大目标」。SAHI 库封装了这个流程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( large_drone_image.jpg, detection_model, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2 ) result.export_visuals(export_dirsahi_output/)slice_height和slice_width是切片尺寸一般设成和训练输入一致。overlap_height_ratio0.2表示相邻切片有 20% 重叠防止目标被切在边界上漏检。这个比例不能太小否则边界目标会丢也不能太大否则重复检测增多、后处理变慢。我一般用 0.2 到 0.3 之间。这两个方法可以叠加先切片每个切片推理时开 TTA召回率能再上一个台阶但推理时间会到原来的 10 倍以上适合离线分析场景不适合机载实时。还有一个容易忽略的细节航拍图像的 EXIF 里带有 GPS 坐标和云台角度检测到羊只后可以把像素坐标反算成经纬度直接输出每只羊的地理位置。反算需要相机内参和无人机姿态数据常见做法是用pyproj做坐标转换再用pix4d或OpenDroneMap生成的正射影像做底图匹配。这一步做完检测结果就不只是屏幕上的框而是可以直接导入牧场管理系统的地理数据。从那以后我每次拿到新的航拍数据集都强制先跑一遍 50 张图的切片推理对比确认小目标召回没有明显下降再决定要不要上 TTA。这个习惯帮我省了好几次返工。希望帮到你。本文还有配套的精品资源点击获取