news 2026/9/19 7:56:24

基于Jetson Nano与YOLOv5s的无人机道路抛洒物实时检测系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Jetson Nano与YOLOv5s的无人机道路抛洒物实时检测系统

最近我把一套基于Jetson Nano和YOLOv5s的无人机道路抛洒物实时检测系统完整地跑通了,从数据集整理、模型训练到机载部署,整个链路踩了不少坑,也沉淀了不少经验。这套系统解决的实际问题是:无人机在空中巡查时,能够实时发现路面上的轮胎皮、纸箱、木板、散落砂石等障碍物,并能把告警信息和位置回传到地面站。它适合做毕业设计、边缘计算项目、无人机视觉方向研究的同学参考,也适合已经在做道路巡检工程应用的朋友拿来借鉴方案。这篇博文我不打算只贴代码,而是把为什么选这套方案、数据集怎么搞、模型怎么调、部署怎么加速、实测会遇到什么问题,一条线讲清楚。

1. 整体方案设计与技术选型思路

1.1 为什么是 Jetson Nano + YOLOv5s 这个组合

先说结论:这个组合是“低成本边缘实时检测”里性价比最稳的一套。Jetson Nano在二手市场几百块就能拿下,算力虽然只有472 GFLOPS,但配合TensorRT加速后,跑YOLOv5s这种轻量级模型,FP16精度下能做到20到30 FPS,完全够无人机巡查这种场景使用。YOLOv5s属于YOLOv5系列里最小的一版,参数量只有7.2M左右,模型文件大概14MB,部署到嵌入式设备上非常友好。

很多人会问,既然Jetson Orin Nano性能更强,为什么还要选Jetson Nano?我的观点是:先看需求再选硬件。道路抛洒物检测对帧率的要求并没有高速场景那么苛刻,10到15 FPS其实就能覆盖绝大多数巡检需求,而且Jetson Nano功耗只有5W到10W,对无人机续航的影响相对可控。Orin Nano固然性能翻倍,但价格也翻了几倍,飞丢或者炸机的损失成本完全不同。等模型验证成熟、确需更高分辨率输入时再升级硬件,整个代码框架可以无缝迁移。

另外一个关键点是生态。YOLOv5的官方仓库对Jetson系列支持非常完善,导出ONNX、转换为TensorRT引擎的社区资料一抓一大把,踩坑成本低。相比之下,如果用YOLOv7、YOLOv8,虽然精度更高,但在老旧的JetPack 4.6环境里,某些算子和自定义模块的兼容性反而需要额外处理,对新手不太友好。

1.2 系统整体架构与数据流

整套系统的数据流可以用三条链路概括:图像采集链路、检测推理链路、告警回传链路。

图像采集链路:无人机挂载的摄像头(可以是CSI接口摄像头,也可以是USB摄像头或图传摄像头)输出视频流,通过GStreamer或OpenCV接入Jetson Nano。实际项目中我推荐使用RTSP流方式,把摄像头画面通过图传模块发送到机载接收端,再由Jetson Nano解码,这样摄像头和计算板可以分离安装,方便减震布局。

检测推理链路:Jetson Nano上运行TensorRT加速后的YOLOv5s引擎,对每一帧图像做目标检测。检测结果包括目标类别、置信度、边界框坐标。这里要注意,不要直接拿原始视频流一帧一帧跑,最好做一个抽帧策略,比如每2帧推理一次,或者按时间间隔0.1秒推理一次,既能降低功耗,也能减少误报。

告警回传链路:检测到抛洒物后,系统会做“多帧确认”,只有连续若干帧都检测到同一区域的同一类别目标,才触发告警。告警信息通过串口或WiFi回传到地面站,同时在本地保存截图和GPS坐标。GPS坐标的获取可以接一个串口GPS模块,或者通过无人机飞控的MAVLink协议读取。

整体来看,Jetson Nano承担的职责就是“边缘计算节点”,所有推理都在本地完成,不需要把视频流大量回传地面站,这对图传带宽有限的实际场景来说非常重要。

1.3 不同方案的取舍对比

我身边有人用纯云端方案,也有人用大模型方案,还有用传统图像处理的,我都简单对比过:

