下水道缺陷检测实战:从CCTV图像预处理到YOLOv8部署

发布时间:2026/9/12 2:29:44
下水道缺陷检测实战:从CCTV图像预处理到YOLOv8部署 简介这是一份面向计算机视觉学习者和工业检测从业者的下水道管道缺陷检测项目包聚焦图像视觉在管道堵塞、裂缝、渗漏识别中的应用。项目以Python算法实现为核心涵盖normalizeRGB、circularMask、arcDetect、Main等模块涉及灰度转换、滤波去噪、边缘检测、特征提取等图像处理环节并针对管道圆形区域掩膜、时间转换、轮廓高亮等关键任务提供可直接运行的脚本。压缩包内附两张示例图片和README说明文档便于对照运行和理解流程。资源共9个文件类型以6个py脚本、2张jpg样例图、1个markdown文档为主总大小约910KB轻量便捷适合快速搭建检测流程或作为课程设计、算法练习的参考。已有107人学习浏览。项目价值在于提供一套从图像预处理到缺陷识别的完整代码骨架用户可基于现有脚本扩展3D视觉、无人机巡检等场景也可用于评估CNN等深度学习模型在管道缺陷分类中的基准效果对城市基础设施智能化维护方向的入门与进阶均有助益。1. 为什么下水道缺陷检测比想象中更吃技术下水道管道堵塞和缺陷检测听起来就是把摄像头探进管道拍一段视频然后让算法标出哪里破了、哪里堵了。真实情况是CCTV 巡检车扫完一条 2 公里的管线产出上万帧画面人工逐帧看既要盯结构缺陷裂缝、塌陷、变形又要盯功能性堵塞沉积、树根、异物疲劳造成的漏检率一直压不下来。基于图像视觉的缺陷检测模型被引入这条产线就是为了同时覆盖“管壁损伤”和“管腔堵塞”两类目标并且保证在高帧率视频流下也能实时反馈。我拿到这类需求时习惯把项目拆成三个环节缺陷标签体系 - 检测模型训练与调参 - 面向现场光照和帧率条件的推理优化。这个以项目分享包为名的 zip 文件价值往往不只在于权重文件更在于预处理脚本和阈值调节记录。适合往下读的是给排水信息化工程师、机器视觉工程岗以及想用一个可复现案例完成毕设或 demo 的研究生。下面按最小可运行链路展开。2. 下水道缺陷检测从哪开始缺陷类别、标注与图像预处理2.1 结构性缺陷与功能缺陷用一张标签表定清楚在下水道的工况里缺陷不是一个标签能包住的“二分类”。检测报告一般区分为结构性缺陷与功能性缺陷前者是管壁物理损伤后者直接影响过水能力。把标签表先固定下来后面标注、训练、验收才不会反复返工。常用标签体系如下表一级类别标签名视觉特征落地要点结构性crack裂缝管壁黑色细线常见分叉最难标容易与阴影混淆结构性deformation变形断面内凹或椭圆化需要参考管口正常形状结构性collapse塌陷大块破损管道阻断风险最高优先保证召回结构性corrosion腐蚀表面麻点、颜色剥落对比度低依赖细节增强功能性deposition沉积/堵塞管底泥砂堆积过水断面变小样本量最大常占一半以上功能性root树根侵入黑色丝状物伸入管道目标小建议切图训练功能性scale结垢灰白色覆盖物容易与腐蚀混淆标注时要避免只看单帧截图。我一般会把该帧前后各 3 帧一起发给标注员作为上下文否则管道内车灯移动造成的光影变化会被大量标成裂缝或腐蚀。标签文件统一导成 COCO json后续接 yolov8 还是转 halcon 缺陷检测流程都方便。标注工具优先用 CVAT它支持按帧插值跟踪而管道内缺陷在相邻帧之间位移很小插值能省掉将近一半的人工框选量。提示如果最终要出结构性和功能性缺陷的分开报告建议在标签名字上直接加前缀例如 structure_crack、functional_root不要在标注完成后靠后处理去猜类别归属。2.2 管壁反光与暗角CLAHE 与 gamma 预处理代码管道内光照条件极差摄像机自带光源造成画面中心过亮、边缘黑暗水面还会出现条状反光。这种分带亮度问题会让模型学到“亮部等于缺陷”的假相关性训练集来自不同井段时尤其明显。我在预处理阶段固定用下面这段代码而不是把原图直接丢给网络import cv2 import numpy as np def preprocess_pipe_frame(image: np.ndarray) - np.ndarray: # 1. 转 HSV只对 V 通道做 CLAHE避免颜色通道同步拉伸产生噪声 hsv cv2.cvtColor(image, cv2.COLOR_BGR2HSV) v hsv[:, :, 2] clahe cv2.createCLAHE(clipLimit3.0, tileGridSize(8, 8)) v_equ clahe.apply(v) hsv[:, :, 2] v_equ img cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) # 2. 暗部提升gamma 大于 1 时暗部细节被拉开 gamma 1.2 table ((np.arange(256) / 255.0) ** (1.0 / gamma) * 255).astype(np.uint8) img cv2.LUT(img, table) # 3. 裁掉画面上下 15% 和左右 10% 的无效黑色区域并缩放到统一尺寸 h, w img.shape[:2] roi img[int(h * 0.15):int(h * 0.85), int(w * 0.1):int(w * 0.9)] return cv2.resize(roi, (640, 640))这段代码做了三件事先分离亮度通道做 CLAHE直接原因是管道图像的问题集中在亮度分布而不在色相缺陷对 V 通道做自适应直方图均衡可以在不放大颜色噪声的前提下拉平明暗之后用 gamma 校正提升暗部纹理参数 clipLimit 决定局部对比度强度1080p 源图用 3.0 即可如果源图是 720ptileGridSize 要改成 (4,4)否则容易出现块状伪影最后裁剪掉画面边缘的黑色无效区并 resize 到 640这个尺寸与后续模型输入保持一致。水面反光区域在 CLAHE 下会被放大clipLimit 超过 3.5 时反光边缘会形成一条明显的假边界极其容易被识别成裂缝。预处理做完后最好抽 20 帧保存为 jpg 人工目检一遍确认每帧缺陷和背景的对比度都有提升。如果某些井段逆光严重gamma 可临时调到 1.4但同一项目里不要多套 gamma 混用否则模型会靠环境的亮度统计特征去分辨缺陷而不是靠缺陷自身的纹理。2.3 增强参数要按管网场景重新设yaml 配置与注意事项下水道视频缺陷检测的增强策略和通用目标检测不同。水平翻转可以用但垂直翻转要慎重管底沉积和管顶结垢在不同检测标准里对应不同判级维度垂直翻转等于把这两类语义交换模型会收到错误监督。我习惯把所有增强参数收敛到一份 yaml 里方便训练时复现和修改# pipe_augment.yaml train: data/train/images val: data/val/images nc: 7 names: [crack, deformation, collapse, corrosion, deposition, root, scale] augment: hsv_h: 0.02 # 色相扰动幅度小管道缺陷靠纹理不靠颜色 hsv_s: 0.5 hsv_v: 0.4 scale: 0.3 # 摄像头进深不同尺度变化需要给足 fliplr: 0.5 # 水平翻转管道左右对称 flipud: 0.0 # 禁掉垂直翻转管顶/管底语义不可交换 mosaic: 0.8 # mosaic 对小目标密集场景提升明显 mixup: 0.0 # 管道图像纹理干净mixup 容易产生脏标签参数说明中几个关键值hsv_h 只设 0.02因为管壁材质和缺陷的判断依赖边缘灰度而不是颜色scale 给 0.3 是为了模拟摄像头在管道内不同工作距离造成的目标尺度差异这比翻转更有价值mosaic 保持 0.8它能显著提升树根、细裂缝这类 64 像素以下小目标的特征泛化能力mixup 建议关掉管道里同类缺陷高度相似混合两帧图像产生的中间样本既不属于源类型又会把标签分布搅乱实际增益为负。3. 缺陷检测模型选型与训练参数yolov8 为主halcon 作补充3.1 目标检测、实例分割、传统视觉三选一下水道缺陷检测的本质是“找到异常区域并给出框”目标检测已经覆盖大部分验收需求。实例分割对裂缝这类细长目标有像素级优势但标注成本高而且结构性和功能性缺陷的判级主要看长度和面积占比分割结果还要进一步转成形态学指标工程链路变长。Halcon 这类传统机器视觉方案用阈值分割加形状特征筛选可以做锈蚀、结垢这种纹理稳定的缺陷但遇到车灯角度变化导致的光照剧烈波动算法参数就要跟着改现场维护成本极高。对比关系如下方案单帧推理耗时小目标能力工程复杂度管道场景建议Faster R-CNN 系列100ms 以上中高数据组织繁琐不推荐作为初始方案YOLOv8s8-15ms中上低首选样本不足 5000 帧时最稳YOLOv8m15-25ms上低样本超过 8000 帧时升级RT-DETR30ms 左右上中实时性、精度双重要求时尝试Halcon 传统视觉5ms 左右差依赖规则库只做单一纹理类缺陷复核部署时我会优先 YOLOv8s 起步它在下水道这种背景相对单调、目标类型固定的场景里训练收敛快边缘设备也能跑得动。Halcon 的角色不是替代而是在检测结果上做二次确认例如对“腐蚀”类缺陷做灰度共生矩阵分析来过滤一部分规则性误报。3.2 yolov8 训练命令与每组参数的依据YOLOv8 的 CLI 可以直接完成训练但要保证项目结果可复现我习惯把关键增强参数和训练参数全部显式写进命令而不是依赖默认配置。一个可实际跑通的启动命令如下yolo detect train \ datapipe_augment.yaml \ modelyolov8s.pt \ imgsz1280 \ batch16 \ epochs150 \ lr00.001 \ augmenttrue \ patience30 \ projectruns/pipe \ nametrain_v1命令里最容易忽略的是 imgsz。管道视频原始帧通常是 1080pimgsz 从默认 640 提到 1280对小裂缝和树根的召回提升非常明显代价是显存需求接近翻倍。8G 显存的 GPU 要把 batch 降到 8否则会在前几个 epoch 就被 OOM 打断。lr0 设为 0.001 是因为 COCO 预训练权重和管道图像分布差异很大学习率太大会把浅层通用特征直接冲坏。patience30 表示验证集指标连续 30 个 epoch 不提升就提前停止这是防止网络在数量少的缺陷类别上过拟合的最后一道保险。训练日志看 runs/pipe/train_v1/ 下的 results.csv重点盯 box_loss 的下降曲线。如果训练集 loss 一直降而验证集 loss 在某个 epoch 后反弹说明模型开始背训练集里的光照特征这时候回退到反弹前的权重并检查增强配置里是否误开了垂直翻转。3.3 数据不平衡与早停的使用边界下水道数据里沉积类样本往往占一半以上裂缝可能只有 5%。直接拿去训练模型会把稀缺类往背景上推。YOLOv8 没有内置 per-class loss 权重常见的做法是重采样把沉积类下采样到总样本的 30%同时保留全部裂缝和塌陷样本。采样后要重新检查验证集分布不能让某一类在 val 里一个样本都没有。每个训练轮次结束后还要单独打印每个类别的验证 AP。如果某类 AP 长期低于 0.5不要急着改模型结构先回查该类别的标注质量。管道缺陷标注最容易出问题的是“裂缝”和“阴影”这两类混淆会让 AP 卡在 0.4 附近并且无论怎么调超参都上不去。4. 推理阶段的图像视觉调优切图、阈值、去重与导出4.1 小目标漏检先做滑窗切图推理模型上了工地就掉点多半不是训练的问题而是远端缺陷太小。CCTV 摄像头贴近管壁扫过时画面深处的裂缝可能只有 20 到 40 像素高整图推理时这些目标经过下采样后特征基本丢失。常见做法是切图推理我一般用滑窗把原图切成 640x640 的块并带 25% 重叠from ultralytics import YOLO model YOLO(runs/pipe/train_v1/weights/best.pt) def detect_tiled(frame, tile_size640, overlap0.25, conf0.25): h, w frame.shape[:2] step int(tile_size * (1 - overlap)) dets [] x 0 while x w: y 0 while y h: tile frame[y:y tile_size, x:x tile_size] res model.predict(tile, imgsz640, confconf, verboseFalse)[0] for box in res.boxes: x1, y1, x2, y2 box.xyxy[0].cpu().numpy() dets.append([x x1, y y1, x x2, y y2, float(box.conf), int(box.cls)]) y step x step return dets切图参数说明overlap 设为 0.25也就是四个方向重叠 25%避免目标恰好被 tile 边界切断tile 尺寸和模型输入保持一致避免二次 resize 引入形变。代价是单帧推理次数成倍增加如果实时性不够改成只对画面远端 1/3 区域切图近端直接整图推理。重叠区域的目标会被检测多次需要把框坐标换算回原图后做一次全局 NMSimport torch from torchvision.ops import nms as tv_nms boxes torch.tensor([d[:4] for d in dets], dtypetorch.float32) scores torch.tensor([d[4] for d in dets], dtypetorch.float32) keep tv_nms(boxes, scores, iou_threshold0.5) final [dets[i] for i in keep.tolist()]4.2 置信度与 IoU 阈值控制在什么范围现场推理时置信度阈值不能直接沿用训练时的 0.25。甲方管道检测更怕漏报因为漏掉一个塌陷意味着整段管道可能报废而误报可以由人工复核兜底。落地时我会把 conf 压到 0.15 到 0.2让模型多出候选框再用规则过滤面积小于 200 像素且连续出现少于 2 帧的框直接舍弃。IoU 阈值在 NMS 阶段保持 0.5如果切图重叠区域出现大量重复框可以提到 0.6但不要超过 0.7否则相邻的两个真实缺陷会被合并成一个。阈值不是调一次就固定。准备 200 帧实拍片段分别在 conf 0.1、0.2、0.3 下跑三遍统计每档的框总数和人工确认数然后画一条精确率-召回率曲线再结合甲方的验收口径去选择落点。4.3 跨帧去重让堵塞缺陷的重复计次消失视频检测最容易出现的问题是把同一个缺陷在相邻帧里重复计数。特别是“沉积/堵塞”这类连续大块目标不去重的话一段 5 米长的淤积会被计成几十个缺陷。处理方式是用 IoU 做跨帧关联当前帧的框与上一帧任一框的 IoU 大于 0.3就判定为同一缺陷只记录首次出现帧号和类别后续只更新最后出现帧号和最大置信度缺陷编号类别首次帧号末次帧号最大置信度D001crack1281560.87D002deposition2102400.92输出这份清单后再回到原始视频截取首次出现帧交给人工复核。跨帧关联的 IoU 阈值 0.3 不能设太高否则检测框抖动的帧会被误判为新缺陷也不能设太低否则紧挨着的两个独立缺陷会被合并成一个。4.4 ONNX 导出与低配置工控机部署项目验收阶段常要求部署到没有 GPU 的工控机。YOLOv8 导出 ONNX 后用 onnxruntime CPU 推理即可yolo export modelruns/pipe/train_v1/weights/best.pt formatonnx opset12 simplifyTrueopset 用 12 是兼容性考虑过高的版本在老设备上会报算子不支持simplify 参数让 onnxsim 折叠常量体积能缩小 10% 左右。CPU 推理时输入尺寸建议退回 640否则单帧延迟可能从 20ms 拉到 100ms 以上。离线判读场景可以保留 1280 输入换取召回实时预警场景则必须降到 640并把 4.1 节的切图逻辑改成只对感兴趣区域执行。5. 项目分享 zip 到手验证三件套校验、回归、置信度校准5.1 先校验文件完整性再对环境做差异化对比从网上下载或同事转来的项目 zip第一个坑是解压后路径里含中文OpenCV 的 imread 在部分系统上会直接返回空对象。我拿到包的第一步是查目录结构确认根目录下有没有 requirements.txt、环境 yaml、权重文件以及数据集标注是否齐全。然后做完整性校验sha256sum defect_detection_pipe.zip unzip defect_detection_pipe.zip -d ./pipe_project cd pipe_project python -c import torch; print(torch.__version__, torch.cuda.is_available())对比发布者给出的 sha256 值只解决传输损坏问题更关键的是环境差异。项目包的 requirements.txt 往往包含 opencv-python、ultralytics、torch 等版本直接 pip install -r 可能把你本机已调好的 CUDA 环境破坏掉。我的做法是先pip freeze current_env.txt再与 requirements.txt 做差异比对只安装缺失或版本不兼容的库。torch 的 cuda 版本建议单独安装不放进 requirements。5.2 用自备帧做回归别直接重训别人训好的权重不能直接拿来做验收因为你不知道它的训练集长什么样。正确做法是先准备 50 到 100 帧来自目标管段的实拍截图跑一遍推理脚本统计框数随置信度变化的曲线。如果框集中在画面同一位置且与缺陷无关基本可以判断模型过拟合了样本的管道环境如果置信度分布整体偏低说明源域和目标域差异较大需要继续微调。这一轮回归不依赖标注先只看框的合理性。抽 10 帧人工核对框住的区域里有没有真正的裂缝或沉积。如果人工认可率在 70% 以上说明预训练权重还能用低于 30% 就要重新标注一批本地数据来微调而不是硬调阈值。5.3 按验收口径校准检测置信度最后一件事是校准置信度与验收指标的关系。如果模型检了 100 个框人工确认其中 70 个是真实缺陷那么当前阈值下的精确率就是 70%。甲方对功能性堵塞更在意漏报也就是把有堵塞的管段判成通畅这时要把精确率放宽到 50% 左右换取更高的召回。反过来如果甲方只是做内部普查误报会给人工复核增加成本可以收紧到精确率 80% 与召回率 60% 的交叉点。实际操作中我会把 conf 从 0.15 到 0.4 每隔 0.05 跑一遍回归集画出精确率和召回的交叉曲线再让甲方在曲线上选点。哪怕只是把 conf 从 0.25 改成 0.2在低照度井段上漏报也能降低 8 到 10 个百分点改完 conf 后用 4.3 节的跨帧去重逻辑保证框数统计可信这轮校准才算闭环。之后再去动训练代码里的增强参数和 imgsz才是在有效基线之上的优化。本文还有配套的精品资源点击获取