
去年夏天我跟着巡河员走了一段将近三公里的河道。太阳晒得水泥堤坝发烫人还没走完一半衣服已经湿透了。回来之后还要把手机里拍的几十张照片导进电脑一张一张放大去看哪里有矿泉水瓶、哪里有泡沫板、哪一堆要分清楚是生活垃圾还是水草。当时我脑子里反复冒出一个念头无人机河道垃圾图像识别这件事必须从想法做成一套真正能跑起来的系统。这篇文章就把我整个项目从技术架构设计、硬件选型、算法调优到真机实测的全过程摊开来讲。不聊PPT里的概念只讲实际做了什么、遇到了什么坑、哪些参数是可以直接抄作业的。如果你在做水利信息化、环保监测、智慧城市巡检或者正准备用无人机和图像识别解决水质、岸线、漂浮物这类问题这篇文章里的数据和踩坑记录应该能帮你省下不少时间。1. 为什么河道垃圾识别绕不开无人机1.1 人工巡河的效率瓶颈先说人工巡河的真实状态。河道巡查不是每天都能做的很多地方一个月才完整巡一次汛期前后才加密。一个人沿河走三公里正常要一两个小时到了草高的季节岸边根本下不去脚只能走一段看一段。桥洞、涵洞、滩涂、茂密芦苇荡这些位置人站在岸上基本就是盲区垃圾藏在那里可能几个月都没人发现。坐船巡河倒是能覆盖水面但成本高、速度慢一条船至少配两个人还有安全风险。汛期水流急的时候小船根本不敢往桥墩附近靠。即便人到了现场记录形式也很原始——大部分是手机拍几张照片回到办公室再手动整理成表格。照片没有地理坐标等清理人员拿着表格去找垃圾可能已经漂走了。整个链条里最大的问题不是人懒而是效率天花板太低。1.2 水面场景的反直觉难点很多人觉得无人机飞得高、看得全拍下来再做图像识别不就是换个视角做目标检测吗真做起来才发现水面场景和常规的马路、工地完全不是一回事。第一个难点是反光。太阳光打在水面上形成的耀斑和白色垃圾在图像上高度相似尤其顺光角度下一大片亮白色的水波纹很容易被模型看成泡沫板。第二个难点是波纹扰动水面的纹理时时刻刻在变同一个目标在不同帧里形态差异很大。第三个难点是水质背景差异清澈的山区河道、浑浊的城市内河、长满绿藻的富营养化水面背景特征完全不同模型在一个水面上效果好换条河可能直接崩掉。还有一点容易被忽略无人机飞行高度不固定。同一个矿泉水瓶10米高度俯拍是一个小点子20米高度俯拍变成半个像素大的目标到30米高度可能就和噪声分不开了。这意味着算法不能只在一个固定的目标尺度下工作。1.3 项目目标与技术指标定义项目启动之前我跟业务方反复确认了需求最后把目标定得很具体识别对象水面常见漂浮垃圾——塑料瓶、泡沫块、编织袋、塑料袋、包装纸等飞行高度10到50米以俯拍视角为主巡航速度8到12米/秒核心指标检测召回率不低于80%误报率控制在15%以内从发现目标到生成带GPS坐标的预警记录端到端时延不超过3秒覆盖能力单次飞行能自动巡查3公里以上的河道这个指标不是拍脑袋定的。业务方真正关心的是能不能减少人工跑腿、能不能精准派单。只要系统能在一次飞行里把八成以上的垃圾找出来并告诉清理人员哪个位置有什么类型的垃圾就已经比纯人工巡河高出一个量级。先做到可用再追求完美这是我做这类项目一贯的原则。2. 整体技术架构与硬件选型2.1 分层的系统架构设计整个系统我拆成了四层层与层之间数据流向非常清晰层级核心组件职责采集层无人机平台、云台相机、RTK模块获取高质量俯拍图像和精确地理坐标感知层机载AI计算单元、推理引擎运行图像识别模型输出目标框和类别决策层路径规划模块、飞行控制逻辑规划巡航路线根据识别结果触发悬停、绕飞、补拍应用层地面站软件、后台管理系统展示实时画面、生成工单、数据归档这个结构的好处是每一层都可以独立替换。感知层模型更新不影响采集层硬件决策层路径规则调整也不需要动推理代码。后期想把固定摄像头监测点位接进来也只需要在应用层加数据源。2.2 无人机平台电机选型与飞控思路平台选择上我坚定不移地选了四轴多旋翼而不是固定翼或者倾转旋翼。原因很简单河道巡检的场景是沿着狭长河道慢速飞行经常需要悬停、绕飞、小半径转弯四轴的垂直起降和悬停能力是最契合的。倾转旋翼虽然巡航效率高、速度快但结构复杂、成本高、维护难度大在河道这种环境里完全发挥不出优势。电机选型是这里容易被忽略的环节。河道巡检相机加云台的载荷通常在0.5到1.5公斤为了留出足够的动力冗余我们按起飞重量5公斤来设计。电机选型的经验值是单电机最大拉力最好达到起飞重量的二分之一以上四个电机的总拉力冗余控制在1.5到2倍。也就是说5公斤的机子每个电机至少能提供2.5公斤以上的最大拉力。这样飞控在做姿态修正、对抗侧风的时候电机不会进入拉力饱和状态。我们用的是3510电机配1555桨叶6S电池实测有效巡航时间在25分钟左右能够支撑一次完整的三公里河道巡查。飞控我们走的是开源路线PX4和ArduPilot都试过最终选了PX4原因是ROS生态和仿真支持更完善。如果团队想快速验证算法像Spacedrone这类开源整机平台也可以作为研究起点省去自己折腾飞控集成的时间。2.3 机载计算单元与相机选型机载端是整套系统算力的核心我对比过三条路线NVIDIA Jetson Orin NX 16GB算力强TensorRT支持好功耗在25W左右适合跑YOLOv8这类模型是我们最终选择的方案RK3588性价比高配合RKNN可以跑轻量模型功耗低但生态和文档相对差一些踩坑成本高ESP32-S3-CAM这是很多人问的低成本方案我专门拿它做过前期验证——它可以跑非常小的分类模型或者只做拍照图传但要跑实时目标检测基本不现实算力差了两个数量级建议不要在上面浪费时间相机选择上我们用了一台4K广角云台相机重点考虑三个参数视角范围要够大至少70度以上才能在巡航时覆盖整个河道截面、支持偏振镜安装、支持RTK时间同步标签。偏振镜这个细节后面会讲可以说是治水面反光最便宜有效的手段。2.4 起降平台与地面站真机实飞之后才发现河道现场很多时候根本没有平整的起飞场地。河堤杂草丛生台阶又窄四轴无人机从地面起飞容易被打到草。后来我们配了一个便携式起降平台就是一个铝合金折叠的平板展开后给无人机足够的离地空间方便视觉定位系统在无特征水面附近锁定地面参考。这个配件不贵但实际用处比想象中大。地面站方面我们没有用太复杂的方案一套自研的Web地面站就够用。飞行过程中通过4G/5G链路把实时画面和检测结果推到后台管理员能在网页上看到带有坐标的垃圾标记。真正的检测计算都在机载端完成链路断了也不影响飞机自己飞完航线这是架构上必须保证的。3. 识别算法的选型路线与水面场景适配3.1 目标检测与语义分割怎么选做水面垃圾识别首先要想清楚用目标检测还是语义分割。目标检测输出的是矩形框和类别优点是速度快、部署成熟、和业务系统的坐标上报天然匹配。语义分割能精细到像素级对泡沫块、塑料袋这种形状不规则的物体会更精准但机载算力开销大、标注成本高实时性很难保证。我的选择是第一阶段用目标检测跑通业务闭环第二阶段再把分割加进来做精细化。理由很务实——业务方需要的是哪里有垃圾、什么垃圾、坐标多少矩形框完全够用等到系统稳定运行、数据积累够了再用分割模型做二次确认也不迟。3.2 主流模型的实测对比我们在Jetson Orin NX上实测对比了三类模型输入分辨率统一用1280推理引擎都是TensorRT FP16模型mAP0.5推理耗时模型大小备注YOLOv8s0.8622ms22MB轻量机载端实时性最好YOLOv8m0.8938ms49MB精度略高耗时可接受RT-DETR-Base0.8841ms58MB精度不错但依赖库较重最终选了YOLOv8s。原因不只是速度而是工程生态YOLO系列的导出、量化、TensorRT部署资料太全了社区踩坑的人多遇到问题很容易搜到解决方案。RT-DETR精度没有显著优势部署却复杂不少在机载内存受限的场景下没必要冒险。做项目不是发论文选型要选最稳的那条路。3.3 针对水面环境的数据增强策略水面场景不能只靠通用增强必须针对反光、波纹、视角变化做专门的模拟。推荐配合Albumentations库实现自定义增强管道。我们的增强序列主要包括随机亮度对比度扰动、HSV色相偏移、水平翻转、随机尺度缩放模拟不同飞行高度以及两个自研增强——一个是水面耀斑模拟在图上随机生成高亮的斜向光带另一个是轻微水波纹扭曲用正弦波网格对图像做局部形变。实测下来加入这两个针对水面的增强后模型在晴天正午时段的误报率下降了大概5个点效果非常明显。但要注意不能增强过度否则模型会对反光过拟合反而忽略真实垃圾——增强的本质是增加多样性不是把样本变成另一个东西。4. 数据集构建与模型训练一场持久战4.1 数据从哪来数据是这套系统真正的护城河。我们用的数据集由三部分组成自采航拍数据80%在不同河道、不同天气、不同时段用无人机实拍这是最贴近真实部署场景的数据专项开源数据集15%比如网上可以找到的编织袋图像识别数据集里面各种编织袋、蛇皮袋的样本非常全和河道垃圾场景高度相关近似场景公开数据5%工地航拍公开数据集里的塑料膜、防尘网、围挡样本虽然场景是工地但视觉特征和河道漂浮物有共性可以帮助模型学到更多材质纹理有人可能会问直接用公开数据集做迁移学习不就行了我的回答是自采数据不可替代。模型最终要在你负责的河道上跑别人数据集里的水面背景、光照条件、垃圾形态都和你不一样哪怕只有几百张自采图也远比几万张无关图片有价值。4.2 类别体系与标注规范类别定义直接影响模型的可用性。我们最终确定了六个目标类别加一个背景概念类别说明塑料瓶矿泉水瓶、饮料瓶等泡沫泡沫板、泡沫箱碎片编织袋蛇皮袋、水泥袋等塑料袋各种软质塑料包装袋包装纸纸盒、纸箱、食品包装自然漂浮物枯枝、树叶、水草单列便于后续过滤背景水面、河岸、反光区等标注规范里最容易扯皮的是聚团垃圾的处理。一堆垃圾漂在一起有瓶子有袋子还有泡沫是标一个框还是标多个框我们的约定是当一个目标群体内部无法清晰区分边界时按一个主目标标注类别选面积占比最大的那个。这样既保证了标注一致性也符合清理工人的实际作业习惯。标注工具用的开源CVAT支持多人协同、交叉审核。每批标注完成后抽5%到10%做质检质检不过的打回重标。这块不能省模型精度上限就取决于标注质量。4.3 样本不均衡与难例挖掘水面数据天然存在严重的样本不均衡。树叶、枯枝这些自然漂浮物到处都是塑料瓶、泡沫块则相对少。如果直接训练模型会学到看到东西就报自然物的偷懒策略这对业务一点用没有。我们做了两件事。第一件是难例挖掘用当前模型去跑大量未标注的原始航拍视频把漏检样本模型没识别出的真实垃圾和误检样本模型误报成垃圾的反光、水草挑出来分批补充进训练集。第二件是复制粘贴增强把塑料瓶、泡沫块的像素从标注图片里裁剪出来贴到各种水面背景上同步生成新标注。这个操作能把稀有类别的样本量提升2到3倍但注意不要贴得太假否则模型学到的全是悬浮感过强的合成物体。4.4 训练实战细节与评估方法训练我们直接用YOLOv8在COCO预训练权重上做迁移学习。关键参数供参考输入分辨率1280batch size 16初始学习率0.01warmup 3个epoch后切换余弦退火总共训练100个epoch。预训练权重非常重要从零初始化的话同样数据量下mAP大概要低10个点以上纯属浪费算力。评估时我建议别看单张mAP业务场景里漏检的代价比误报高得多。我的习惯是看召回率0.5阈值下的PR曲线如果某个类别的召回率明显低于其他类别就针对这个类别补充难例和做增强而不是一味调全局超参数。5. 机载部署与推理优化让模型在飞机上跑得动5.1 部署硬件路线怎么选模型训练好只是开始真正难的是把它塞进机载设备里稳定跑。前面提过我们选了Jetson Orin NX 16GB。选它不是因为算力最高而是因为TensorRT对YOLO系列的优化非常成熟FP16和INT8量化都有现成工具链。如果预算更紧张RK3588也是个备选但你需要额外承受RKNN工具链的bug和时间成本。5.2 从PyTorch到TensorRT的完整链路部署流程我整理成了一套固定命令团队里任何人照着跑都能复现# 第一步PyTorch模型导出为ONNX yolo export modelbest.pt formatonnx imgsz1280 opset17 simplifyTrue # 第二步ONNX转TensorRT FP16引擎 trtexec --onnxbest.onnx --saveEnginebest_fp16.engine --fp16 # 第三步如果做INT8量化需要额外指定校准集 trtexec --onnxbest.onnx --saveEnginebest_int8.engine --int8 --calibcustom_calib.txt这里有几个特别容易踩的坑。第一ONNX导出的opset版本不要太新Jetson上的TensorRT版本对opset有上限要求我们因为版本不匹配吃过一次亏。第二预处理必须和训练时完全一致包括RGB还是BGR的顺序、letterbox的填充值、归一化系数。推理端做一次letterbox后处理就要把坐标精确映射回原图。第三TensorRT引擎和CUDA版本是绑定的刷了Jetson系统镜像后一定要确认CUDA、cuDNN、TensorRT三个版本匹配我们team里不止一个人在这上面浪费了一整天。5.3 SN8精度收益与实测数据量化这块我们做了充分的对比实验引擎mAP0.5推理耗时显存占用备注FP160.8622ms约2.1GB首选方案精度和速度平衡INT80.8514ms约1.3GB精度掉点约1%速度提升明显FP320.8745ms约4.2GB不作为部署选项最终我们线上用的FP16。INT8只掉了1个点的精度14毫秒的推理速度也很诱人但在水面场景下召回率任何一点下降都会转化为实际漏检这个代价不值得。如果你的算力特别紧张可以考虑INT8但一定要用覆盖反光、水草、多时段样本的校准集做量化校准集质量直接影响量化后精度。5.4 长时间稳定运行的几个关键细节机载设备在高空狭小空间里散热差长时间满负荷运行容易触发降频推理帧率会突然掉一半。我们做了两件事一是在飞控安装时给Jetson加了一个主动散热风扇起飞前通过脚本开启二是在软件里用jetson_clocks锁定最高性能模式同时每30秒读取一次芯片温度和帧时间温度超过85度时自动降低输入分辨率到960保证系统不崩溃。端到端时延方面单模型推理只要22毫秒但加上相机取流、预处理、后处理、坐标解算、链路传输整条链路稳定在80到100毫秒。这个速度完全够用因为飞行决策本来就是秒级的。6. 路径规划与整机联调从仿真到实飞的跨越6.1 河道自适应巡航路径规划河道不是直线路径规划模块需要根据河道的中心线坐标自动生成航点序列。我们的做法是先从离线地图里提取河道中心线每隔50米插值一个航点在弯道处加密到20米间隔然后通过平滑算法生成一条无人机可飞行的轨迹。路径规划算法层面可以用经典的A*或RRT做全局避障也可以直接在MATLAB里先建三维路径规划的数学模型做仿真验证。河道场景的有趣之处在于大部分路线都在水面上方真正要避的是桥、高压线、岸边树木这些高空障碍所以路径规划的重点是垂直方向的安全高度设定——根据跨越障碍物的高度动态调整飞行高度而不只是水平绕行。这里必须提醒一句无论算法仿真多漂亮我们在真机执行时依然遵守当地空域管理规定并且只在获得许可的区域开展飞行任务。6.2 硬件在环仿真先行再上真机首次实飞之前强烈建议做硬件在环仿真HITL。HITL就是把真实飞控硬件连到仿真环境里无人机在虚拟场景中飞行飞控跑的是真实的固件和参数。我们拿着这个配置把航线逻辑、失效保护、链路断连这些场景全部跑了一遍然后才挪到真机上首飞。这一步看起来多花了时间实际上省了大钱。我们有个同事直接上真机测试路径规划逻辑结果参数没调好飞机一头扎进河边的芦苇丛桨叶全废。仿真环境里这种问题最多花几秒钟重启真机上就是一次维修成本加至少一周的项目延期。6.3 识别结果反哺飞行策略的疑似—确认机制机载端识别结果不能只做记录还要影响飞行动作。我们设计了一套疑似—确认两阶段机制第一阶段模型在巡航过程中以较低置信度阈值扫描画面任何潜在目标都会标记为疑似第二步一旦出现疑似目标飞控切换为悬停或小半径绕飞模式从不同角度连续抓取2到3帧第三步连续帧中有两帧以上同时确认该目标系统才把这条记录标记为确认垃圾并记录GPS坐标和截图证据这个机制把最终误报率压到了一个非常可用的水平。单帧误报可能很高但连续多帧都误报的概率会呈指数下降。系统确认目标后会自动计算当前航线的断点位置做完补拍后回到断点继续巡查不会因为一个疑似垃圾就中断整个航次。7. 真机实测复盘水域垃圾识别的坑与解法7.1 反光最大的误报来源没有之一上真机跑的第一个星期我们的系统在晴天中午的误报率一度超过25%其中80%都是反光误报。太阳低角度照射时水面大片亮斑和白色泡沫、白色塑料在外观上几乎无差别模型根本分不清。针对性解决做了三件事。第一云台相机前端加偏振镜这是物理层面最有效的方案能把大部分镜面反射滤掉。第二把训练数据里特意加入了大量顺光和顶光时段的画面让模型见过更多反光形态。第三在后处理里加了一个HSV空间的过滤逻辑对高亮度、低饱和、面积巨大的连通区域做降权处理因为真实垃圾很少占据画面那么大比例。这几项叠加后误报率降到了10%以内。7.2 自然漂浮物与垃圾的分类边界另一个高频混淆是水草、浮萍、枯枝被识别成垃圾。业务方其实对这类自然物有明确态度枯枝落叶不需要清理但大面积水草浮萍可能是水体富营养化的信号需要单独上报。这个业务语义如果模型区分不了系统就是废的。我们把自然漂浮物作为独立类别加进训练集而不是让它混在背景里。加了这个类别之后模型在垃圾和自然物之间的判断有了一个中间选项塑料瓶和枯枝的混淆率明显下降。在业务审核界面里自然物也单独用一种颜色标记方便环保人员区分处理。7.3 天气、时段对模型稳定性的考验水面这种反射性极强的场景受光照影响比陆地场景大得多。实测数据很直观阴天和多云天气模型全天表现都稳定晴天上午9点到11点、下午3点到5点识别效果最好正午顶光反光最强傍晚低角度阳光会在水面拉出长条光带误报率重新抬头。应对策略是双管齐下。训练层面在数据采集时就有意识地按不同时段分配任务保证训练集覆盖各个光照条件。执行层面把自动巡检任务尽量安排在上午和下午的黄金窗口正午和傍晚留给人工确认和数据补采。这套策略听上去很简单但对系统在真实业务中的可用性提升非常明显。7.4 连续帧确认、GPS去重与人工复核交互最后要说的是算法输出只是半成品业务闭环需要一套交互逻辑配合。飞控系统每天跑一次飞行同一段河道里同一个垃圾很可能被多帧拍到。我们做了GPS聚类去重半径5米内只保留置信度最高的那条记录。单个目标在整个航次中被误报多次、但每次位置都不同会被当作多个目标吗不会多帧空间聚类直接解决了这个问题。地面站里给管理员保留了人工复核入口——每条自动上报的记录都附带三张不同角度的截图和GPS坐标审核人员只需要看图确认是/否一键生成清理工单。这个设计很朴素但让模型的误报由人来最终把关整个系统才真正具备可用性。8. 项目成本账与可复制经验8.1 预算构成参考很多团队关心这类项目到底要花多少钱我列一张我们项目的实际预算分配表项目预算占比说明无人机平台含载荷30%机架、飞控、电机、电池、云台相机机载AI计算单元15%Jetson Orin NX及散热附件数据采集人力15%多河道、多时段飞行拍摄数据标注与质检15%标注人力是持续性投入算法开发与部署15%模型训练、TensorRT部署、调优地面站与后台系统10%Web平台、数据库、工单系统整体加起来一套可投入使用的原型系统大约在十五万到二十万这个区间如果已有无人机硬件成本会大幅下降。相比每年的人力巡河开销和漏检带来的治理成本这个投入的回报周期很短。8.2 项目中最容易延期的环节做完整套项目我的经验是最容易延期的不是算法而是数据标注和现场协调。算法调优是一个可控的过程但数据标注的进度往往被质量参差拖累而且很难通过加班解决。现场协调更头疼你要去某条河段飞得先和相关管理方沟通台风、暴雨、禁飞管制都会让计划泡汤。给后来者的建议是项目启动的第一周就去跑数据采集流程请巡河员参与第一批数据标注。他们最清楚哪些东西是垃圾、哪些是自然物他们的参与从源头上决定了类别定义和标注规范是否正确。这项工作越早后面的算法和部署就越顺利。8.3 后续演进方向这套系统的识别框架已经跑通后续我计划在两个方向上扩展。一是把检测升级为轻量级语义分割对泡沫散碎、塑料袋撕裂这类不规则目标做精细轮廓提取同时保持实时性。二是把单目可见光延伸到多光谱甚至热红外热红外对水面油污、高温排放物有明显优势可以和可见光数据做多模态融合。路径规划层面引入动态热点分析——根据一段时间的垃圾分布密度自动调整巡检航点密度把高频出现垃圾的区域列为重点巡查区段进一步提升单次飞行的有效产出。最后再分享一个实际体会这类项目真正的难点往往不在模型结构多新颖而在于数据、部署和业务流程三者之间的缝合。如果你正准备启动类似的项目我的建议很简单——前两周别急着调模型先把数据采集和标注流程跑顺再把最小闭环打通。哪怕模型只有80%的召回率对比人工巡河的效率已经是质变。精度优化的事数据积累够了自然水到渠成。