方案优势劣势是否适合本场景
云端AI检测(视频传回服务器)可用大模型、精度高依赖网络、延迟高(500ms以上)、流量费贵不适合
大模型目标检测(如YOLOv8x、RT-DETR)精度高嵌入式设备跑不动或帧率极低不适合
传统视觉(边缘检测、阈值分割)零成本、延迟低泛化能力差、光照一变就废仅适合特定辅助
Jetson Nano + YOLOv5s平衡精度、速度、成本需要一定的部署经验适合

尤其要说明的是,道路抛洒物检测最怕的就是“漏报”。传统视觉方案在固定角度、固定光照的监控摄像头下还能用,但无人机视角变化快、光照条件复杂,一个阴影或者路面标线就会让阈值分割失效。深度学习模型虽然需要准备数据,但泛化能力远好于传统方法,这也是我坚持用YOLOv5s而不是OpenCV轮廓检测的原因。

2. 数据集构建:从零搞定道路抛洒物标注

2.1 数据来源怎么找

做检测项目,数据集永远是第一道坎。道路抛洒物这个方向比较垂直,网上没有现成的完整公开数据集直接下载,需要自己收集和整理。我整理过的数据来源主要有三类:

第一,自采数据。用无人机在真实道路上空拍摄视频,高度控制在30到80米,视角尽量模拟实际巡查场景。拍摄时间覆盖白天不同时段,包含晴天、阴天、逆光等光照条件。采集到的视频用OpenCV按每5秒抽一帧的方式切成图片,筛选出含抛洒物的帧。这个过程比较耗时间,但数据质量最高。

第二,公开数据集的二次标注。BDD100K、Cityscapes这类自动驾驶数据集里包含大量路面目标,可以把其中属于“抛洒物”类别的目标(比如纸箱、轮胎、锥桶)抽取出来,重新整理标注格式。虽然它们的视角大多是车载平视,和无人机俯拍有些差距,但可以作为预训练辅助数据。

第三,合成数据。用3D建模或者图像合成的方式,把抛洒物贴到路面上,再通过背景融合生成训练样本。这种方法适合补充稀有类别,但做出来的图片和真实感有差距,需要控制比例,我只用来补“轮胎皮”这种难以采集的类别。

需要强调的是,数据集的版权和隐私问题一定要重视。自采数据避免拍到清晰人脸和车牌,公开数据集要注意授权协议,商用之前要逐条核对。

2.2 类别定义与标注规范

道路抛洒物种类繁多,一开始不要太贪心,建议先定义6到8个高频类别就够用了。我项目中用的是这8类:轮胎皮、纸箱、木板、锥桶、散落砂石堆、塑料布、铁质障碍物、其他抛洒物。“其他”这个类别很重要,它能兜住那些标注时说不清、但确实是异物的目标,避免模型在推理时把未知物体硬分到某个已知类里。

标注工具我用的是LabelImg,虽然界面老一点,但胜在轻量和稳定。标注格式有两种主流选择:PASCAL VOC格式(XML文件)和YOLO格式(txt文件)。LabelImg默认导出VOC格式,YOLOv5训练需要YOLO格式,转换用脚本统一处理。

标注规范上有几条实操经验:

  • 边界框不宜过大,尽量贴合目标轮廓,但也不能切到目标内部,因为YOLO训练的损失函数对框的大小很敏感。
  • 被遮挡的目标如果可见面积超过20%,仍然标注;低于20%就跳过,避免引入大量模糊学习信号。
  • 夜间或反光严重的图片建议单独建文件夹,不要混在正常数据里,方便后面做针对性增强。
  • 一个小技巧:标注时统一使用“从左上角拖到右下角”的习惯,虽然LabelImg支持任意方向,但统一方向可以避免后期脚本处理坐标时出现负数。

2.3 数据增强与小目标处理策略

无人机俯拍视角下,抛洒物在整张图中的占比通常很小,很多目标可能只有三四十个像素宽。这种小目标检测是YOLO系列一直以来的弱项,必须从数据处理阶段就做准备。

我在离线增强阶段做了四类操作:水平翻转、随机旋转(±15度)、亮度对比度调整、高斯噪声。这部分我建议用脚本批量处理而不是在线增强,因为离线增强能看到实际效果,避免生成过于畸形的样本。在线增强用的是YOLOv5自带的Mosaic、MixUp、HSV扰动,训练时随机应用。

