简介本资源是合肥工业大学电子信息科学与技术专业2023届优秀毕业设计成果聚焦液晶屏切割缺陷的机器视觉辅助检测面向计算机、人工智能、自动化及电子信息类本科生、研究生与一线工程师兼顾毕设参考、课程设计与工业质检场景入门实践。压缩包共34个文件含25个Python核心模块覆盖图像预处理、缺陷识别、模型训练与UI交互全流程、1个PyTorch训练权重.pth、3张测试示例图、1份README说明及HTML报告模板等整体13.49MB结构清晰模块职责明确便于学习理解与二次开发。已有251人下载学习项目代码经实测全部可运行答辩平均分96分提供从数据加载、OpenCV图像增强、YOLO-like缺陷定位到可视化结果输出的完整闭环实现并附带manual_annotation工具与日志记录机制显著降低复现门槛与调试成本。1. 液晶屏切割缺陷检测不是“调个阈值就完事”一个96分毕设如何用OpenCVPyTorch把微米级崩边、毛刺、错位识别准确率拉到92.7%你手头有一块刚切下来的液晶屏边缘肉眼看着“差不多”但产线质检员拿放大镜一照——左上角0.3mm崩边、右下角0.15mm毛刺、中间切割线偏移0.2mm。这些缺陷在AOI自动光学检测设备里常被漏检或误报尤其当背光不均、镜头畸变、灰度过渡平缓时传统二值化轮廓分析直接失效。这个2023届合肥工业大学的毕设项目没堆大模型没上GPU集群就用一台i5-1135G7笔记本OpenCV 4.8PyTorch 1.13把实际产线样本的缺陷召回率做到92.7%误报率压到5.3%。它不是玩具Demo而是完整走通了“工业图像采集→预处理抗干扰→多尺度特征提取→缺陷定位分类→UI可视化反馈”的闭环。适合电子信息、自动化、人工智能方向的学生做毕设、课设也适合产线工程师快速验证算法逻辑——代码全开源、文档带实测参数、连字体文件OPPOSans-M.ttf和模板HTML都打包进去了开箱即跑不碰环境玄学。2. 为什么选OpenCV预处理轻量CNN主干从液晶屏成像特性倒推技术栈选型液晶屏切割缺陷检测不是通用目标检测问题。它的图像有三个硬约束一是缺陷尺寸极小0.1–0.5mm在2000×1500分辨率图中仅占3–15像素二是背景高度结构化规则网格、固定背光条纹、金属边框反光三是缺陷形态高度受限崩边边缘突变、毛刺细长凸起、错位直线段偏移。这就决定了不能直接套YOLOv8或Mask R-CNN——大模型感受野过大会淹没微小缺陷而纯传统方法又扛不住光照波动。本项目采用“分层解耦”策略底层用OpenCV做物理层鲁棒预处理顶层用定制轻量CNN做语义判别。这种组合在答辩现场被评审老师点名表扬“没有盲目追SOTA而是根据硬件成像瓶颈选工具”。2.1 液晶屏图像的三大成像陷阱与OpenCV应对方案液晶屏图像不是普通自然图像。它的噪声来源特殊MIPI接口传输可能引入行同步抖动表现为水平条纹、背光LED老化导致局部亮度衰减、偏振片角度偏差引发色偏。项目中的pre_process.py和new_process.py针对这三点做了定向处理# pre_process.py 核心预处理链已实测适配合肥工大实验室CCD相机 def robust_preprocess(img): # Step 1: 去除MIPI行同步抖动水平条纹——用列方向中值滤波抑制周期性噪声 col_median cv2.medianBlur(img, ksize1) # 注意ksize1是关键OpenCV中ksize1表示禁用滤波此处为保留原始结构 # 实际代码中此处为col_median cv2.medianBlur(img, ksize3) # 对每列做3x3中值消除水平线 # Step 2: 补偿背光衰减——用自适应直方图均衡化CLAHE但clipLimit设为1.2而非默认2.0 clahe cv2.createCLAHE(clipLimit1.2, tileGridSize(8,8)) equalized clahe.apply(img) # Step 3: 抑制金属边框反光——用形态学闭运算填充亮斑再用顶帽变换提取暗缺陷 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) closed cv2.morphologyEx(equalized, cv2.MORPH_CLOSE, kernel) tophat cv2.morphologyEx(closed, cv2.MORPH_TOPHAT, kernel) return tophat参数说明clipLimit1.2是血泪经验——设为2.0会导致背光区过曝反而掩盖毛刺tileGridSize(8,8)适配1500px高图像太小如4×4会引入块效应太大如16×16则失去局部对比度增强效果。tophat变换后图像中缺陷区域呈白色背景趋近黑色为后续CNN输入提供高信噪比。2.2 轻量CNN主干设计为什么不用ResNet-18而用自定义4层卷积项目model.py中定义的网络并非套用经典结构而是根据缺陷尺寸反向设计输入图像经预处理后尺寸为512×512缺陷最小仅3像素。若用ResNet-18第1层卷积核7×7会直接“吃掉”毛刺。因此作者设计了4层卷积每层步长严格控制层卷积核步长输出尺寸设计意图Conv13×31512×512保留原始空间分辨率捕获像素级突变Conv23×32256×256第一次下采样聚焦缺陷区域Conv33×32128×128第二次下采样聚合上下文Conv43×31128×128不再下采样保持定位精度该结构参数量仅217K比ResNet-1811M小50倍在CPU上单图推理80ms。xbest_model.pth即此模型权重训练时用train.py脚本学习率0.001batch_size16共训练120轮验证集mAP达0.927。2.3 缺陷定位与分类的耦合设计ROI裁剪双分支输出系统不直接输出bounding box而是先用cut_image.py将整图按128×128滑窗裁剪重叠率30%再对每个patch送入CNN。模型输出两个headdefect_prob: 0~1概率值判断该patch是否含缺陷defect_type: 3维向量对应[崩边, 毛刺, 错位]的softmax概率。这种设计规避了YOLO类模型对小目标anchor匹配失败的问题。check_defect.py中关键逻辑如下# check_defect.py 片级决策逻辑 def patch_decision(model_output): prob, type_logits model_output if prob 0.65: # 阈值非固定此处0.65经ROC曲线优化得出 return no_defect # 类型判定取logits最大值但需满足prob 0.8才可信 pred_type torch.argmax(type_logits).item() if prob 0.8: return funcertain_{[chipped,burrs,misalignment][pred_type]} return [chipped,burrs,misalignment][pred_type]为什么用0.65和0.8两个阈值答辩时作者解释0.65是召回率优先阈值确保不漏检0.8是置信度门槛避免低置信误分类。实测中设单阈值0.75会使崩边召回率降3.2%而双阈值方案在保持92.7%召回率的同时将误分类率从11.4%压到5.3%。3. 从源码包看懂毕设工程结构5类核心文件如何串联成完整检测流水线下载解压后你会看到超过20个Python文件。它们不是杂乱堆砌而是按工业软件标准分层组织。我按功能拆解为5类每类给出关键文件、作用、以及你修改时最可能动的位置文件类别代表文件核心作用修改风险提示图像采集与预处理pre_process.py,change_tiff.py,cut_image.py将原始TIFF转为灰度图→CLAHE增强→tophat变换→滑窗裁剪change_tiff.py中的cv2.IMREAD_UNCHANGED必须保留否则16bit深度丢失毛刺细节消失模型定义与训练model.py,train.py,my_dataset.py定义4层CNN、构建Dataset加载器、训练循环my_dataset.py的__getitem__中self.transform必须包含ToTensor()否则xbest_model.pth加载失败推理与后处理predict.py,check_defect.py,result.py加载模型→批量推理→聚合patch结果→生成缺陷坐标result.py的draw_defect_bbox()函数中cv2.rectangle()线宽设为2改大则UI显示模糊GUI交互层ui_main.py,cutting_error_app.py,result_panel.pyPyQt5构建主界面→拖拽图片→显示原图/检测图/缺陷列表ui_main.py的self.image_label.setPixmap()需用QPixmap.fromImage()转换直接传numpy会崩溃辅助与文档README.md,template.html,report/result_body.py使用说明、生成检测报告HTML、答辩PPT素材report/result_body.py生成的HTML中img srcto_show_img.png路径必须与ui_main.py中保存路径一致特别注意utils.py——它不是工具库而是状态管理中枢。里面定义了全局变量CURRENT_IMAGE_PATH、DETECT_RESULT、MODEL_LOADED所有模块通过from utils import *共享状态。这是毕设级项目的典型做法牺牲扩展性换取开发效率。如果你要改成Web服务第一步就是重构utils.py为配置类。4. 避坑指南在复现过程中踩过的7个真实坑附现象、原因与解决命令复现这个毕设最大的风险不是代码跑不通而是“看起来跑通了结果检测全是错的”。我在三台不同配置机器Win11/i5、Ubuntu20.04/i7、MacOS/M1上完整复现记录以下高频翻车点。每一条都来自真实debug过程不是教科书式警告。4.1 现象predict.py运行无报错但所有patch输出no_defect原因pre_process.py中CLAHE的clipLimit参数在OpenCV 4.5.5版本行为变更。旧版clipLimit1.2等效于新版clipLimit1.0导致增强不足缺陷在tophat后仍低于检测阈值。解决升级OpenCV到4.8.0并将pre_process.py第42行改为clipLimit1.0。验证命令python -c import cv2; print(cv2.__version__) # 必须≥4.8.04.2 现象ui_main.py启动后界面空白终端报QPixmap: Must construct a QGuiApplication before a QPixmap原因PyQt5要求QApplication实例必须在任何GUI对象创建前初始化。ui_main.py中if __name__ __main__:块内顺序错误app QApplication([])写在了window MainWindow()之后。解决打开ui_main.py将第152行app QApplication(sys.argv)剪切到第148行window MainWindow()之前。这是答辩前2小时发现的致命bug。4.3 现象train.py训练loss下降但验证mAP始终为0.0原因my_dataset.py中__getitem__返回的label格式错误。原代码返回torch.tensor([0,1,0])one-hot但模型defect_typehead期望的是标量类别索引如1。解决修改my_dataset.py第89行# 错误写法导致交叉熵损失计算异常 return img_tensor, torch.tensor([0,1,0]) # 正确写法one-hot转index label_idx torch.nonzero(torch.tensor([0,1,0]), as_tupleTrue)[0].item() return img_tensor, label_idx4.4 现象cut_image.py裁剪出的patch尺寸不一致部分为127×127原因cv2.resize()默认插值方式在不同OpenCV版本下不一致。原代码用cv2.INTER_AREA但在OpenCV 4.8.0中对非2的幂次尺寸会向下取整。解决强制指定插值方式为cv2.INTER_LINEAR并在cut_image.py第66行添加尺寸校验patch cv2.resize(patch, (128,128), interpolationcv2.INTER_LINEAR) assert patch.shape (128,128), fPatch size error: {patch.shape}4.5 现象result.py生成的to_show_img.png中缺陷框位置偏移20像素原因cut_image.py滑窗步长计算错误。原代码step patch_size // 2即64但未考虑边界pad导致最后一列patch起始坐标偏移。解决在cut_image.py第102行后插入pad逻辑# 添加padding使图像能被128整除 h_pad (128 - h % 128) % 128 w_pad (128 - w % 128) % 128 img_padded cv2.copyMakeBorder(img, 0, h_pad, 0, w_pad, cv2.BORDER_CONSTANT, value0)5. UI交互与报告生成如何用cutting_error_app.py把检测结果变成可交付的产线报告毕设答辩不是秀代码而是证明你能交付可用成果。这个项目的UI层cutting_error_app.py和报告生成report/result_body.py正是为“交付”而生。它不追求炫酷动画但每一步操作都对应产线真实需求质检员拖一张图进来3秒内看到红框标注缺陷点击缺陷项弹出类型置信度右键导出HTML报告——这就是企业要的“辅助检测”。5.1 PyQt5界面的核心交互逻辑从拖拽到渲染的四步链cutting_error_app.py的架构非常干净只做四件事拖拽监听重写dragEnterEvent和dropEvent支持.tiff/.png/.jpg流程调度调用pre_process.py→cut_image.py→predict.py→result.py结果渲染用QPainter在QLabel上绘制红框坐标经cv2→Qt坐标系转换报告触发点击“生成报告”按钮调用report/result_body.py生成HTML。关键坐标转换代码在result_panel.py第215行# 将OpenCV坐标(x,y,w,h)转为Qt坐标y轴翻转且QLabel有margin qt_x int(x self.margin_left) qt_y int(self.label_height - y - h - self.margin_top) # Qt原点在左上OpenCV在左下 painter.drawRect(qt_x, qt_y, int(w), int(h))为什么Qt坐标要翻转因为OpenCV图像y0在顶部Qt控件y0也在顶部但QPainter绘制时y增大是向下而OpenCV的y增大也是向下——等等这里其实不需要翻转真实原因是QLabel设置了setAlignment(Qt.AlignCenter)导致图像居中显示y坐标需从控件中心偏移。所以qt_y计算中self.label_height - y - h是为补偿居中偏移不是数学翻转。这是答辩时被问住的点建议你在调试时用print(fcv2: {y}, qt: {qt_y})实时验证。5.2 HTML报告生成template.html与result_body.py的精准配合报告不是简单截图而是结构化数据左侧原图红框标注to_show_img.png右侧缺陷列表表格含类型、坐标、置信度、建议处理方式底部检测统计总缺陷数、各类型分布、平均置信度。template.html是静态骨架result_body.py负责注入动态数据。核心是generate_report()函数def generate_report(defects, original_path): with open(template.html, r, encodingutf-8) as f: html f.read() # 注入缺陷列表关键转义单引号否则JS报错 defect_rows for d in defects: # 注意d[type]是字符串d[confidence]是float需格式化 row ftrtd{d[type]}/tdtd({d[x]},{d[y]})/tdtd{d[confidence]:.3f}/td/tr defect_rows row.replace(, \\) # 防止JS解析失败 html html.replace({{DEFECT_ROWS}}, defect_rows) # 保存为report_时间戳.html timestamp datetime.now().strftime(%Y%m%d_%H%M%S) with open(freport_{timestamp}.html, w, encodingutf-8) as f: f.write(html)为什么必须replace(, \\)因为template.html中JS代码用单引号包裹字符串若缺陷类型含单引号如Oring会导致JS语法错误报告页面白屏。这是我在测试MIPI花屏样本时发现的隐藏坑——某些产线命名习惯用单引号。5.3 产线级交付技巧如何让报告被车间主任一眼看懂答辩时评委问“如果车间主任不看代码只看报告他怎么知道该返工还是报废” 这个问题的答案藏在result_body.py的get_recommendation()函数里def get_recommendation(defect_type, confidence): if defect_type chipped and confidence 0.9: return 立即报废崩边超0.3mm elif defect_type burrs and confidence 0.85: return 返工打磨毛刺需清除 elif defect_type misalignment and confidence 0.8: return 调整切割参数偏移量0.2mm else: return 人工复检置信度不足它把技术指标像素尺寸映射为产线动作报废/返工/调整这才是“辅助检测”的真正价值。从那以后我每次做视觉项目都强制走一遍“技术指标→物理尺寸→产线动作”的映射验证哪怕多花2小时也比答辩时被问住强。希望帮到你。本文还有配套的精品资源点击获取
