ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

下水道管道缺陷检测源码实战:图像预处理与弧线检测全流程解析

下水道管道缺陷检测源码实战:图像预处理与弧线检测全流程解析 简介这份资源面向计算机视觉与智慧城市基础设施方向的开发者、学生及算法工程师聚焦下水道管道堵塞与缺陷的自动检测问题。传统人工巡检效率低且存在安全风险而该方案借助摄像头采集管道内部图像结合图像预处理、模式识别与深度学习如CNN完成堵塞、裂缝、渗漏等缺陷的识别与严重程度评估并涉及3D视觉、无人机等扩展思路。压缩包共9个文件约910KB包含6个Python脚本、2张示例图片和1份README说明文档脚本覆盖图像归一化、圆形掩膜、时间转换、轮廓高亮与弧线检测等模块图片可用于快速验证算法效果文档则帮助理解项目结构与运行方式。目前已有107人学习下载适合希望快速上手管道缺陷检测、复用图像处理与检测脚本、或作为课程设计与项目原型参考的读者。1. 下水道管道缺陷检测这套源码到底能跑出什么结果城市地下管网排查最头疼的不是没相机而是拍回来一堆模糊、反光、带水渍的管内视频人工逐帧看一天也标不出几处堵塞。这套「缺陷检测-基于图像视觉的下水道管道堵塞缺陷检测」资源包走的是传统图像处理路线不依赖深度学习训练拿到就能在普通笔记本上跑通。它用圆形掩膜裁掉管道图像四周的无效区域再做 RGB 归一化压掉光照不均接着用轮廓检测和弧线检测定位堵塞物与结构性缺陷。适合做市政管网巡检、工业管道内窥检测的从业者也适合想入门图像视觉缺陷检测的学生拿来做第一个可复现的项目。包里带了 Sample.jpg 和 Sample2.jpg 两张样例图README.md 说明运行入口Main.py 是主流程其余脚本各管一个环节。下面按实际拆包顺序讲清楚每个文件干什么、参数怎么调、哪里容易翻车。2. 拆开压缩包先看文件六个脚本的分工与调用链2.1 从 Main.py 反推执行顺序拿到一个没文档的视觉项目我习惯先看主入口调了谁。Main.py 里通常按「读图 → 归一化 → 圆形掩膜 → 缺陷检测 → 结果叠加」串起来。打开后重点找 import 了哪些本地模块就能还原调用链。常见写法是# Main.py 典型结构按资源包内脚本名推断 import cv2 import numpy as np from nomralizeRGB import normalize_rgb # 注意文件名拼写是 nomralize from circularMask import apply_circular_mask from arcDetect import detect_arc_defects from contorsHighlight import highlight_contours img cv2.imread(Sample.jpg) img normalize_rgb(img) # 第一步压光照 img apply_circular_mask(img) # 第二步裁掉管壁外区域 defects detect_arc_defects(img) # 第三步弧线/裂缝检测 result highlight_contours(img, defects) # 第四步把缺陷画回原图 cv2.imwrite(output.jpg, result)逻辑说明normalize_rgb 负责把三通道亮度拉平避免管道一侧过曝一侧死黑apply_circular_mask 用圆形掩膜把画面裁成管道内壁的圆环区域减少管壁外噪声干扰detect_arc_defects 针对裂缝这类弧形结构做检测highlight_contours 把检出的轮廓用高亮色叠回原图方便人工复核。参数说明cv2.imread 默认读 BGR如果你的样例图是灰度图后续归一化函数里要判断通道数否则会报 shape 错误。掩膜半径一般取图像短边的 0.450.48 倍留一点边缘余量取满 0.5 会把管壁反光带进来。2.2 文件名拼写与模块导入的坑资源包里归一化脚本叫nomralizeRGB.py不是normalizeRGB.py这是原作者的拼写。你 import 时必须照抄否则 ModuleNotFoundError。我一般会在项目根目录先跑一遍导入测试python -c import nomralizeRGB, circularMask, arcDetect, contorsHighlight, timeConvert; print(all ok)如果某个模块报缺 cv2 或 numpy先装依赖pip install opencv-python numpytimeConvert.py 从名字看是处理视频时间戳或帧号转换的如果你只跑单张图可以暂时不调它要做视频逐帧检测时用它把帧序号换算成实际时间方便定位缺陷出现在第几秒。2.3 样例图先跑通再换自己的数据别急着拿现场视频往里灌。先用 Sample.jpg 跑一遍确认输出图能正常生成、缺陷框位置合理再换 Sample2.jpg 验证第二张。两张都过了说明环境没问题。换自己数据时注意样例图大概率是已经裁好的管道内壁正视图如果你直接丢一张带法兰、带支架的现场图圆形掩膜会把有效区域也裁掉。常见做法是先用 circularMask 里的调试开关把掩膜边界画出来看一眼确认圆心和半径对得上再关掉调试。3. 图像预处理两个核心脚本归一化与圆形掩膜怎么调3.1 nomralizeRGB.py 的归一化逻辑与参数管道内窥图像最大的问题是光源偏心一侧亮到发白另一侧暗到看不清纹理。归一化的目的不是增强对比度而是把整体亮度分布拉到一个稳定区间让后续阈值分割不因光照漂移而失效。常见实现是逐通道做线性拉伸或 CLAHE。假设脚本里用的是简单 min-max 归一化# nomralizeRGB.py 归一化核心逻辑 def normalize_rgb(img): img img.astype(np.float32) for c in range(3): ch img[:, :, c] ch (ch - ch.min()) / (ch.max() - ch.min() 1e-6) * 255 img[:, :, c] ch return img.astype(np.uint8)逻辑说明逐通道减最小值除极差把每个通道拉到 0255。加 1e-6 是防止全黑图除零。这样处理后三通道动态范围一致后续转灰度或做颜色阈值时不会因为某通道偏暗而漏检。参数说明如果你发现归一化后噪点被放大说明原图暗部噪声重应该先做一次高斯滤波再归一化核大小取 3 或 5。如果管道图像本身对比度就够可以跳过归一化直接进掩膜避免过度拉伸把水渍反光变成假边缘。3.2 circularMask.py 的圆心半径怎么定圆形掩膜是这套流程里最影响检出率的环节。管道内壁在图像里通常呈一个圆或椭圆掩膜的作用是把圆外的管壁、支架、电缆全部置黑只保留内壁区域。核心就三行# circularMask.py 圆形掩膜 def apply_circular_mask(img, radius_ratio0.46): h, w img.shape[:2] mask np.zeros((h, w), dtypenp.uint8) center (w // 2, h // 2) radius int(min(h, w) * radius_ratio) cv2.circle(mask, center, radius, 255, -1) return cv2.bitwise_and(img, img, maskmask)逻辑说明先建全黑掩膜在中心画白色实心圆再和原图做按位与圆外变黑。center 默认取图像几何中心适用于相机正对管道轴心的拍摄方式。参数说明radius_ratio 默认 0.46意思是取短边的 46% 作半径。如果你发现掩膜后边缘还有一圈亮环说明半径偏大降到 0.42 试试如果内壁有效区域被裁掉一块说明相机没对准轴心需要手动改 center 坐标。我一般会加一个调试分支把 mask 边界用红色画在原图上存一张 debug 图确认无误再跑正式流程。3.3 预处理顺序为什么不能反有人图省事先掩膜再归一化结果圆外全黑区域参与 min-max 计算把最小值拉到 0归一化后内壁整体偏亮阈值全乱。正确顺序一定是先归一化再掩膜或者掩膜后只在掩膜区域内做归一化。这个顺序问题在血泪经验里排前三换数据后检出率突然掉一半八成是顺序反了。4. 缺陷检测与轮廓高亮arcDetect 和 contorsHighlight 实战4.1 arcDetect.py 的弧线检测思路管道裂缝在图像里表现为细长弧线堵塞物则是不规则团块。arcDetect 从名字看侧重弧线常见做法是 Canny 边缘 霍夫变换或轮廓拟合。一个可跑的简化版# arcDetect.py 弧线/裂缝检测 def detect_arc_defects(img, min_area80): gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges cv2.Canny(gray, 50, 150) # 双阈值边缘 contours, _ cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) defects [] for cnt in contours: area cv2.contourArea(cnt) if area min_area: continue # 滤掉噪点小轮廓 perimeter cv2.arcLength(cnt, True) circularity 4 * np.pi * area / (perimeter * perimeter 1e-6) if circularity 0.3: # 越接近 0 越像细长弧线 defects.append(cnt) return defects逻辑说明Canny 提取边缘后找外轮廓用面积过滤噪点再用圆度公式区分团块和细长弧线。圆度接近 1 是圆接近 0 是细长形状裂缝和刮痕通常圆度很低。参数说明Canny 的 50/150 是低/高阈值光照均匀的图可以提到 80/200 减少假边缘min_area 默认 80 像素图像分辨率高时要按比例放大比如 1080P 图可以设到 300。圆度阈值 0.3 是经验值想只抓裂缝可以降到 0.2想连堵塞团块一起抓就提到 0.6。4.2 contorsHighlight.py 把缺陷画回原图检测出轮廓后要让人能一眼看到缺陷在哪。contorsHighlight 通常做两件事用醒目颜色描边加编号或面积标注。# contorsHighlight.py 轮廓高亮 def highlight_contours(img, defects, color(0, 0, 255), thickness2): out img.copy() for i, cnt in enumerate(defects): cv2.drawContours(out, [cnt], -1, color, thickness) x, y, w, h cv2.boundingRect(cnt) cv2.putText(out, fD{i1}, (x, y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1) return out逻辑说明drawContours 把每个缺陷轮廓描红boundingRect 取外接框左上角putText 在框上方标 D1、D2 编号方便和检测报告对应。参数说明color 是 BGR 顺序(0,0,255) 是红色thickness 在 1080P 图上建议 23太小看不清太大盖住缺陷本身。编号字号 0.5 适合 720P1080P 可以提到 0.7。4.3 检出结果怎么判断靠不靠谱跑完先看输出图重点看三类误检管壁接缝被当成裂缝、水渍反光被当成堵塞、掩膜边缘被当成缺陷。接缝误检通常是 Canny 阈值太低水渍误检是归一化过度拉伸掩膜边缘误检是半径偏大把边界带进来了。我一般会拿 Sample.jpg 和 Sample2.jpg 各跑三组参数记录检出数量和误检位置选一组在两张图上都稳定的参数作为默认值再拿去跑现场数据。5. 避坑与排查这套源码最容易翻车的五个地方5.1 现象ModuleNotFoundError: No module named normalizeRGB原因资源包内文件名是nomralizeRGB.py拼写为 nomralizeimport 时按正确拼写写会找不到。解决import 语句照抄文件名from nomralizeRGB import ...或者把文件重命名为 normalizeRGB.py 并同步改所有引用。重命名更规范但要注意 Main.py 里可能也写了原拼写两处一起改。5.2 现象掩膜后图像全黑或只剩一个小圆原因radius_ratio 传了 0.05 这类过小值或者图像短边本身很小乘完半径只剩几像素。解决打印min(h, w)确认图像尺寸radius_ratio 保持在 0.40.48。如果原图分辨率低于 200px先放大再处理否则掩膜和轮廓检测都没有足够像素支撑。5.3 现象Canny 边缘图全是噪点轮廓数量几百个原因管道图像噪声重或者归一化把暗部噪声放大了Canny 低阈值 50 太低。解决在 Canny 前加高斯滤波cv2.GaussianBlur(gray, (5,5), 0)低阈值提到 80100高阈值提到 200。如果还多用形态学开运算去掉细碎边缘。5.4 现象换自己的图后一个缺陷都检不出原因样例图是正对管道轴心的圆形视野现场图可能是斜视、椭圆视野圆形掩膜把有效区域裁掉了或者缺陷在掩膜外。解决先关掉掩膜跑一遍看原始检测能不能出结果。能出说明是掩膜问题需要改圆心坐标或改用椭圆掩膜不能出说明是阈值问题按 5.3 调 Canny 参数。5.5 现象输出图缺陷框位置偏移原因highlight_contours 在掩膜后的图上画框但保存时又和原图尺寸不一致或者中途做了 resize 没同步坐标。解决确保从读图到保存全程尺寸不变。如果必须 resize把缩放比例记下来画框前把轮廓坐标乘回去。我一般会在 Main.py 开头固定img cv2.resize(img, (640, 640))后续所有操作都基于这个尺寸避免坐标错乱。6. 从单张图到批量视频timeConvert 的用法与参数固化技巧单张图跑通只是第一步实际巡检拿到的是几十分钟的管内视频。timeConvert.py 就是干这个衔接的。常见实现是把帧号换算成时间戳或者把视频按固定间隔抽帧存成图片序列。我一般这样用# 批量抽帧 时间戳记录 import cv2 from timeConvert import frame_to_timestamp # 按资源包内函数名推断 cap cv2.VideoCapture(pipe.mp4) fps cap.get(cv2.CAP_PROP_FPS) interval int(fps * 2) # 每 2 秒抽一帧 idx 0 while True: ret, frame cap.read() if not ret: break if idx % interval 0: ts frame_to_timestamp(idx, fps) # 换算成 00:01:23 形式 cv2.imwrite(fframes/{ts}.jpg, frame) idx 1 cap.release()逻辑说明按固定帧间隔抽帧避免逐帧处理几万张图。frame_to_timestamp 把帧号除以 fps 得到秒数再格式化成时分秒文件名直接带时间戳后面检出缺陷能对应到视频第几秒。参数说明interval 取 fps 的 13 倍2 秒一帧适合巡检视频缺陷不会只出现一瞬。如果管道移动快改成 0.5 秒一帧。抽帧后批量跑 Main.py把每张图的检出结果汇总成 CSV字段包括文件名、缺陷编号、面积、圆度方便排序看哪些位置缺陷最密集。参数固化有个习惯一旦在样例图上定好 Canny 阈值、掩膜半径、min_area 这三个值就写进一个 config.py所有脚本从 config 读不要散落在各个文件里。换项目时只改 config不动算法代码。这套源码包没带 config我建议你自己加一个后面维护省很多事。从那以后我每次拿到这类图像检测包都先跑样例图、再跑一张自己的图、最后跑一段视频抽帧三步都过了才敢往正式数据上铺。希望帮到你。本文还有配套的精品资源点击获取
返回列表