针对小目标,还有一个更关键的策略——切图。我实验过,把原始4096x2160的俯拍大图先切成四块1024x1080的子图,再分别送入模型训练,小目标的像素尺寸相当于放大了一倍,mAP能提高约8个百分点。虽然标注时要多花点时间,但效果立竿见影。

数据增强的过程中一定要检查增强后的图片是否合理。我出现过旋转90度后“纸箱”被旋转成了“竖条”,视觉上已经不像纸箱的情况,这种样本混进去只会增加学习难度,后来我在脚本里限制了最大旋转角度并在输出前人工抽样检查。

2.4 数据划分与YOLO格式转换

数据准备好之后,要按训练集、验证集、测试集7:2:1的比例划分。注意划分时要以“视频片段”为单位,而不是以“图片”为单位。如果同一个视频片段里的连续帧被同时分到训练集和验证集,会因为场景高度相似导致验证指标虚高,部署到新场景后掉点明显。

YOLO格式的txt文件内容很简单:每行代表一个目标,格式为“类别ID 中心点x 中心点y 宽度w 高度h”,所有坐标都归一化到0到1之间。转换时要注意类别ID和类别名称一一对应,别在脚本里写死。

我项目的完整数据目录结构是这样的:

dataset/ ├── images/ │ ├── train/ # 训练集图片 │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片 ├── labels/ │ ├── train/ # 对应的YOLO标注txt │ ├── val/ │ └── test/ ├── data.yaml # 数据集配置文件 └── classes.txt # 类别列表

写转换脚本的时候,有一个坑值得注意:读取XML坐标时,像素坐标要除以图片的原始宽高,而不是重新缩放后的宽高。我一度为了方便先把图片压缩到640x640再读取标注,导致框的位置全部偏移,训练出来的模型预测框基本都在图片左上角,排查了半天才发现是归一化基准错了。

3. YOLOv5s 模型训练关键细节

3.1 训练环境准备

训练阶段不一定要在Jetson Nano上跑,我是在一台有NVIDIA显卡的PC上训练的,模型训练完毕后再部署到Jetson上。PyTorch版本建议用1.10到2.0之间的稳定版本,CUDA版本对应显卡驱动选择,没有太苛刻的要求。

YOLOv5仓库的克隆和依赖安装按照官方README来就行。特别提醒一句:训练前要确认torch和torchvision版本是匹配的,很多人直接pip install torch就完事,结果导入torchvision的时候报错,来回折腾半天。

git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt

如果显卡显存不足,比如只有4GB显存,就把训练批次调小、输入分辨率调低,而不是直接换更大的batch。YOLOv5对batch size的敏感度没有想象中高,小batch配稍多的epoch也能收敛到不错的精度。

3.2 配置文件和训练命令

训练前需要改两个文件:数据集配置文件data.yaml和模型配置文件yolov5s.yaml。

data.yaml内容如下:

train: /path/to/dataset/images/train val: /path/to/dataset/images/val test: /path/to/dataset/images/test nc: 8 # 类别数量 names: ['tire', 'carton', 'wood', 'cone', 'gravel', 'plastic', 'metal', 'other']

yolov5s.yaml里主要改nc为8,其他参数保持默认。训练命令:

python train.py \ --data data.yaml \ --cfg models/yolov5s.yaml \ --weights yolov5s.pt \ --batch-size 16 \ --epochs 200 \ --img 640 \ --device 0

每条命令我都解释一下:weights指定预训练权重,YOLOv5s.pt是在COCO上预训练过的,迁移学习能让模型快速收敛;img 640是训练输入分辨率,我在实验中发现640比416在抛洒物检测上的mAP高约5个点,虽然显存占用增加,但值得;epochs 200是因为小数据集加迁移学习,150到200轮左右基本收敛,再多了容易过拟合。

3.3 关键训练参数与调优心得

训练参数里最值得花心思的是这三个:学习率、锚框、损失权重。

YOLOv5默认使用cosine学习率调度,初始学习率0.01。我之前贪快调成0.02,训练直接发散,loss曲线飞上天。后来实验下来,0.006到0.01是安全区间,新手不要轻易动。

