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

YOLO实战:排水管网缺陷与废弃物巡检从数据到部署的完整攻略

简介目标检测是计算机视觉领域的核心任务之一而YOLO系列模型凭借其出色的速度与精度平衡成为工业落地中最受欢迎的选择。在实际工程中智慧城市和市政巡检场景往往面临小目标、低光照、遮挡、样本不均衡等复杂挑战单纯调参无法解决根本问题。本文从数据工程出发围绕数据采集、标注规范、数据增强与难例挖掘系统讲解如何训练一个可靠的检测模型随后结合边缘端部署介绍TensorRT加速、视频流接入以及告警工单闭环的实现思路。无论你是刚接触YOLO的算法工程师还是负责城市基础设施运维的项目开发者都能从中找到可复用的经验避开设坑真正将模型从实验环境推向生产环境。 先别急着解压这份.zip我可以负责任地说这个项目名听起来像是“智慧城市招标书”里随便抽出来的一条但真正落地的时候你会发现它几乎把目标检测这个方向最难啃的骨头都碰了一遍小目标、低光照、遮挡、样本不均衡、边缘端部署、业务系统联动。我去年带团队做了一模一样的方向——排水管网缺陷识别和城市废弃物巡检所以看到这个标题特别有感触。这篇就把从数据到部署、从模型训练到工单闭环的完整经验摊开讲不管是刚入门YOLO的算法工程师还是被迫接智慧水务外包项目的开发都应该能从这里找到能直接抄作业的东西。这个项目要做的事简单说就是让摄像头和检测机器人学会“看”排水管道里哪里破了、哪里堵了学会“看”路面、河道、垃圾堆放点有没有违规废弃物然后自动生成告警和工单把一线巡检人员从海量视频录像里解放出来。YOLO在这里承担的是视觉感知中枢的角色而整个系统的复杂程度往往取决于你背后要接多少业务系统。1. 这包东西到底是干嘛的需求拆解与方案定位1.1 排水系统和废弃物管理现实中到底难在哪排水系统这个场景外行听起来就是“下水道”觉得无非是拿个内窥镜进去看一圈但真实情况要复杂得多。城市排水管网以万公里计大部分管段埋在地下超过十年甚至二十年混凝土管老化、变形、破裂树根从接口钻进去垃圾和泥沙沉积导致过水断面缩水这些隐患单靠人工看CCTV检测视频一条管段几十上百分钟的视频人盯屏幕看半小时眼睛就花了漏检率相当高。这是排水侧的核心痛点。废弃物管理听起来比管道检测简单其实是另一个量级的难题。路面垃圾、河道漂浮物、建筑垃圾偷倒点、大件垃圾乱堆放这些目标不是固定点位出现时间随机、外观千奇百怪而且往往分布在广阔的区域里。靠人工巡检要么覆盖率不够要么成本太高。再加上现在很多城市已经建了海量监控摄像头摄像头有了但后端靠人盯屏根本看不过来。所以这个项目本质上不是在做一个算法demo而是在做一个“视觉巡检替代人工巡检”的系统工程。算法只是眼睛真正解决问题的是“眼睛 大脑 手脚”的闭环眼睛是摄像头和管道机器人大脑是YOLO模型和告警规则手脚是工单系统和现场处置人员。想清楚这一点后面所有技术选型都不会跑偏。1.2 为什么是YOLO而不是别的检测方案目标检测领域能用的方案其实不少两阶段的Faster R-CNN、一阶段的SSD、Transformer系的DETR我早年都折腾过。但最后给排水和废弃物这个场景选型时综合对比下来YOLO系列几乎没有悬念。第一个理由是部署友好性。排水场景大量部署在边缘端——管道检测车上的工控机、河道边的智能球机、Jetson盒子这些设备算力有限两阶段检测器推理速度顶不住Transformer系模型对算力要求更高。YOLO从v5到v8再到YOLO11一直有一条完整的n/s/m/l/x轻量到重量级的模型谱系小模型可以在Jetson Nano这种级别的设备上跑到实时再配合TensorRT还能再快一截。第二个理由是工程生态成熟。YOLO社区是目标检测领域里文档最全、工具链最顺的没有之一。数据格式、预训练权重、部署转换工具链都是约定俗成的标准做法。这意味着你在数据准备和工程集成上省下的时间足够你把业务闭环做得更完善。尤其对一个几万张图的数据集来说Ultralytics的YOLO训练接口一行命令就能跑起来这种效率是其他框架很难比的。第三个理由是技术指标够用。排水管道缺陷和废弃物识别本质上对精度要求没有工业质检那么变态mAP能到百分之七八十就可以大幅降低人工负担了YOLO很容易到。而且现在YOLOv8/v11已经是anchor-free设计省掉了锚框调参的麻烦还有配套的YOLOv8-seg实例分割分支遇到需要精确分割裂缝区域或者漂浮物轮廓的需求不用换框架直接切一个任务头就行。选型时唯一要犹豫的是版本。如果项目追求稳定我建议用YOLOv8社区足够大、坑都被填得差不多了如果追求性能上限也可以直接上YOLO11精度和推理速度比v8有提升部署方式基本一样。我们项目用的是v8起步后期迁移到v11做对比整体迁移成本很低。2. 数据工程算法能不能跑起来全看这一步2.1 数据从哪来三类采集渠道的取舍很多团队拿到这个项目第一反应是上网找公开数据集。能找到的公共数据集包括管道缺陷类的Sewer-ML、污水管道CCTV数据集以及各类垃圾检测数据集但坦白说公开数据集只适合用来做预研和模型能力验证真正要落地还是要自采数据因为各地管网材质、垃圾类型、摄像头机位差异太大了直接用公开数据训练出来的模型现场泛化效果通常不太行。自采数据主要来自三个渠道。第一个是管道CCTV/QV检测机器人这是排水管道缺陷数据的主要来源检测机器人进管后录制视频回来按帧抽图一个项目下来攒几万帧很常见。要注意的是抽帧不要每秒全抽不然相邻帧高度相似会让训练集实际信息量下降一般按1-2帧/秒抽缺陷段还可以稍微加密。第二个渠道是路面、河道的固定监控摄像头和球机。这类数据是废弃物检测的主力视频分辨率通常在1080p到4K之间抽帧后筛选出有目标的帧。这里有个经验多机位、多角度、多时段地采集同一个垃圾堆放点拍晴天、阴天、清晨、傍晚不同光线下的样子模型才能在实战里扛得住。第三个渠道是无人机巡检和无预算限制的“随手拍”平台。无人机适合河道漂浮物、建筑垃圾偷倒点这种大面积目标随手拍数据画质参差但胜在真实场景复杂拿来当难例补充很有价值。数据量上我的经验是单类目标至少要有2000-5000个标注实例整个数据集建议从1.5万张图起步往下浮动太多就开始明显影响精度。我们最终凑了管道缺陷图2万多张、废弃物图1.5万张、井盖/雨水篦子图5千张左右效果算是比较稳。2.2 标注规范、类别体系与格式转换标注是整个项目里最枯燥但决定上限的环节。我见到太多项目死在标注不规范上框得松松垮垮、目标只框了半边、类别定义含糊最后模型训练出来定位飘忽不定找原因找半天。类别体系是第一步要定死的。排水管道缺陷我建议直接用行业内通用的编码规范来定比如参考CCTV检测报告里常见的几类crack破裂、deformation变形、blockage堵塞、root_intrusion树根侵入、sediment沉积、foreign_object异物侵入。废弃物类别按管理和处置方式分plastic_bottle塑料瓶、construction_waste建筑垃圾、floating_garbage河道漂浮物、domestic_garbage生活垃圾、bulky_trash大件垃圾等。类别别贪多控制在12-15类以内类别越多训练难度和标注成本都指数上升。标注格式上如果你用的是LabelImg、X-AnyLabeling这类工具默认输出是Pascal VOC的XML格式而YOLO训练需要的是txt格式一行一个目标类别id、归一化中心点坐标和宽高。这一步需要一个转换脚本我贴一个我常用的import xml.etree.ElementTree as ET import os def convert_voc_to_yolo(xml_path, output_path, class_map): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: continue cls_id class_map[name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) with open(output_path, w) as f: f.write(\n.join(lines))转换之后一定做一次数据校验写个脚本检查每张txt的类别id是否越界、坐标是否在0-1范围内、是否存在图片和标注文件对不上的情况。这个小检查能拦住大量后期诡异问题。2.3 一张被忽略的底牌数据增强与难例挖掘样本采集回来直接扔给模型训练是最浪费的做法。排水管道和废弃物这两类场景都有一个共同特点正样本缺陷/垃圾出现的频率低负样本正常管段、干净路面一大堆。如果不做处理模型会倾向于把所有东西都预测成背景指标看着还行实际召回率低得可怕。数据增强是缓解这个问题的第一道防线。YOLO自带的增强策略里Mosaic四图拼接对小目标特别友好它让模型能在小尺寸目标上见更多样例。HSV颜色抖动要拉开幅度因为管道内光线差异极大有的管段打光充足有的只有微弱环境光颜色扰动太弱模型学不到不变性。随机翻转、缩放、平移也都开着但要注意管道检测里“上下颠倒”这种增强不一定合理如果管道机器人拍摄时镜头方向固定上下翻转会引入伪样本建议只做左右翻转。难例挖掘是第二道防线也是最容易被忽略的。训练第一版模型后把误检和漏检的样本挑出来回填训练集迭代两三轮精度能肉眼可见地涨。废弃物识别里有个经典难例黑色的塑料袋在阴影里几乎和沥青路面融为一体这种样本第一版模型大概率漏检回填之后效果立竿见影。另一个经验是去“扒拉”一些和你不相干的公开检测数据集做预训练迁移比如BDD100K、VOC数据格式五花八门不要紧统一转成YOLO的txt格式就能用这招能显著提升小样本类别的表现。3. 模型训练与性能调优实操3.1 训练环境与首次训练训练环境我直接说结论有NVIDIA显卡的Linux机器最省心Windows也能跑但坑更多。我个人推荐用Windows主力机装WSL2或者直接在VS Code里连远程Linux服务器来训练这样文件路径、CUDA环境都和线上跑批一致减少“本地好了服务器跑不起来”的尴尬。内存16G以上显卡显存最好8G起步8G可以跑yolov8n/s的batch 16要跑m/l系列就需要更大显存或者降低输入分辨率。首次训练不要贪心先把流程跑通我会建议直接用Ultralytics的YOLOv8模型和它的COCO预训练权重起步。数据集描述文件按YOLO的格式组织好path: /data/drainage train: images/train val: images/val names: 0: crack 1: deformation 2: blockage 3: root_intrusion 4: sediment 5: foreign_object 6: manhole_damage 7: manhole_missing 8: gully_blocked 9: plastic_bottle 10: construction_waste 11: floating_garbage 12: domestic_garbage 13: bulky_trash然后一行命令开训yolo detect train datadrainage.yaml modelyolov8n.pt epochs200 imgsz640 batch16 patience30 device0 workers8 cacheTrue这里有几个参数是后面反复要调的。imgsz默认640但排水场景小目标多后期我通常提到960甚至1280来涨点。patience是早停耐心值我习惯设30左右给模型足够时间去跳出局部最优又不至于浪费算力。cache设为True可以把图片预加载到内存训练速度快非常明显但内存不够大的机器会爆注意取舍。首次训练的观察重点不是mAP多高而是loss曲线有没有正常下降、验证集有没有一上来就震荡爆炸、有没有class id不匹配的报错。这些跑顺了再开始调参。3.2 关键超参数和训练策略训练策略上我强烈建议不要一上来就用完整训练集和200个epoch硬怼。我的标准流程是先用预训练模型、小学习率、少量epoch跑一个baseline看看各类别的基线和困难样本长什么样然后再加数据增强、调学习率、拉长训练周期。这样能帮你快速定位是数据问题还是模型问题。学习率的设置Ultralytics默认lr00.01配合它的自动调度其实已经不错但如果你用预训练权重做迁移学习我建议把lr0降到0.005左右因为主干网络已经学到通用特征了步子迈太大会破坏原有特征。batch size如果是单卡能大则大但别为了凑batch把imgsz降太低图像分辨率对检测小目标的影响往往比batch size更大。我用过的组合是yolov8s imgsz960 batch16在RTX 3080 10G上训练一个2万图的数据集大约需要6-8小时一轮属于可接受的节奏。训练中期要盯几个经常被忽略的指标。Precision查准率和Recall查全率要分开看废弃物检测场景误检多会给处置中心添乱Precision更重要而管道缺陷检测漏检一个破裂点可能导致后续爆管Recall权重更高。所以训练目标不是一个统一的mAP而是按业务侧重点去调置信度阈值和类别损失权重。Ultralytics里可以给个别类别设权重比如把focal loss的gamma调大来逼模型更关注困难样本。类别不均衡在排水场景特别突出crack和sediment多到几千个实例manhole_missing可能只有几十个。对几十个样本的类别再牛的增强也难救建议要么合并成大类别比如“井盖异常”涵盖破损和缺失要么专门去补采数据。靠模型调参拯救不均衡样本基本是徒劳。3.3 小目标、遮挡、低光照的三座大山排水管道和废弃物这两个场景几乎把这个领域最头疼的三个问题全占了。小目标是第一座山。管道里一块拇指大的石子、远距离摄像头下的一只塑料瓶在640分辨率下可能只有十几个像素。处理手段我亲测有效的是第一训练和推理时提高输入分辨率从640提到1280通常能给小目标检测带来三五个点的提升代价是推理时间增加但边缘端只要算力允许就划算第二用SAHI这类切片推理工具把大图切成多块小图分别推理再合并结果对4K监控画面里的废弃物检测效果显著第三收集小目标难例回填训练集时有意保留各种尺寸的小目标别只挑大的标否则模型对小目标的泛化能力会越来越差。遮挡是第二座山。河道漂浮物被水草挡住一半、大件垃圾堆中只露出一个角这种目标人工看都费劲。我的应对思路是标注时坚持“能看到一部分就算正样本”哪怕只有20%的可见面积也要标注逼模型学习部分特征另外用实例分割模型YOLOv8-seg做遮挡场景的备选方案分割掩模对边缘遮挡更鲁棒缺点是标注成本更高适合重点点位小范围使用。低光照和光照不均是第三座山。管道里灯光直射产生强烈反光夜间道路监控靠路灯补光都会让模型失效。我在项目里做了两件事一是训练时把HSV增强里的亮度变化范围调大让模型适应更宽的亮度分布二是对夜间样本超过一定比例的点位额外做一次针对性的亮度归一化和图像增强预处理比如直方图均衡再喂给模型。有一个坑要提醒如果只在白天数据上训练直接拿到夜间效果就拉胯这个没有捷径必须凑夜间数据。4. 部署落地从Jetson盒子到业务闭环4.1 模型导出与边缘端部署模型训练完拿到best.pt这只是开始。真正落地部署时PyTorch模型很少直接上生产因为推理速度慢、依赖重、不好和现有C/Java系统集成。我的标准流程是PyTorch模型先导出成ONNX再转成TensorRT引擎在NVIDIA边缘设备上跑FP16量化。YOLO的官方工具链让导出非常简单yolo export modelbest.pt formatonnx imgsz1280 dynamicFalse导出后在本地或直接把onnx文件拷到目标设备用TensorRT的trtexec转换trtexec --onnxbest.onnx --saveEnginebest.engine --fp16转换完成后在边缘设备上跑推理时直接加载engine文件速度和GPU利用率都远好于原始PyTorch。我们项目部署在Jetson Orin NX上yolov8s imgsz960 TensorRT FP16单帧推理能压到30-50ms应对视频流实时检测没有压力。考虑轻量化的话直接上yolov8n能再快一倍代价是精度掉一截建议用验证集实测后再决定。如果你要集成到C环境就用TensorRT C API加载engine或者用OpenCV DNN模块加载onnx后者部署简单但对优化后的引擎支持有限。如果后端是Java系常见做法是单独起一个Python推理服务通过gRPC/HTTP和Spring Boot通信把模型细节隔离在推理服务里开发和更新都方便。4.2 视频流接入与多路并发处理边缘设备部署完成后项目立刻会撞上另一个现实问题现场不是让你拿一张图跑一次推理而是好几个摄像头实时拉流每路都是7x24小时画面。视频流接入最常用的是RTSP协议海康、大华这些厂商的IPC基本都支持。Ultralytics的YOLO推理接口可以直接吃视频流地址但生产环境我会自己写一个推理服务用多线程或进程池管理多路拉流。一个经验采集线程和推理线程分开采集线程只做拉流和取帧把帧放到队列里推理线程从队列取帧处理避免某个摄像头网络卡顿拖垮整体。队列长度要限流积压太多就直接丢旧帧因为检测实时性比完整性重要丢了当前帧下一帧还能补上但积压导致延迟飙升告警就失去了意义。多路并发的另一个坑是GPU显存管理。每路推理线程都会占用一块显存如果你用batch1做视频流推理一个模型实例占用的显存不高但多个实例叠加很可观。更优的做法是用batch推理把多路取到的帧拼成一个batch一次推理吞吐量明显提升不过这需要轮询策略和复杂一点的代码适合路数多、资源紧的场景如果路数少于10路多线程单帧推理其实就够了。4.3 告警、工单、GIS检测结果怎么变成管理动作检测到缺陷和垃圾不是终点部署系统里的钱都是花在“检测结果怎么变成管理动作”上的。我见过太多项目算法精度很高但告警只能往一个QQ群里推几张截图现场人员根本不看最后沦为摆设。一个稍微像样的闭环要包含这几层检测结果结构化、告警规则、工单系统、空间定位。结构化输出就是每一帧检测完把类别、置信度、坐标、时间戳、摄像头ID写到消息里告警规则负责做抑制和聚合比如同一摄像头连续50帧都检测到同一个漂浮物只发一次告警就行避免刷屏工单系统接到告警后自动生成待处理任务派人去现场核实处置空间定位则是把摄像头/检测机器人对应的地理位置和管网GIS数据关联起来告警里带上经纬度。经纬度这个事多说一句如果是固定点位摄像头直接配置摄像头坐标就行如果是无人机或移动检测车就要结合设备GPS/IMU数据和画面里目标的像素偏移去估算目标真实位置这也是“基于YOLO的经纬度定位”这类需求的来源。我们做无人机河道巡检时用目标在画面中的位置结合无人机POS数据反算经纬度误差十几米内可以接受定位精度要求高还是得靠激光测距那些设备。后端技术栈上我们用了PostgreSQL存告警和工单记录加上PostGIS做空间查询前端用地图把检测结果叠加在管网GIS图层上处置人员在手机端就能看到红点位置和现场照片。整体并不复杂但每层都要有人愿意做脏活这才是项目真正落地和demo拉开差距的地方。5. 常见问题与排查实录5.1 训练指标全为0先别急着骂数据集YOLO训练时遇到“指标全为0”是高频问题尤其数据集来源复杂、从VOC转YOLO格式、或者用了多台标注软件合数据的时候。我的排查顺序是这样的先看数据集配置文件里的类别顺序和标注文件里的类别id是否一致VOC的类名转成数字id时如果name顺序和YAML里names对不上训练出来必然一脸懵再看有没有标注文件内容为空或坐标越界的样本YOLO遇到非法标注通常会跳过但跳多了模型学不到东西三看图片本身和标注文件是否对齐多任务标注时经常出现标了一张图但txt名字写错的情况。最直接的办法是训练前写个可视化脚本随机抽一些图片把标注框画出来看一眼。如果画出来的框位置明显不对说明标注转换有bug如果框都正常但训练还是全0再去查配置和路径问题。这类问题八成是数据集侧而不是模型侧。5.2 “supported values”报错无显示器环境下的环境坑这个词条在YOLO相关搜索里很常见YOLO supported values are [gtk3agg, gtk3cairo, gtk4agg, gtk4cairo, ...]看着像YOLO本身报错实际上这是matplotlib在无显示器的Linux服务器上试图选择GUI后端时的报错模型训练过程中需要画loss曲线和预测图但机器没有图形界面matplotlib就抱怨当前shell不具备显示条件。解法非常简单三种任选在代码开头加import matplotlib; matplotlib.use(Agg)或者环境变量export MPLBACKENDAgg或者升级matplotlib到新版新版对无后端环境会有更友好的自动降级。加完之后训练过程中那个“画图”环节就不会再卡了但要注意加了Agg之后你在本地跑训练脚本时如果还想着弹窗显示matplotlib图那是看不到了图像只会保存成文件正好适合远程SSH训练场景。5.3 漏检、误报、卡顿的现场排障上线之后的问题大多是三类漏检、误报、卡顿。漏检先看是不是图像分辨率不足或目标太小我习惯在漏检样本上叠加画一下真值框对比模型输出如果框都在但就是没识别出来基本是小目标问题按3.3节的方法处理如果连真值框都很难辨认说明数据采集本身质量不够需要调整摄像头机位或补光这事改算法不如改硬件来得快。误报则要看模型把什么误判成了目标。管道场景常见的是把管壁接缝或水痕误检成crack废弃物场景是把路面裂缝、光影边界误检成垃圾。这种问题优先用数据手段解决把误报样本回填训练集作为负样本或者调高置信度阈值。如果特定类别的误报还压不下去可以在后处理里加逻辑比如同一位置偶尔出现一次就忽略连续多帧都出现才告警这样能过滤大量随机误检。卡顿问题主线是算力瓶颈。先看是拉流卡还是推理卡拉流卡就调低帧率或换码流推理卡就用TensorRT FP16、换小模型、降输入分辨率三者按影响程度依次尝试。如果只部署一路还卡基本是模型硬件组合没选好换yolov8n是性价比最高的折中。多路的卡顿优先查显存占用和CPU占用很多时候是内存交换导致整体性能雪崩。我在实际操盘这个方向的时候最大的体会是YOLO把算法的门槛拉得很低任何一个小团队都能够在几周内跑通一个像模像样的检测系统但真正拉开差距的从来不是模型本身的精度而是数据工程和业务闭环的复杂度。排水管网和废弃物管理这类市政场景脏活累活非常多——数据要下井、要跟养护单位打交道、要理解工单流程——这些比调一个超参数重要得多。如果你的团队正好在做类似的事先把数据采集和标注质量稳住再考虑网络结构、换主干之类的高级玩法。最后再分享一个小技巧把训练好的模型导出ONNX前一定在验证集上对比一下导出前后精度和速度float32转float16虽然快偶尔会出现个别类别精度明显下降的情况逐类别对比后再决定是否上FP16这个细节能帮你省掉部署后很多麻烦。本文还有配套的精品资源点击获取
分享:

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

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