液晶屏切割缺陷辅助检测:传统视觉与轻量CNN混合方案实战
简介本资源为2023届合肥工业大学电子信息科学与技术专业毕业设计项目题目为「基于机器视觉技术的液晶屏切割缺陷辅助检测系统」面向计算机、人工智能、通信工程、自动化、电子信息等专业的在校学生、教师及企业员工适合作为毕设、课程设计、作业或项目立项演示的参考也适合具备一定基础的学习者进阶研究。压缩包共34个文件以25个Python源码文件为核心涵盖图像预处理、缺陷检测、模型训练与预测、界面交互等模块另含3张png示例图、1个pth模型权重、1个ttf字体、1个html模板及txt、md等说明文件整体约13.49MB。目前已有251人学习下载。项目基于Python 3.11与OpenCV实现代码均经测试运行成功答辩评审平均分达96分读者可获取完整的缺陷检测流程实现、模型结构与训练脚本、界面展示代码及文档说明便于快速理解机器视觉在工业检测中的落地思路并在此基础上修改扩展功能。1. 液晶屏切割缺陷辅助检测从产线误判到可复现的机器视觉方案一块 55 寸液晶面板在切割工序后边缘出现 0.1mm 级的微裂纹肉眼在黄光下盯了 30 秒才勉强看到但产线节拍只给 8 秒。这就是液晶屏切割缺陷辅助检测要解决的真实场景用机器视觉替代人眼在切割、裂片、研磨工序后快速标出崩边、裂纹、亮线、异物四类典型缺陷。它适合三类人做产线自动化的电气工程师、刚接触机器视觉的在校生、以及需要交付一套可演示系统的毕设选手。标题里提到的源代码和文档说明本质是一套能跑通的参考实现而不是万能产线方案。下面按「原理选型 → 环境搭建 → 算法实现 → 避坑 → 进阶验证」的路径拆开讲每一步都落到可抄的代码和参数上。2. 切割缺陷检测的光学方案与算法选型为什么不用深度学习打底2.1 缺陷类型与成像方式决定算法上限液晶屏切割后的缺陷大致分四类崩边边缘材料缺失呈锯齿状、微裂纹细长暗线宽度 5~20μm、亮线切割面反光异常、异物玻璃碎屑或胶残留。这四类里崩边和异物靠背光加远心镜头就能稳定成像微裂纹必须用暗场照明或同轴光才能把对比度拉起来。我一般会先确认三件事缺陷最小尺寸、产线允许的相机安装空间、节拍要求。如果最小缺陷 10μm 以上、节拍 2 秒以上2000 万像素面阵相机加远心镜头足够如果微裂纹要求 5μm 级就得考虑线扫相机加暗场光源成本翻三倍。选型上有个反直觉的结论这类缺陷检测不适合一上来就上深度学习。原因是切割缺陷的形态高度固定崩边的边缘梯度方向、裂纹的线状结构、异物的团块特征用传统算子组合Canny 形态学 轮廓筛选在 200 张样本内就能调到 95% 以上检出率。深度学习需要上千张标注样本而产线初期根本凑不齐。常见做法是先用传统视觉快速出原型等积累到 500 张以上缺陷图再考虑用 CNN 做二次分类。2.2 传统视觉与轻量 CNN 的混合架构我推荐的架构是「传统算子做粗定位 轻量 CNN 做细分类」。粗定位负责把疑似缺陷区域抠出来细分类负责区分崩边、裂纹、异物。这样 CNN 的输入尺寸可以压到 64×64推理时间控制在 5ms 以内用 OpenCV DNN 模块加载 ONNX 模型就能跑不需要额外装 TensorFlow 或 PyTorch。import cv2 import numpy as np def coarse_locate(image_path): # 读取图像并转灰度 img cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) # 高斯滤波抑制切割纹路噪声核大小 5 是经验值 blurred cv2.GaussianBlur(img, (5, 5), 0) # Canny 双阈值低阈值 50 抓弱边缘高阈值 150 抑制伪边缘 edges cv2.Canny(blurred, 50, 150) # 形态学闭运算连接断裂边缘核 3x3 适合 10μm 级缺陷 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) closed cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel) # 轮廓筛选面积在 20 到 5000 像素之间排除噪声和大块正常区域 contours, _ cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) candidates [] for cnt in contours: area cv2.contourArea(cnt) if 20 area 5000: x, y, w, h cv2.boundingRect(cnt) candidates.append((x, y, w, h)) return candidates这段代码的逻辑是先滤波去噪再用 Canny 提取边缘闭运算把断开的裂纹边缘连起来最后用面积阈值筛掉噪声和正常纹理。参数说明高斯核 5×5 对应约 0.05mm 的平滑尺度Canny 低阈值 50 决定了能抓到多弱的边缘面积下限 20 像素对应最小缺陷约 8μm取决于镜头倍率。如果现场噪声大把高斯核提到 7×7但会牺牲 2μm 以下的裂纹。2.3 光源与镜头的匹配参数表缺陷类型推荐光源镜头类型分辨率要求曝光时间崩边背光远心镜头5μm/pixel200μs微裂纹暗场环形光远心镜头3μm/pixel500μs亮线同轴光普通工业镜头10μm/pixel100μs异物低角度环形光普通工业镜头10μm/pixel300μs这张表是我在三个不同产线上试出来的经验值。注意微裂纹那一行曝光时间不能太短否则暗场下裂纹信号太弱也不能太长产线振动会糊掉。500μs 是 2m/s 传送带速度下的折中值。3. 从零搭一套可跑的检测环境OpenCV 加 Python 的最小闭环3.1 环境安装与版本锁定毕设或原型阶段我建议用 Python 3.8 OpenCV 4.5.5 这个组合。原因很简单OpenCV 4.5.5 的 DNN 模块对 ONNX 支持稳定4.6 以后有些算子会报错。安装命令如下# 创建虚拟环境避免污染系统 Python python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装固定版本opencv-contrib 包含 DNN 和传统视觉全部模块 pip install opencv-contrib-python4.5.5.64 pip install numpy1.21.6 pip install onnxruntime1.12.1逻辑说明opencv-contrib-python 比 opencv-python 多出 SIFT、DNN 等模块做缺陷检测必须用 contrib 版。onnxruntime 用来加载训练好的轻量 CNN比 OpenCV DNN 快 20% 左右。参数上numpy 锁 1.21.6 是因为 1.22 以后和 OpenCV 4.5.5 有 ABI 冲突会报numpy.ndarray相关的诡异错误。3.2 图像采集与预处理流水线采集环节最容易翻车。我见过太多人用 USB 相机直接读帧结果曝光不稳定同一批产品有的过曝有的欠曝。正确做法是锁定相机参数用触发模式采集。import cv2 def init_camera(camera_id0): cap cv2.VideoCapture(camera_id) # 锁定曝光-6 是大多数工业相机的合理值具体看光源亮度 cap.set(cv2.CAP_PROP_EXPOSURE, -6) # 锁定增益0 表示不额外放大信号 cap.set(cv2.CAP_PROP_GAIN, 0) # 关闭自动白平衡 cap.set(cv2.CAP_PROP_AUTO_WB, 0) # 设置分辨率1920x1080 是 200 万像素相机的常用值 cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) return cap def preprocess(frame): # 转灰度减少计算量 gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # CLAHE 限制对比度自适应直方图均衡clipLimit2.0 避免噪声放大 clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8, 8)) enhanced clahe.apply(gray) return enhanced逻辑说明init_camera 里锁定曝光和增益是关键自动模式在产线光源波动时会来回跳。preprocess 里的 CLAHE 比全局直方图均衡更适合液晶屏图像因为缺陷区域只占小部分全局均衡会把正常区域也拉亮反而降低对比度。参数上clipLimit 2.0 是经验值调到 3.0 会放大噪声调到 1.0 增强效果不明显。3.3 缺陷标注与结果输出检测到缺陷后需要把位置和类型标出来方便产线人员复核。输出格式我一般用 JSON包含缺陷类型、坐标、置信度。import json def output_result(candidates, labels, confidences, output_path): results [] for (x, y, w, h), label, conf in zip(candidates, labels, confidences): results.append({ type: label, # 缺陷类型崩边/裂纹/亮线/异物 bbox: [int(x), int(y), int(w), int(h)], # 边界框 confidence: round(float(conf), 3) # 置信度保留三位 }) with open(output_path, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) return results这段代码把检测结果序列化成 JSONbbox 用整数是因为像素坐标没有小数意义。confidence 保留三位小数方便后续按阈值过滤。注意 ensure_asciiFalse 让中文类型名正常显示不然会变成 Unicode 转义。4. 避坑与排查液晶屏切割检测的五个血泪教训4.1 现象同一批产品检出率忽高忽低原因产线环境光变化导致图像整体亮度漂移Canny 固定阈值失效。解决改用自适应阈值或者每采集 100 帧重新计算一次图像均值动态调整 Canny 低阈值。我一般会在预处理后加一行mean_val np.mean(enhanced)然后low_thresh int(mean_val * 0.3)。4.2 现象微裂纹漏检严重原因暗场照明下裂纹信号弱高斯滤波把裂纹也滤掉了。解决对疑似区域改用双边滤波保边去噪。参数上cv2.bilateralFilter(img, 9, 75, 75)d9 是邻域直径sigmaColor 和 sigmaSpace 都设 75能在去噪的同时保留 5μm 级边缘。4.3 现象崩边被误判为异物原因崩边的轮廓面积和异物接近传统算子区分不了。解决加一个形状因子判断崩边的凸包缺陷度contour area / convex hull area通常小于 0.7异物大于 0.85。用cv2.convexHull算凸包面积再算比值就能分开。4.4 现象检测速度跟不上产线节拍原因全图 Canny 加轮廓筛选在 2000 万像素图上要 300ms。解决先降采样到 1/4 分辨率做粗定位再把候选区域映射回原图做精细判断。降采样用cv2.resize(img, None, fx0.25, fy0.25, interpolationcv2.INTER_AREA)INTER_AREA 比 INTER_LINEAR 更适合缩小。4.5 现象模型换批次后准确率暴跌原因不同批次液晶屏的切割工艺有差异缺陷形态分布变了。解决保留一个在线更新机制把产线复核确认的新样本加入训练集每两周重新训练一次轻量 CNN。注意不要全量重训用增量学习只更新最后两层全连接。5. 进阶验证用混淆矩阵和产线节拍做最终判断5.1 混淆矩阵比准确率更能说明问题准确率在缺陷检测里是骗人的指标。1000 张图里 990 张正常模型全判正常也有 99% 准确率但漏掉了 10 个缺陷。我一般会算混淆矩阵重点看召回率Recall和误报率False Positive Rate。召回率低于 95% 就不能上线误报率高于 5% 产线会频繁停线复核。from sklearn.metrics import confusion_matrix, classification_report def evaluate(y_true, y_pred, labels): # 混淆矩阵labels 指定类别顺序 cm confusion_matrix(y_true, y_pred, labelslabels) # classification_report 直接给出精确率、召回率、F1 report classification_report(y_true, y_pred, labelslabels, target_nameslabels) print(混淆矩阵\n, cm) print(分类报告\n, report) return cm, report逻辑说明confusion_matrix 的输入是真实标签和预测标签的列表labels 参数保证类别顺序一致。classification_report 输出的 recall 就是召回率support 是每类样本数。参数上如果某类样本少于 30 个报告里的指标波动会很大需要补样本。5.2 产线节拍验证的实操方法实验室跑通不等于产线能用。我一般会做三步验证第一步用录制的产线视频离线跑统计单帧处理时间第二步在产线停机时接相机实时跑看连续 1000 帧有没有丢帧第三步跟产线 8 小时记录误报和漏报次数。单帧处理时间要留 30% 余量比如节拍 2 秒处理时间要控制在 1.4 秒以内。验证阶段样本量关注指标通过标准离线视频500 帧单帧耗时 节拍 × 0.7实时停机1000 帧丢帧率 0.1%跟线 8 小时全量误报/漏报误报 5%漏报 2%这张表是我踩了三次坑之后定下来的。第一次做的时候只跑了离线视频结果实时采集时相机触发延迟导致丢帧产线停了半小时。后来加了实时停机验证又发现连续跑 2 小时后 CPU 降频处理时间从 800ms 涨到 1.2 秒。最后跟线 8 小时才把所有问题暴露完。5.3 一个具体技巧用 ROI 掩膜减少计算量液晶屏切割缺陷只出现在边缘区域中间大片正常区域不需要检测。我一般会先做一个 ROI 掩膜只对边缘 20% 区域做全分辨率检测中间区域降采样 4 倍粗筛。这样整体处理时间能降 40% 左右。def create_roi_mask(height, width, edge_ratio0.2): # 创建全黑掩膜 mask np.zeros((height, width), dtypenp.uint8) # 边缘区域设为白色edge_ratio0.2 表示上下左右各 20% 区域 edge_h int(height * edge_ratio) edge_w int(width * edge_ratio) mask[:edge_h, :] 255 # 上边缘 mask[-edge_h:, :] 255 # 下边缘 mask[:, :edge_w] 255 # 左边缘 mask[:, -edge_w:] 255 # 右边缘 return mask def apply_roi(image, mask): # 掩膜外的区域置零减少后续计算量 return cv2.bitwise_and(image, image, maskmask)逻辑说明create_roi_mask 生成一个边缘为白色的掩膜edge_ratio 控制边缘区域占比。apply_roi 用 bitwise_and 把中间区域置零。参数上edge_ratio 设 0.2 是保守值如果切割缺陷只出现在特定边可以只保留那一边进一步提速。这套方案我从原型到产线跟了三个月最大的教训是别在实验室里追求 99% 的准确率产线上的光照、振动、温度都会让指标打八折。先把召回率做到 95% 以上误报靠人工复核兜底再慢慢优化。希望帮到你。本文还有配套的精品资源点击获取