锚框(anchor)是很多教程忽略的点。YOLOv5在训练时会自动调用k-means重新计算anchor,但如果你用的是预训练权重,它默认的anchor是基于COCO数据集的80类目标统计出来的。对于抛洒物这种细长、扁平的物体,建议在训练前手动跑一次anchor计算:

python train.py --data data.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --noautoanchor False

让YOLOv5在训练开始前先执行自适应anchor计算。我实测不调整anchor时,细长木板这类目标召回率只有50%左右,调整后提升到76%。

损失权重方面,YOLOv5的box_loss和cls_loss默认权重是0.05和0.5。如果项目更关注“别漏检”,可以把box_loss权重适当调低、cls_loss略微调高,让模型更积极地把目标分到正确类别;如果更关注“别误报”,则反过来。我用默认配置效果已经不错,建议默认跑通后再微调。

另外推荐开启--cache属性,把小图片缓存到内存中,训练速度能提升好几倍:

python train.py ... --cache

3.4 模型评估指标怎么看

训练结束后,看results.png和混淆矩阵。YOLOv5训练完成会自动生成results.png,里面有训练loss、验证loss、mAP等曲线。我判断过拟合的方法是:验证集mAP在某个epoch后开始下降或者波动增大,但训练集mAP还在涨,说明模型开始“背题”而不是“学规律”了,这时取下降前的权重即可。

混淆矩阵最重要。道路抛洒物场景里,我重点关注的是“轮胎皮”和“纸箱”这两个类之间是否互相误判。它们在外观上确实有点像,都是深色块状物,如果混淆矩阵显示两者互相误判比例超过15%,我就回过去检查数据标注,看是不是有些纸箱被打上了轮胎皮标签。

TensorBoard也可能用到,YOLOv5支持用--project和--name参数指定输出目录,训练结束后用tensorboard --logdir=目录即可可视化。不过对我来说results.png基本够用,TensorBoard更像锦上添花。

4. Jetson Nano 端侧部署与加速

4.1 部署环境与依赖安装

Jetson Nano的推荐系统是JetPack 4.6,它自带了CUDA 10.2、cuDNN 8.2、TensorRT 8.2,这些组件的版本匹配关系很重要。我见过有人直接刷最新JetPack 5.x,然后发现TensorRT版本和YOLOv5导出的ONNX算子不兼容,反而多花时间。

刷机步骤简单说三步:用SD卡烧录JetPack镜像、开机完成初始配置、开启MaxN性能模式。

# 开启MaxN模式 sudo nvpmodel -m 0 sudo jetson_clocks

Jetson Nano默认运行在5W低功耗模式,CPU主频被限制,实测跑YOLOv5s只有5到7 FPS。切换MaxN模式后功耗上限10W,性能直接翻倍,实测能到15到20 FPS。如果无人机供电充足,一定要开MaxN。

PyTorch安装是很多人的噩梦。Jetson Nano是aarch64架构,不能直接pip install torch,需要到NVIDIA官方论坛下载预编译的wheel包,或者用NVIDIA提供的PyTorch容器镜像。我建议直接在Jetson上创建Python 3.6的虚拟环境,然后安装对应用户版本的torch 1.11.0和torchvision 0.12.0。

pip3 install torch-1.11.0-cp36-cp36m-linux_aarch64.whl pip3 install torchvision-0.12.0-cp36-cp36m-linux_aarch64.whl

注意,Jetson上安装torch主要是为了导出ONNX和做精度对比,实际推理走TensorRT,不依赖PyTorch,所以版本选型以兼容性为先。

4.2 ONNX导出与TensorRT加速

YOLOv5自带的export.py可以直接导出ONNX:

python export.py --weights best.pt --include onnx --img 640 --opset 11 --simplify

导出后可以用Netron工具打开ONNX文件检查一下网络结构,确认输入输出的维度符合预期。这一步能提前发现很多问题,比如输入节点名不对、输出层被优化掉了,这些问题到TensorRT阶段再排查会非常痛苦。

转换成TensorRT引擎有两种方式:一种是直接使用trtexec工具命令行转换,另一种是写Python脚本用TensorRT API加载ONNX后构建engine。trtexec方式更简单,适合快速验证。

/usr/src/tensorrt/bin/trtexec \ --onnx=best.onnx \ --saveEngine=best_fp16.engine \ --fp16

