
简介基于Python和OpenCV开发的材料缺陷检测程序是一份面向图像处理初学者的完整工程资源可支撑毕设、课程设计或工程实训。压缩包共55个文件总大小986KB主要包含3个Python主程序、20张JPG实验图片、12个XML配置文件、3个CSV数据文件以及drawio流程图和readme说明。资源内置三个迭代版本从基础版到最新版逐步优化便于对比不同阶段的图像预处理、阈值分割和结果输出逻辑。每版均附带原始图、平面图、阈值图与结果图能够直观复现缺陷检测从输入到输出的全过程。已有139人学习下载适合希望通过实际代码理解OpenCV操作细节的读者。借助包内流程图、CSV数据文件和分版本目录结构可快速定位关键模块学习灰度化、二值化、轮廓或区域筛选等经典方法并基于现有脚本做二次修改与实验验证。1. 基于Python和OpenCV的材料缺陷检测一张薄片上的瑕疵怎么变成数字提到材料缺陷检测很多人第一反应是要上深度学习和工业相机。但这套基于Python和OpenCV开发的程序走的是另一条路用传统图像处理把缺陷的位置、面积、周长直接算出来连模型训练都不用拿到就能跑。解压之后你会看到 main.py、几张样板图、data.csv 和流程图文件三个 ImageProcessing 目录是作者迭代留下的版本痕迹。适合毕设、课程设计或工程实训阶段想快速搞懂 OpenCV 图像处理完整链路又不希望只对着 PPT 看概念的人。2. 工程结构与主链路main.py 里那张缺陷图是怎么生成的2.1 目录结构与三个版本目录说明哪些改动先看压缩包结构整个 ImageProcessing_OpenCV-main 下面有三套代码目录分别是 ImageProcessing、ImageProcessing(new) 和 ImageProcessing(latest)外加根目录一份 README.md 和流程图文件。三个目录不是重复打包而是作者逐步迭代留下的版本痕迹从文件变化能看出思路演进。目录新增/变化的文件对应阶段ImageProcessingImg_plane.jpg、Img_source.jpg、result.jpg第一版出结果图ImageProcessing(new)新增 heat.jpg、Img_thres.jpg、Img_result.jpg第二版补中间过程图ImageProcessing(latest)新增 gridSampling.jpg、sampling.jpg、result_1~3.jpg第三版批量与分块采样新手拿到之后直接看 latest 版本就好前面的版本留着对照演进。每个版本里都有一份 readme.txt第一次跑先把那个 readme 打开里面写了运行先后顺序。我一般会把三个目录先在 IDE 里打开做 diff观察同一张 Img_source.jpg 在不同版本里处理结果有什么不同这是拆这类项目的第一步比直接跑代码更快建立全局印象。2.2 main.py 的处理链路灰度→二值→形态学→轮廓这里要说清楚 main.py 具体做了什么。虽然不同版本略有差异但主链路是一致的按这段代码来走import cv2 import numpy as np import pandas as pd img cv2.imread(Img_source.jpg) # 读入原始材料照片 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转灰度简化计算 ret, thres cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV) kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) thres cv2.morphologyEx(thres, cv2.MORPH_CLOSE, kernel) contours, hierarchy cv2.findContours(thres, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) result img.copy() records [] for idx, cnt in enumerate(contours, 1): area cv2.contourArea(cnt) if area 100: # 过滤噪声区域 continue cv2.drawContours(result, [cnt], -1, (0, 0, 255), 2) records.append([idx, area, cv2.arcLength(cnt, True)]) pd.DataFrame(records, columns[id, area, perimeter]).to_csv(data.csv, indexFalse) cv2.imwrite(Img_result.jpg, result)这段代码每一行都要看懂cv2.imread读图不传第二个参数时默认带通道彩色图。后续转灰度是为了把三通道降成一维单通道图做阈值运算速度更快也不会被材料本身的颜色干扰判断。cv2.threshold里 127 是固定阈值像素值大于127的变白、小于的变黑。这里用THRESH_BINARY_INV反向二值化因为材料缺陷通常是暗色区域反向之后缺陷变白色前景方便后边找轮廓。cv2.morphologyEx是形态学闭运算3x3 矩形核可以让断裂的缺陷边缘连起来但不明显改变缺陷面积。核越大连接能力越强也越容易把相邻缺陷粘成一块。cv2.findContours返回轮廓点和层级关系。OpenCV 4.x 里这个函数返回两个值OpenCV 3.x 返回三个值这是最常见的翻车点第四章详细说。面积过滤是关键参数小于 100 像素的轮廓当作噪声直接跳过。这个值要根据实际图片分辨率调不是固定的。跑完之后磁盘上会多出两个文件data.csv记录每个缺陷轮廓的面积周长Img_result.jpg是标红圈的缺陷标记图。这个流程就是整个程序的核心后面所有版本改动都围绕这条主链路加东西。2.3 流程图.drawio 和 readme 透露的设计意图压缩包里有一对文件流程图.png 和流程图.drawio。.drawio 是 draw.io 的工程文件可以用 draw.io 桌面版或者网页版直接打开继续改图png 是导出的静态图片。这两份图表达的处理顺序跟 main.py 基本一致读取图像、灰度转换、图像二值化、形态学处理、轮廓提取、缺陷标记、结果输出。提示把 readme.txt 和流程图.drawio 一起打开对照 main.py 看一遍能搞清楚作者当时是先写代码还是先画流程。多数情况下这份流程图画在了代码之后是给报告准备的。如果要把这套流程写进课程设计报告我建议直接用 draw.io 打开改两处把处理框的颜色按输入、处理、输出分三类在原流程末尾加一个“数据记录”分支把 data.csv 的输出路径也画上去。这样流程图和代码就对上了答辩时不会被问倒。3. 环境与运行把 main.py 跑起来并读懂 data.csv3.1 Python 与 OpenCV 安装三种环境的安装顺序按现在的常见环境Python 3.8 到 3.12 配 OpenCV 4.x 都没问题。用 pycharm 配置 python 环境时注意项目解释器要选到 venv 而不是系统 Python否则容易出现装了包但导入失败的问题。python -m venv venv source venv/bin/activate # Windows 上执行 venv\Scripts\activate pip install opencv-python pandas numpy python -c import cv2; print(cv2.__version__)最后一行能打印出 4.x 版本号就说明安装成功。这里要提醒opencv-python是官方预编译包不需要自己用 cmake 编译如果你以后转 OpenCV C 方向才需要走 cmake 编译步骤。遇到ModuleNotFoundError: No module named opencv是因为模块名是cv2不是opencvimport 必须写cv2。如果是 vscode 配置 python 环境注意启动终端时要先激活虚拟环境否则 pip install 装到全局编辑器里跑又找不到 cv2这类环境错位问题在第四章细说。3.2 运行 main.py 并调试关键参数把 main.py 放在和 Img_source.jpg 同一个目录下然后执行python main.py如果原来的 main.py 写的是相对路径工作目录不对就会报找不到图片。我一般会在 main.py 开头加两行保护防止路径翻车import os os.chdir(os.path.dirname(os.path.abspath(__file__)))这两行的作用是把当前工作目录强制切到脚本所在目录这样不管用 pycharm 运行还是命令行运行Img_source.jpg 都能被找到。参数层面最值得调的三个地方阈值 127材料表面偏亮或偏暗时 127 就不适用。可以用大津法 OTSU 替代让程序自己算阈值代码是cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU)。形态学核大小 3x3缺陷细碎就调成MORPH_CROSS十字核避免把两个独立缺陷粘在一起。最小轮廓面积 100分辨率越高这个下限要跟着调高否则图上每一个噪点都会进 data.csv。这三个参数是这套程序的“黑匣子旋钮”调参时一次只动一个改完立刻看 Img_result.jpg 的变化不要同时动两个。3.3 data.csv 输出解读与 result 系列图片运行成功之后当前目录出现 data.csv。用 Excel 或 pandas 打开每一行是一条缺陷记录列名含义典型数值id缺陷编号按轮廓检出顺序排1, 2, 3...area缺陷像素面积800.0perimeter缺陷周长像素124.3如果 data.csv 是空的说明所有轮廓面积都小于过滤阈值这不是程序坏了是阈值或光照问题。再看输出图片result.jpg、Img_result.jpg、result_1.jpg、result_2.jpg、result_3.jpg 是不同迭代版本保存的结果heat.jpg 是类似热力图的缺陷分布可视化。检查结果图时重点看红圈位置是不是真的对应材料缺陷如果圈在毛刺或边框上说明预处理还需要加一步去边框的操作常见做法是在二值化之后做一次边缘裁剪去掉图像边界处的干扰连通域。4. 材料缺陷检测避坑指南五个常见的翻车现场与修复方案4.1 ModuleNotFoundError: No module named cv2现象在 pycharm 里点运行控制台报 No module named cv2但在终端里 import cv2 却正常。原因pycharm 的项目解释器和你终端里 pip 指向的不是同一个 Python。pycharm 默认创建 venv 虚拟环境而 pip install 装到全局环境去了。解决在 pycharm 的 Terminal 面板里执行pip install opencv-python或者手动把项目解释器路径切到全局 Python。最简单的验证方式是打开 pycharm 的 Python Console输入import cv2能过就说明当前解释器已经装好。4.2 固定阈值 127 换一张图片就失效现象用下载包里的 Img_source.jpg 跑得好好的换成自己拍的材料照片结果图上大片区域被当成缺陷或缺陷完全检测不到。原因127 是硬编码固定阈值。不同批次材料因为底色、光照、相机参数不同灰度分布完全不一样固定阈值没有自适应能力。解决改用 OTSU 自适应阈值或者先打印灰度直方图再人工定阈值。OTSU 一行改动就能避免大部分问题threshold_value, thres cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU)注意 OTSU 要求输入是单通道灰度图且直方图最好接近双峰分布否则算出来的阈值会落在两个峰之间偏上或偏下的位置。真遇到直方图没有明显双峰的情况再回来手调 127 也不迟。4.3 findContours 返回值差异ValueError 或 IndexError现象复制了网上某个 OpenCV 3.x 时代的代码跑cv2.findContours时直接报ValueError: not enough values to unpack (expected 3, got 2)。原因OpenCV 4.x 改了这个 API函数只返回 contours 和 hierarchy 两个值旧代码里image, contours, hierarchy cv2.findContours(...)的三变量写法已经不适用。解决统一用新版写法contours, hierarchy cv2.findContours(thres, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)顺便说一个更隐蔽的坑findContours 会修改输入的二值图如果你后面还要用 thres 做别的计算一定要先thres.copy()再传进去。4.4 imread 碰到中文路径返回 None现象cv2.imread 不报错但打印 img 是 None程序直接崩在下一行 cvtColor。原因OpenCV 的 imread 在 Windows 上对中文路径支持不好或者相对路径的工作目录不对。解决项目路径里不要有中文同时用第二章说的os.chdir把工作目录强制切到脚本目录避免 pycharm 默认运行目录和脚本目录不一致。这两点都做到路径相关的报错基本绝迹。4.5 形态学闭运算把多个缺陷粘成一个大块现象分割出来的缺陷区域比实际看起来大很多两个相邻缺陷被算成一条。原因闭运算的核选得太大。MORPH_RECT 3x3 在小分辨率图上可能已经能连接几个近邻缺陷如果调整成 5x5粘连会更严重。解决把核缩小或者改成十字形。我的经验是先小后大kernel cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) thres cv2.morphologyEx(thres, cv2.MORPH_CLOSE, kernel)MORPH_CROSS 十字核只在水平和垂直方向连接斜向的像素不会强行粘连对材料表面的细长缺陷更友好。改完再看二值图缺陷边缘明显干净很多。5. 进阶把矩形框和数字变成缺陷报告5.1 轮廓特征扩展长宽比、填充度与缺陷分类基础版只输出面积和周长。实际上截面缺陷的形状特征可以区分类型裂纹通常是长条气泡接近圆形划痕填充度很低。用 cv2.minAreaRect 和 cv2.boundingRect 可以扩展特征for cnt in contours: area cv2.contourArea(cnt) if area 100: continue x, y, w, h cv2.boundingRect(cnt) rect cv2.minAreaRect(cnt) (rx, ry), (rw, rh), angle rect aspect min(rw, rh) / max(rw, rh) # 长宽比越小越像裂纹 fill_ratio area / (w * h) # 填充度越小越像划痕 records.append([idx, area, w, h, round(aspect, 3), round(fill_ratio, 3)])长宽比接近 1 说明外接矩形接近正方形气泡概率高长宽比小于 0.3 说明是细长区域裂纹概率高。填充度是面积与包围矩形面积的比值划痕通常是一条细线填充度很小。这个思路能直接把输出的 data.csv 扩展成带属性列的缺陷表格导入 Excel 后可以做筛选比肉眼翻结果图高效得多。5.2 像素到物理尺寸的换算材料检测最终要报告毫米级别的缺陷尺寸。常见做法是找一条已知宽度的参照物在相同拍摄距离下拍一张标定图像# 参考物宽度 10mm在图中占 480 像素 pixel_per_mm 480 / 10.0 def mm_of(pixels): return round(pixels / pixel_per_mm, 2) print(mm_of(900)) # 输出 18.75 mm这套比例换算的前提是相机到材料表面的距离固定换了机位或者变焦都要重新标定。如果你只有一张图没有参照物也可以退而求其次直接用像素面积做相对比较至少能判断缺陷大小的排名。5.3 网格采样gridSampling.jpg 提示的大幅面处理思路latest 版本目录里有 gridSampling.jpg 和 sampling.jpg这是作者处理大面积材料的思路把整张图按网格切成多块逐块检测再合并结果。step 512 h, w gray.shape for y in range(0, h, step): for x in range(0, w, step): patch gray[y:ystep, x:xstep] _, patch_thres cv2.threshold(patch, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU) # 在 patch_thres 上找轮廓坐标需要加上 (x, y) 偏移网格分块的好处有两个一是大图直接做阈值分割时光照不均会造成局部误检分块后每块阈值独立适应亮度变化二是内存占用可控超大图不至于撑爆内存。缺点是块与块接缝处可能切断缺陷我的做法是网格之间重叠 50 像素重叠部分检出的缺陷按坐标去重。6. 验证检测结果三个手段让输出不再像黑匣子读完前面五章你已经能跑通 main.py、调参、看 data.csv。但光能跑不代表结果可信我每次拆这类检测项目都会花三分之一时间做验证。第一个手段是保存中间结果。把灰度图、二值图、形态学处理后的图、轮廓标记图依次写盘cv2.imwrite(step1_gray.jpg, gray) cv2.imwrite(step2_thres.jpg, thres) cv2.imwrite(step3_result.jpg, result)二值图里白色区域就是程序判定为缺陷的像素拿它和 Img_source.jpg 叠加对比一眼能看出漏检和误检比盯着控制台日志直观得多。第二个手段是画灰度直方图选阈值。cv2.calcHist统计灰度分布如果直方图是明显的双峰阈值选谷底最稳如果单峰说明前景背景混在一起得改预处理而不是硬调阈值import matplotlib.pyplot as plt hist cv2.calcHist([gray], [0], None, [256], [0, 256]) plt.plot(hist) plt.savefig(hist.jpg)第三个手段是人工记账。找十张已知缺陷位置和数量的样图跑完后比对 data.csv 里检出的轮廓个数和真实缺陷数记录漏检、误检各几个。准确率低于 80% 就不要急着调参先回头查二值化质量看 step2_thres.jpg 里缺陷前景是不是断裂或者粘连。这套验证流程不是选修而是必修。我当年第一次做表面缺陷检测直接把阈值改成 OTSU 就交给老师结果换一张图大面积误检后来学乖了每次改完参数都强制走一遍保存中间结果加人工比对的流程。从那以后再也没在答辩现场翻过车。希望帮到你。本文还有配套的精品资源点击获取