
写这个模块的时候我本来以为“目标检测”只是给无人机加一双眼睛做完才发现它是整个视觉感知、飞控决策、甚至任务规划的交汇点。Module 16 这一节内容实际上是把你前面学过的图像处理、神经网络部署、串级 PID 控制全部串起来让无人机真正从“能飞”变成“会看”。下面我按自己的实操顺序把这套从环境配置、模型选型到机载部署的完整链路拆开讲踩过的坑和不便明说的细节都会一起放进来。1. 整体思路拆解先搞清楚目标检测在无人机上到底承担什么角色1.1 从“遥控飞行”到“自主感知”差的就是这一步目标检测很多人一开始会把目标检测理解成一个单纯的视觉问题觉得跑通一个 YOLO 模型就能交差。但放到无人机这个场景里目标检测实际上是一个包含感知、决策、执行的闭环里的第一环。无人机要自动找到目标首先得有传感器数据往上是目标检测算法从图像或点云里框出目标位置再往上是坐标转换把像素坐标变成机体坐标系或世界坐标系下的偏移量最后才是飞控根据这个偏移量去调整姿态和位置。如果只停留在“模型能出框”的阶段那跟本地跑个 demo 没有区别。我在给学生讲这个模块时一直强调一个观点目标检测在无人机上不是一个独立功能它是“视觉伺服”和“自主避障”的输入源。比如追踪任务检测框的中心跟图像中心的像素偏差经过比例控制或串级 PID就能生成期望的偏航角速度。再比如避障检测到的障碍物类别和距离决定了路径规划算法是绕行还是悬停等待。所以 Module 16 的真正核心不是某一个模型而是把检测结果转化为飞控能够理解的指令。这就是为什么在动手训练模型之前最好先明确任务类型是静态目标搜索、动态目标跟踪还是广域巡检中的异常检测不同任务对检测算法的要求差异巨大。1.2 为什么选视觉方案而不是激光雷达或毫米波方案无人机目标检测的数据源主要分三类可见光相机、红外热成像、激光雷达点云。入门阶段绝大多数人都会选可见光相机原因很实际传感器便宜、图像直观、算法生态成熟。一个普通的 USB 摄像头或者树莓派 Camera Module 就能干活配合开源的 COCO 预训练权重很快就能出一个效果可接受的原型。而毫米波雷达虽然不受光照影响但点云稀疏、缺乏语义信息想分辨“前面那棵树是棵树还是个人”很困难。激光雷达精度高但价格劝退一套入门级固态雷达的价格就够买好几台飞控开发板了。但这不意味着视觉方案没有短板。无人机视角下的目标尺寸通常很小一个 640x480 分辨率下的行人可能只有十几个像素宽再加上运动模糊、光照变化、视角俯冲检测难度比行车记录仪视角高不少。所以实际项目中我一般建议“主视觉 辅助高度/距离传感”的组合视觉负责语义识别和类别判断超声波或单点 ToF 负责短距离测距GPS 和 IMU 负责全局定位。目标检测的系统设计本质上是在算力、精度、实时性、成本之间做权衡理解这一点比换更强的模型更重要。2. 环境准备与依赖安装几个会让新手当场崩溃的坑2.1 开发环境与机载计算平台的选型清单目标检测的完整流程涉及训练端和推理端。训练端一般用 PC 或服务器装深度学习框架和 GPU 驱动推理端才是真正放到无人机上的东西。Module 16 的教学项目里机载计算平台我建议三个层级选一个最省事的树莓派 4B/5适合跑轻量模型中间档的 Jetson Nano / Jetson Orin Nano能流畅跑 YOLOv5s 或 YOLOv8s预算充足的直接上 Intel NUC 配外置 GPU但考虑续航和载重这种方案实际飞起来很少见。软件的版本配套是一个大坑这里整理一份我验证过可以稳定配套的环境组合组件推荐版本备注操作系统Ubuntu 20.04 / 22.04Jetson 自带 JetPack 对应 Ubuntu 版本Python3.8~3.103.11 某些包还没有预编译 wheelPyTorch1.13~2.1Jetson 上装 JetPack 自带版本OpenCV4.6~4.9源码编译注意开启 CUDA 加速CUDA11.7 / 11.8必须跟 PyTorch 编译版本匹配YOLO 系列YOLOv5 / YOLOv8Ultralytics 库装最新即可2.2 module not found 类报错的快速修复方法热词列表里好几个都是关于modulenotfounderror的比如no module named opencv、no module named pkg_resources还有module pkgutil has no attribute impimporter。这几个问题我在环境配置课上反复遇到总结下来就是大多数模块找不到的问题根源不是没装而是装了多个 Python 环境pip 装到了一个环境解释器却跑在另一个环境。拿no module named opencv举例如果你用的是 Anaconda正确的安装方式是先激活对应的虚拟环境再用 pip 或 conda 安装conda activate drone_vision pip install opencv-python opencv-contrib-python装完后别急着跑代码先检查装到了哪个环境python -c import cv2; print(cv2.__version__)这条命令输出的版本号如果跟你 pip 安装的版本对不上说明解释器路径有问题。no module named pkg_resources则通常是因为 setuptools 版本过老或损坏更新一下就行pip install --upgrade setuptools wheel至于pkgutil has no attribute impimporter这是 Python 3.12 之后移除imp模块引起的兼容性问题最快的解决方式是降级到 Python 3.10或者把相关依赖包升级到支持新版本的版本。经验法则项目里遇到奇怪的 module 加载问题先看 Python 版本再看依赖包版本最后看是否多个环境混用。九成的问题都在这个三角关系里。3. 目标检测模型选型与关键参数YOLO 之外还有哪些选择3.1 为什么 YOLO 系是无人机目标检测的事实标准YOLO 系列能成为无人机目标检测的主流核心原因是它在实时性和精度之间找到了平衡。基于 Region Proposal 的两阶段检测器如 Faster R-CNN精度虽高但一张图跑一次前向要几百毫秒无人机飞控响应周期通常是 50~200Hz一次视觉推理占掉几十个控制周期根本没法用。YOLO 把目标检测重新定义成单次回归问题输入端直接预测边界框坐标和类别概率在嵌入式平台上能跑到 20~60 FPS这才是它能上机的原因。以 YOLOv8s 为例输入尺寸选 640x640 时在 Jetson Orin Nano 上开启 TensorRT 加速后实测推理延迟大约 15~25ms这个量级对飞控来说是可以接受的。但要注意640 输入对无人机小目标检测并不友好。如果任务目标在画面中占比很小有两个调整方向一是把输入分辨率提到 1280精度会涨但延迟可能翻倍二是保持 640 输入改用更深的检测头或增加小目标检测层。3.2 小目标检测和 transformer 检测器的取舍热词里反复出现“小目标检测”和“transformer 目标检测”。无人机视野高、目标远小目标检测确实是绕不开的话题。传统 YOLO 系列在 80x80 特征图上负责小目标如果目标在原图中只有 8x8 像素下采样 8 倍后只剩 1 个像素点特征几乎消失了。解决办法常见的有几种切图把大图切成多个 640 区块分别检测、多尺度训练Mosaic 增强里混合不同缩放比例、添加 P2 检测层。我在实际项目里用过简单有效的方案飞行高度控制在目标物高度的 5~8 倍之内尽量让目标在画面中占 30 像素以上比任何算法的收益都明显。Transfomer 检测器如 DETR、Deformable DETR 虽然解决了 NMS 后处理的问题、全局建模能力强但收敛慢、训练资源要求高在算力受限的机载设备上并不划算。如果追求极致的小目标精度可以尝试 DINO 这类模型但综合工程成本入门到中期项目我还是推荐 YOLO 系。等以后机载算力普遍到 200 TOPS 以上transformer 检测器才有机会在无人机上普及。3.3 模型导出与量化的实操设置模型训练完之后从 PyTorch 权重到机载可用的推理引擎中间还有一段路要走。YOLOv8 直接用model.export()可以导出多种格式关键参数是model.export(formatengine, imgsz640, halfTrue, dynamicFalse)formatengine导出的是 TensorRT 专用的 engine 文件halfTrue开启 FP16 推理精度损失很小速度提升明显。注意导出 TensorRT engine 时目标平台的 GPU 架构必须跟实际部署设备一致在 PC 上导出的 engine 无法直接在 Jetson 上跑需要在 Jetson 上重新导出一次这个坑几乎每个新手都会踩。4. 无人机视角的数据准备与标注策略4.1 公开无人机数据集与自采数据的配合训练目标检测模型数据是第一生产力。热词里提到“无人机数据集”、“鸟类目标检测数据集”等说明很多人已经意识到垂直场景数据的重要性。公开数据集方面VisDrone 是无人机视角目标检测最常用的基准数据集包含行人、车辆、自行车等类别拍摄视角和高度接近实际飞行场景。其他还有 UAVDT侧重车辆检测和跟踪以及大规模遥感数据集 DOTA适合高空大范围目标检测。但公开数据集的问题是跟你的实际任务场景总有偏差。我的一般做法是先用公开数据集预训练再用自采数据微调。自采数据不需要一上来就标几千张100~200 张覆盖不同光照、不同高度、不同背景的图片配合数据增强已经能显著提升实际场景的效果。具体步骤用无人机飞几个架次从 10~60 米高度拍摄目标物体抽帧并剔除模糊重复帧用 LabelImg 或 X-AnyLabeling 标注为 YOLO 格式然后按 8:1:1 划分训练、验证、测试集。4.2 贴地飞行与俯视视角无法避免的标注细节问题俯视视角带来的标注问题很多人要等模型训练完才发现。俯拍时目标不是标准的长方形框物体的朝向、遮挡、投影变形都跟水平视角不一样。标注的时候有一种很常见的错误一群人很密集时用一个大框把一群人框起来当一个人这会让模型学习到错误的类别特征。正确的做法是宁可漏标也不要错标漏标只会影响召回率错标会污染特征。另外一个细节是边界框边距。YOLO 格式标注的 cx、cy、w、h 都是相对于图片宽高的归一化值有些标注工具导出时保留小数位数太少会导致框偏移几个像素。小目标本身只有十几个像素几个像素的偏移就足够让 IoU 掉到 0.5 以下了。我建议标注完统一检查标签文件坐标值保留 5 位以上小数训练时开启cacheTrue把数据加载到内存能显著缩短训练循环的 IO 时间。5. 从检测框到飞控指令视觉与控制的联动实现5.1 串级 PID 在目标跟踪中的角色目标检测输出的边界框最终要通过飞控去执行这里就不可避免地接触到无人机串级 PID。热词里把“内外环的作用及时间间隔”都翻出来了说明这是个公认的难点。串级 PID 的内环是角速度环也叫姿态内环外环是角度环或者位置环。用目标检测做追踪时视觉外环负责“目标在画面中往右偏了多少”输出期望角速度给内环内环再控制电机转速实现转动。举个例子目标中心在图像 x720 处图像中心在 x640横向偏差 80 像素乘以一个比例系数 0.5得到期望偏航角速度 40°/s这个指令传给姿态控制器无人机就会平滑地转向目标。内外环的时间间隔在工程上通常相差一个数量级内环运行频率 200~500Hz外环 50~100Hz。如果视觉检测只有 20FPS直接作为外环输入会显得非常卡顿。我的习惯是在视觉检测和控制器之间加一个低通滤波或卡尔曼滤波对目标中心坐标做平滑预测这样即使检测帧率只有 15FPS控制量也不会突变。最简单的做法是smoothed_x alpha * raw_x (1 - alpha) * smoothed_xalpha 取 0.3~0.5 时跟踪效果会平顺很多。5.2 避障、路径规划与目标检测的数据流设计目标检测在避障和路径规划中扮演的是“感知层”角色。飞行过程中检测模型输出障碍物的类别和边界框结合单目测距或者先验尺寸估算距离生成一个障碍物列表路径规划模块在此基础上调整全局路径或局部避障轨迹。这块的工程重点在异步处理检测算法不能阻塞控制循环。我在 Module 16 里推荐的架构是三个独立线程相机采集线程、检测推理线程、飞控控制线程。相机采集线程以 30FPS 持续抓帧放入队列检测线程从队列取帧、推理、把结果写入共享内存控制线程以固定频率读取最新检测结果并结合 PID 输出控制指令。用 Python 的话multiprocessing或threading都能实现但要注意 GIL 限制深度学习推理最好放在子进程中跑避免主线程卡顿。6. 常见问题与调优实录我在这套流程里踩过的坑6.1 依赖、推理与标定问题速查表把我在 Module 16 教学中遇到的高频问题整理成一张表并附上排查思路现象可能原因排查方法与解决import cv2 报 ModuleNotFoundErrorPython 环境不对OpenCV 装到了别的环境检查which python重新激活虚拟环境后安装导入 pkg_resources 报错setuptools 版本损坏pip install --upgrade setuptoolsTensorRT engine 在 Jetson 上无法加载engine 在 PC 上导出架构不匹配在 Jetson 上重新执行导出脚本目标检测框抖动厉害检测帧率低控制量突变加入低通滤波或卡尔曼平滑Alpha 从 0.4 起步小目标完全检测不到输入分辨率太低或目标像素过小提高输入尺寸、添加 P2 层、降低飞行高度无人机转向时画面模糊曝光时间过长运动模糊调低曝光时间或开卷帘快门校正模型训练 loss 不降数据集标注错误太多或学习率过高随机抽 50 张图人工检查标签降低 lr 至 1e-4 重新训练6.2 几个提升精度和稳定性的调参技巧除了一步步排错再分享几个我实测下来有效的调参技巧。第一训练时开启自动混合精度AMP能省大概 40% 显存训练速度也更快且对最终精度几乎没有影响。第二YOLOv8 的patience参数默认 100如果数据集小建议改成 30~50否则早停机制几乎不会触发白白浪费算力。第三数据增强不是越强越好无人机俯视场景下色彩抖动和水平翻转是安全的但垂直翻转会让模型学到错误的地面关系建议关闭。部署到机载设备之前还有一个容易被忽略的环节——相机标定。很多无人机吊舱的广角镜头畸变很大如果直接把畸变图像送入检测模型目标位置在画面边缘时会偏移十几个像素。用 OpenCV 的棋盘格标定法跑一遍拿到内参和畸变系数在图像输入模型前做 undistort可以获得更稳定的检测框输出。配合飞控的云台姿态数据还能把检测结果从像素坐标转到地理坐标为后续更复杂的自主降落、投掷、巡检等任务打好基础。这个模块做完之后我最大的体会是目标检测本身可以很“无脑”地跑通但真正难的永远是把检测结果变成飞行行为的那一段。如果你打算接着往下做可以试试把检测框的类别信息和尺寸信息结合加入简单的单目深度估计从“找到目标”升级到“定位目标”。再往后接一个基于地理坐标的航点规划算法无人机就能自主完成一个完整的搜索—识别—逼近任务链了。项目源码和配置我放在文末的代码仓库里欢迎拿去改改完记得告诉我你的飞行效果。