FP16是Jetson Nano上的最佳平衡点,INT8虽然更快,但需要校准数据集,而且校准不好精度损失明显。我在项目里没有用INT8,因为FP16已经能跑满30 FPS了,且mAP掉了不到1个点,INT8虽然能到40 FPS,但部分小目标开始漏检,性价比不高。

TensorRT引擎构建时间在Jetson Nano上比较久,慢的话要等两分钟,这是正常的。建议在PC上构建好engine文件然后拷贝到Jetson上运行,但要注意构建机器的TensorRT版本必须和Jetson一致,否则序列化出来的engine无法加载。

4.3 视频流接入与实时推理流程

Jetson Nano上常见的视频接入方式有CSI摄像头、USB摄像头、RTSP网络流。无人机场景里,RTSP流更常见,通过图传接收模块把画面转发到本地端口,Jetson用OpenCV读取。

# 用OpenCV读取RTSP流 cap = cv2.VideoCapture("rtsp://192.168.1.100:8554/stream")

用GStreamer可以降低延迟,尤其是在USB摄像头上,直接cap.read()的CPU开销比较大。推荐在OpenCV后端设置GStreamer属性:

cap = cv2.VideoCapture("rtspsrc location=rtsp://192.168.1.100:8554/stream latency=0 ! decodebin ! videoconvert ! appsink", cv2.CAP_GSTREAMER)

latency=0是降低画面延迟的关键,不设置的话默认缓冲会让画面延迟几百毫秒,实飞时操作手感会很差。

推理主循环的核心代码结构:

import cv2 import numpy as np import tensorrt as trt import pycuda.autoinit # 加载TensorRT engine并分配缓冲区的代码省略... # 这里只展示推理和显示的骨架 while True: ret, frame = cap.read() if not ret: break # 抽帧策略:每2帧处理1次 frame_id += 1 if frame_id % 2 != 0: continue # 预处理:letterbox +归一化 input_blob, ratio, (dw, dh) = letterbox(frame, new_shape=(640, 640)) # 推理 outputs = engine(input_blob) # 后处理:坐标还原+NMS boxes, scores, class_ids = postprocess(outputs, frame.shape, ratio, (dw, dh)) # 绘制结果 draw_boxes(frame, boxes, scores, class_ids)

这里的letterbox和postprocess代码可以直接复用YOLOv5仓库utils里的函数,我建议单独写一个推理模块,把TensorRT引擎、预处理、后处理封装成类,方便在多个场景里调用。

4.4 性能实测数据与功耗控制

我实测的几种配置对比如下:

配置输入分辨率帧率FPS单帧耗时ms备注
PyTorch直接推理640x6401.8555不可用
TensorRT FP16640x6406.5154可用但偏低
TensorRT FP16416x4161283高抛洒物场景可用
TensorRT FP16 + 抽帧640x6402245实际体验流畅

Jetson Nano的显存是4GB,FP16推理时显存占用大约1.2GB,剩余显存足够跑多个应用。但要注意开启MaxN模式后核心温度上升很快,如果没有主动散热,几分钟就会触发降频,帧率从12掉到5。我的解决方案是给Jetson Nano加了个5V风扇,温度控制在60度以内,帧率稳定很多。

功耗方面,整个Jetson Nano加摄像头模组在MaxN模式下实测约8到12W。如果是大疆这类载重较大的无人机,挂载这个问题不大;如果是自制小四轴,就需要权衡电池容量和飞行时间。我在实验机上用的是5200mAh 3S电池单独给Jetson供电,能和飞控电源隔离,避免电机启动瞬间拉低电压导致系统重启。

5. 无人机集成与实时告警实现

5.1 机载设备安装与减震

Jetson Nano在无人机上的安装,核心问题不是固定,而是减震。无人机飞行时的高频震动会让Jetson的存储卡读写异常,严重点直接死机。我的做法是用减震球把Jetson Nano固定在一个碳纤维底板上,底板再通过四个减震柱连接到机架。摄像头单独用一个小支架固定,尽量让镜头朝下,同时避开螺旋桨视场。

很多教程会忽略电磁干扰的问题。Jetson Nano的WiFi模块、GPS模块、图传模块最好分开一定距离,避免相互干扰。我第一版把所有模块堆在一起,结果GPS搜星很慢,图传画面还经常花屏,拆开重排之后问题消失。

5.2 图传链路与检测结果回传

检测画面回传地面站有两种做法:一种是把OpenCV处理后的画面直接编码成H.264流推到地面站;另一种是只回传检测结果数据和截图。我推荐第二种,因为图传带宽有限,推视频流会占用大量带宽且影响控制信号。我实测用WiFi的UDP协议传JPEG压缩后的检测结果图,1080p的图片压缩到100KB左右,每秒传1张毫无压力。

检测结果如果要叠加显示在无人机遥控器的屏幕上,可以用MAVLink的自定义消息通道,不过这个接入比较麻烦。更简单的方式是地面站程序通过TCP接收JSON格式的检测结果,自己叠加到地图或画面上。

5.3 告警与防抖逻辑实现

实时检测系统最容易被忽视的问题是“抖动误报”。无人机在飞行时,画面不断变化,同一个抛洒物可能这一帧被检测到、下一帧又没了。如果每一帧都触发告警,地面站会收到几十条重复信息。

我的防抖方案是“连续多帧确认+空间去重”:

from collections import deque # 用一个队列记录最近N帧的检测结果 detection_history = deque(maxlen=10) def detect_filtered(new_detections, frame_id): detection_history.append(new_detections) stable_alerts = [] # 对当前帧每个候选框 for detect in new_detections: # 查找在最近N帧中是否有同一位置的检测 count = 0 for hist in detection_history: if any(similar_box(detect, h) for h in hist): count += 1 # 连续出现至少3次才触发告警 if count >= 3: stable_alerts.append(detect) return stable_alerts

坐标还原到GPS也比较关键,我采用的做法是:先获取无人机当前GPS坐标和相机正下方的中心点坐标,再根据目标在画面中相对中心点的像素偏移和当前飞行高度,用近似的比例关系估算目标GPS坐标。精度在没有云台姿态数据时大概在5到10米范围内,但作为道路抛洒物的位置提示已经够用,地面人员到场后可以沿路搜索。

5.4 实飞测试中的工程取舍

实飞和实验室差异最大的不是模型精度,而是现场环境的不可控性。我遇到过几次坑:一是飞行高度变化导致目标像素尺寸剧烈变化,在80米高度标注训练的数据,飞到120米时很多目标太小根本检不到。解决方法是训练时加入不同模拟高度的增强,或者干脆设定固定的巡查高度。二是在强光下,摄像头自动曝光导致路面过曝,抛洒物被亮光吞掉。解决方法是切换摄像头为手动曝光模式,并把曝光时间压低。

抽帧策略在实飞时也要动态调整。巡航速度快时,抽帧间隔要短;悬停检查时,可以降低采样频率来省电。这个逻辑也不复杂,读一下飞控的速度信息,设置几个档位即可。

6. 常见问题与排查经验速查

6.1 性能与稳定性问题

**检测帧率低怎么办?**先看是不是没有开MaxN模式和jetson_clocks,这一步能翻一倍性能。再看CPU占用,如果是OpenCV解码消耗过高,切换到GStreamer管线。最后再考虑降低输入分辨率或增大抽帧间隔。

**运行过程中突然卡死或自动重启,是什么原因?**大概率是供电不足或温度过高。用万用表测一下Jetson输入电压,电机的瞬时压降会导致电压跌到4.8V以下。解决办法是加入防反接二极管和足够容量的电容,或者采用独立供电。

**系统存储空间不足,怎么处理?**JetPack系统本身占空间比较大,训练过程中生成的日志和权重文件也会积累。建议把swap文件设大一点(4GB左右),同时定期清理未使用的容器和日志文件。

6.2 检测精度问题

**模型在自采视频上漏检小目标,但在测试集上表现不错,为什么?**这种情况通常是训练数据里小目标太少,测试集恰好避开了这些困难样本。解决办法是回到数据集,增加小目标样本数量,并使用切图策略让模型看到更多的“放大的小目标”。

**误报特别多,尤其是路边的树木护栏被识别成抛洒物,怎么处理?**我在项目里也遇到类似情况,原因是护栏在俯拍视角下和木板很像。一个有效的做法是增加负样本,把没有抛洒物但包含护栏、路标、树影的图片作为背景图片加入训练,并设置背景类。YOLOv5训练时可以用--train background图片路径来加入负样本。

**置信度阈值调多高合适?**这个需要根据告警系统的容忍度来定。我巡航模式下把置信度阈值设置为0.35,悬停复核时提升到0.6。追求低漏检率时阈值调低,追求低误报率时阈值调高,两者只能取一个平衡,没有一步到位的阈值。

6.3 部署环境问题速查表

现象可能原因解决方式
trtexec转换报“Network has dynamic or shape input”ONNX未固定输入尺寸导出时指定固定输入尺寸或设置--explicitBatch
TensorRT engine加载报错引擎在别的机器上构建在目标设备上重新构建engine
CV2无法打开RTSP流GStreamer插件缺失sudo apt install gstreamer1.0-plugins-good
内存不足导致进程被杀swap过小或显存溢出增加swap并关闭无关进程
letterbox后检测框错位后处理没有还原坐标检查坐标还原公式中的比例和填充值
图像颜色异常GStreamer的像素格式不匹配在appsink前加videoconvert,指定BGR输出

部署环境的坑往往是“环境匹配”问题,CPU架构、TensorRT版本、PyTorch版本、CUDA版本,任何一个不匹配都会出现奇奇怪怪的报错。我的经验是先跑通一个最简单的分类模型,比如torchvision里的resnet18,确认整条推理链路没有问题,再上YOLOv5的ONNX导入,这样能快速定位是哪一层的问题,而不是几件事混在一起排查。

写到最后,我想起一个实际测试里印象很深的细节:第一次带着整套系统去室外跑的时候,模型在电脑上测试精度很高,一到无人机上就频繁漏检。排查了很久,发现是无人机飞行时视角倾斜导致抛洒物形状变化剧烈,而我训练数据里绝大多数是近乎垂直的俯拍照。后来我在训练集里加入了倾斜拍摄角度(让模型看到更“躺”的抛洒物),问题才真正解决。这件事给我最大的教训是:流程跑通只是第一步,真正要花时间的是让数据和真实部署环境尽可能一致。数据质量上投入的功夫,会在最终效果中数倍地体现出来。这套思路也可以继续扩展,比如在无人机上同时跑车道线检测、裂缝检测等,只要遵循“数据贴近场景、模型轻量可靠、边缘端做好加速”这三条原则,很多巡检类问题都能用类似的方案落地。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 7:55:31

PiXYZ实战:工业CAD模型导入Unity的数字孪生数据治理指南

1. 工业模型进Unity,为什么PiXYZ是绕不开的一环做过数字孪生项目的朋友大概率都经历过这个场景:甲方甩过来一个几十兆甚至上百兆的STEP或IGES文件,说“把这个设备模型放进场景里,下周演示”。你兴冲冲地把文件拖进Unity&#xff0…

作者头像 李华
网站建设 2026/9/19 7:55:17

OpenHarmony中React Native数据持久化Hook设计与实现

1. 项目背景与核心价值在OpenHarmony生态中集成React Native开发能力,本质上是在探索如何将成熟的跨平台框架与新兴操作系统深度结合。这次我们要解决一个看似简单但实际影响开发效率的关键问题:如何在React Native组件中优雅地实现本地数据持久化。传统…

作者头像 李华
网站建设 2026/9/19 7:53:53

Flutter布局核心:Row、Column与Expanded详解

1. Flutter 布局基础与核心思想作为一名从2017年开始使用Flutter的开发者,我见证了Flutter布局系统的演进与成熟。Flutter的布局机制与传统的Web或原生开发有着本质区别,这也是很多初学者容易困惑的地方。理解Flutter布局的核心思想,是掌握UI…

作者头像 李华
网站建设 2026/9/19 7:53:25

北斗定位核心原理与工程实践:从伪距解算到误差消减

简介:这份PDF资料系统梳理了北斗卫星导航系统的定位原理与实际应用,内容涵盖系统组成、双星定位机制、工作流程,以及北斗一号与二代的演进对比,适合通信、测绘、交通等领域的技术人员和对卫星导航原理感兴趣的读者。压缩包内仅包含…

作者头像 李华
网站建设 2026/9/19 7:48:36

BI平台选型本质:企业数据能力与AI分析落地路径

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华