
简介一份面向机器视觉从业者与工业质检工程师的实战型知识梳理聚焦工业缺陷检测中的硬件选型、图像处理算法与算法库应用。资源为单份PDF文件大小约1.26MB内容系统梳理视觉检测系统的组成从光源选型入手对比LED、萤光灯、卤素灯等常见光源的特性并说明背向照明、前向照明、结构光等照明方式在尺寸测量、表面划痕检测中的适用场景随后介绍相机、镜头与图像采集卡的参数选择要点包括分辨率、帧率、光谱响应等关键指标其中图像采集卡负责将光学信号转换为数字信号。图像处理部分则涵盖去噪、增强等预处理以及边缘检测、模板匹配等检测方法并给出划痕、Logo识别等实际案例的光源搭配思路。已有1188人学习适合刚入门或希望系统化构建视觉检测知识体系的读者。通过这份文档可快速掌握从光源、相机到图像算法的关键要点减少选型与调试中的试错成本。1. 机器视觉工业缺陷检测到底在检测什么生产线上的金属冲压件表面有一道 0.2 毫米宽的划痕人工目检每分钟看几十个十分钟后注意力就掉下来了。机器视觉工业缺陷检测要解决的就是这类“人眼不稳定”的问题用相机代替眼睛用图像处理算法代替判断在节拍时间内把缺陷找出来。这个标题把范围限定在“工业”场景意味着它不是实验室里的图像分类比赛要面对反光、油污、震动、环境光变化和严格的漏检率要求。适合刚切入工业视觉的软件工程师和自动化集成工程师阅读也适合准备机器视觉面试的人用来梳理知识骨架。下面从成像原理讲到模型落地把一条能复现的路径拆开讲。2. 从成像到判决机器视觉工业缺陷检测的核心链路与像素精度2.1 缺陷检测的共性流程采图、预处理、分割、分类工业缺陷检测无论用传统图像处理还是深度学习都逃不开这几个环节采图、预处理、分割、特征提取与分类。采图决定信息上限预处理负责去噪和增强分割把缺陷区域从背景里分离出来分类最后判断缺陷类型和等级。很多新手一上来就调模型忽略了前面两步结果换一个打光角度模型就崩根源就在于成像环节没有把缺陷和背景的差异固定下来。以表面划痕为例灰度图上划痕通常是比背景暗的细线。预处理可以先做高斯滤波去掉随机噪声然后用顶帽变换提取暗细节。OpenCV 里的实现非常直接import cv2 import numpy as np img cv2.imread(surface.png, cv2.IMREAD_GRAYSCALE) blur cv2.GaussianBlur(img, (5, 5), 0) kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15)) tophat cv2.morphologyEx(blur, cv2.MORPH_TOPHAT, kernel) _, mask cv2.threshold(tophat, 0, 255, cv2.THRESH_OTSU) cv2.imwrite(mask.png, mask)这段代码先做高斯模糊抑制随机噪声再用椭圆结构元素做形态学顶帽变换。顶帽变换的原理是用开运算估计背景再用原图减去背景这样比背景暗或亮的细小结构都会被保留下来。最后用 Otsu 自动阈值把缺陷像素从灰度差异里分出来。结构元素尺寸要大于缺陷宽度而小于缺陷间距否则会把整片区域当成背景。参数上GaussianBlur 的 (5, 5) 是核尺寸针对亚像素级噪点kernel 的 15x15 要和缺陷尺度匹配。缺陷更细就缩小图像上有周期性纹理时还要先考虑用频域滤波抑制纹理而不是盲目加大模糊核。传统分割的问题在于干扰项太多光照不均、材质纹理都会造成误检所以现在工业现场更常见的是“传统分割出候选区域 分类网络判真假”的混合流程。下面这张表是我在不同缺陷类型上常用的预处理路线能够在方案评审时快速对齐思路缺陷类型成像特征首选预处理常见难点划痕低对比度细线顶帽/底帽变换纹理干扰脏污灰度块状差异中值滤波差分光照不均缺料边界缺失边缘检测倒角误判毛刺局部凸起形态学梯度毛刺尺寸小2.2 像素精度怎么算物方分辨率与视场的关系“机器视觉动了什么会导致像素精度变化”是现场和面试里最高频的提问之一。像素精度指的是图像上一个像素对应到物体表面的实际尺寸单位是 mm/pixel。计算公式是像素精度 视场宽度 / 传感器像素数。比如视场要拍 100 毫米宽相机是 500 万像素长边有 2456 像素那一个像素大约对应 100 / 2456 ≈ 0.0407 毫米。注意这里要用长边对应长边如果传感器是 5:4 还按总像素除就错了。有一个容易踩的坑像素精度不等于检测精度。要稳定检测一个缺陷至少需要 3 到 5 个像素覆盖缺陷的最小尺寸。也就是说如果要测 0.05 毫米的划痕像素精度至少要到 0.01 毫米/像素否则缺陷成像后只有一两个像素不管是阈值分割还是卷积神经网络都很难稳定识别。相机高度动了视场变化像素精度马上变镜头焦距变了视场也变相机没有固定好图像抖动造成的模糊还会等效降低精度。这里还要区分一个概念亚像素定位不是像素精度提升。边缘检测可以通过插值把重复精度做到 0.1 像素但这不意味着能稳定识别只有 1 个像素的缺陷。亚像素算法对噪声敏感在缺陷检测里更常见的是用多帧平均来提高稳定性而不是追求单帧亚像素。实际项目里我会先计算理论像素精度再把被测工件放到视场对角线最远的角落看边缘是否还在景深范围内。镜头的光圈收小可以增大景深但光圈太小会引入衍射模糊一般工业镜头推荐开 F5.6 到 F8 之间。2.3 曝光调整为什么会影响检测结果2.3.1 曝光三要素与缺陷对比度曝光由光圈、快门、增益共同决定。光圈控制进光量快门控制感光时间增益是对信号做放大。工业相机通常固定光圈后优先调快门因为光圈影响景深快门不影响清晰度但影响运动模糊。增益要尽量小因为增益放大的同时把噪声也放大了缺陷和背景的对比度反而可能下降。曝光不足时暗部细节被量化噪声淹没划痕和背景的灰度差变小曝光过度时高光区域饱和到 255亮背景上的暗缺陷可能仍然可见但暗背景上的凸起点会失去形貌信息。所以工业缺陷检测的打光目标不是拍得好看而是让缺陷和背景的灰度差最大。2.3.2 曝光调整的一个标定步骤我一般会在相机 SDK 提供的外部触发模式下做这样的曝光标定import numpy as np def autofind_exposure(capture, gain_fixed0): best_exposure 0 best_contrast -1 for exposure in np.linspace(100, 10000, 20): capture.set_float(ExposureTime, exposure) capture.set_float(Gain, gain_fixed) frame capture.read() # 固定工位下取两个已知区域的灰度均值 defect_roi frame[50:100, 50:100] background_roi frame[200:250, 200:250] contrast abs(defect_roi.mean() - background_roi.mean()) if contrast best_contrast: best_contrast contrast best_exposure exposure return best_exposure这段代码用对比度作为目标函数在所有曝光值里搜索最大灰度差。缺陷 ROI 需要由模板或固定工位预先确定否则场景变化会让对比度计算失去意义。实际现场要再考虑运动模糊如果被检物体在运动曝光时间需要小于“一个像素对应的时间”否则横向拖影会把缺陷拉长。上限公式是曝光时间 ≤ 像素精度 / 运动速度例如像素精度 0.01 mm/pixel、速度 100 mm/s 时曝光最多 0.1 毫秒这时候往往需要补强光源。3. 打光方案与硬件选型机器视觉工业缺陷检测的落地地基3.1 常见打光方式与适用缺陷类型打光是机器视觉缺陷检测里最影响结果的一步。同一个划痕用同轴光可能看不见用低角度光就非常明显。常见方案有环形光、条形光、同轴光、背光、低角度光、圆顶光。环形光安装方便适合大多数表面划痕和字符识别但对镜面反射会有亮点干扰同轴光适合高反光平面能消除阴影但对比度较低背光适合轮廓尺寸测量把缺陷投影成暗影低角度光让表面凹凸产生明显灰度差异。下面这个表格是现场选型时我会参考的映射打光方式适合缺陷典型角度注意点环形光字符、浅划痕30-45度反光表面注意亮点同轴光镜面、晶圆垂直对比度偏低背光轮廓、孔洞180度只能看边界低角度光压伤、凹陷10-20度易受环境光干扰圆顶光球形、曲面散射均匀但亮度损失大低角度光用条形光可以强调激光雕刻的纹理圆顶光适合电镀球面这类容易产生镜面反射的物体。一个经验灯光不要一开始就上全包围先做黑箱模拟用可调角度的光源从各个方向照一遍把缺陷最明显的角度记录下来再用对应光源复现。3.2 相机与镜头选型参数速查相机选型核心是传感器尺寸、分辨率、帧率、曝光方式。工业检测一般用全局快门的 CMOS避免卷帘快门在高动态场景下产生果冻效应。500 万像素在大多数 2D 表面缺陷场景里够用只有当缺陷非常小且视场很大时才考虑 1200 万以上。镜头选型需要看焦距、接口、畸变和工作距离。焦距根据视野和工作距离用相似三角形估算可以用下面这个函数直接算def calc_focal_length(working_distance, sensor_height, fov_height): return working_distance * sensor_height / fov_height focal_length calc_focal_length(200, 3.8, 50) print(round(focal_length, 1))这里 working_distance 是工作距离 200 毫米sensor_height 是传感器短边 3.8 毫米fov_height 是目标视野短边 50 毫米输出 15.2 毫米可以选 16 毫米定焦镜头。定焦比变焦便宜且畸变小首选。另一个参数是镜头接口与相机靶面的匹配C 接口镜头兼容 2/3 英寸以下靶面如果用 1 英寸相机还用 C 口镜头会形成暗角甚至不能合焦。选型时最好让相机和镜头供应商的工程师确认接口。3.3 一个最小硬件验证流程在没有完整产线条件时我会用一个万能支架、一台工业相机、一支镜头和一个可调光源搭最小验证环境。步骤是第一步把工件固定调整工作距离到理论值第二步打开光源用正对工件的相机拍摄一张灰度图第三步在软件里实时调整曝光使背景灰度为 180 左右第四步从 20 度、45 度、90 度几个角度分别打光观察缺陷对比度。这个流程能快速判断项目可行性。如果多个角度的光照都无法将缺陷与背景分开就得考虑是否把缺陷类型换成其他特征或者用结构光等 3D 方法。机器视觉 3D 入门通常从激光三角测量开始用线激光扫过表面从高度图里找凹陷和凸起。2D 处理不了的深度缺陷3D 往往能直接显示出来但 3D 的成本和标定复杂度也高一个数量级。4. 用卷积神经网络做机器视觉工业缺陷检测分类从数据到模型4.1 为什么工业场景常用小模型迁移学习工业缺陷检测的数据集通常很小缺陷样本可能只有几百张。从头训练一个深层卷积神经网络不仅容易过拟合还很难收敛。常见做法是用 ImageNet 预训练模型做迁移学习把分类层换成自己的缺陷类别只微调最后几层。因为预训练模型已经学到底层边缘、纹理、角点这些通用特征对工业缺陷的纹理也有一定迁移能力。但注意工业图像和自然图像差异大灰度图输入时需要把单通道复制成三通道或者修改网络第一层的输入通道数。另一个更贴近工业的做法是利用异常检测思路只用正常样本训练一个重建模型缺陷作为重建误差较大的区域被定位出来。比如 PatchCore 这类算法会在正常样本的 patch 特征上建立记忆库推理时比较待测 patch 与记忆库的距离。对于“缺陷类型未知”的场景这种方案比分类网络更实用因为不需要提前穷举缺陷形态。另外工业场景里的类别通常只有正常与缺陷两类但缺陷形态差异大二分类网络很难区分“不同缺陷类型”。一种做法是先做缺陷定位再用分类器区分子类把“是否有缺陷”和“是哪一种缺陷”拆成两个阶段。4.2 数据标注与注意点工业标注讲究“框出缺陷”“标类别”“标等级”三层。首先标注框要尽量贴近缺陷边缘不要拉一个大框把正常区域包进去否则模型会学到周围环境。其次类别数量要平衡如果某一类缺陷极少合成数据或者从其他产线迁移是常用手段。第三标注标准要统一同一个划痕不同标注员可能一个标成“划痕”另一个标成“擦伤”需要在标注前做一张示例图。数据增强里旋转、翻转、缩放只能用于增强位置无关的缺陷。像金属印刷字符上的划痕翻转会改变文字方向不能随便用。工业上更可靠的是模拟光照变化对图像做亮度抖动、局部高斯噪声、模糊模拟失焦。这类增强不改变缺陷本质还能让模型对现场的光照波动更鲁棒。4.3 训练一个分类网络的最小代码示例4.3.1 数据读取与增强我用 PyTorch 写一个最精简的目录读取流程目录结构是 train/正常/图片 和 train/划痕/图片。import torch from torch.utils.data import DataLoader import torchvision.transforms as T from torchvision.datasets import ImageFolder transform T.Compose([ T.Resize((256, 256)), T.RandomHorizontalFlip(p0.5), T.ColorJitter(brightness0.2, contrast0.2), T.ToTensor(), T.Normalize(mean[0.5], std[0.5]) ]) train_data ImageFolder(train, transformtransform) train_loader DataLoader(train_data, batch_size32, shuffleTrue, num_workers2) print(train_data.classes)ImageFolder 会根据子目录名自动分配类别标签这里我直接利用了这个约定。Resize 让所有图统一到 256 乘 256随机水平翻转是常见增强但如果缺陷有方向性比如方向固定的划痕要谨慎使用。ColorJitter 中的 brightness 和 contrast 模拟不同曝光下的灰度波动对工业图像很关键。4.3.2 训练循环与指标我一般会用 ResNet18 做特征提取去掉最后一层替换成二分类输出层。import torch.nn as nn import torchvision.models as models model models.resnet18(pretrainedTrue) model.conv1 nn.Conv2d(1, 64, kernel_size7, stride2, padding3, biasFalse) model.fc nn.Linear(model.fc.in_features, 2) criterion nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.parameters(), lr1e-4) for epoch in range(20): for images, labels in train_loader: outputs model(images) loss criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() print(epoch, loss.item())这里把第一层改成了单通道输入原因是工业现场很多相机输出灰度图把三通道改成 1 通道能减少参数和计算量。学习率 1e-4 是微调的保守值如果从头全量训练可以用 1e-3。评价指标最好同时看两类错误率不能只用准确率掩盖缺陷漏检。表格里记录一下训练集和验证集上最需要关注的指标指标表达式工业含义漏检率漏检缺陷数 / 实际缺陷数缺陷没找出来最危险过杀率误报数 / 正常品数把良品当缺陷浪费产能F12精确率召回率/(精确率召回率)平衡两者的综合指标实际产线验收一般要求漏检率低于千分之一所以模型置信度阈值要偏向召回率宁可多过杀一些也要把缺陷逮住。这就需要额外的现场验证了。5. 现场调试与面试题里的机器视觉常见坑5.1 缺陷检测系统的验证方法现场最容易出的问题不是模型不准而是节拍内跑不完或者频繁误触发。我一般先把模型离线跑速度再用 C 推理引擎转成 onnx 或 tensorrt在工控机上测单张图耗时。如果超时优先缩输入尺寸而不是换网络。工业相机的触发频率不一定是最高帧率外部触发模式下要确认每一次触发都能在下一帧前处理完否则会丢帧。验证缺陷检测系统一定要准备一份“缺陷样本 良品样本”的固定测试集散落在不同生产时段。不能只拿训练时见过的缺陷图来测因为缺陷形态千差万别一个亮度变化就可能导致漏检。正确的做法是在产线上连续跑几个小时把误报和漏报的图都保存下来按缺陷位置、光照时段分类统计。5.2 机器视觉面试题里的高频知识点面试题里经常出现的几个考点其实都能在缺陷检测里找到对应场景。“机器视觉的曝光调整原理”会问你增益为什么不能太大答案就是信噪比问题。“机器视觉动了什么会导致像素精度变化”考的是视场和分辨率关系现场改动相机高度或镜头焦距都会影响像素精度。“机器视觉学习路线”则要看候选人有没有从成像、算法、工程化三个维度组织知识。回答时不妨从缺陷检测案例引出先讲光源选型再讲图像处理然后讲深度学习最后讲部署这样比背八股文更可信。5.3 一条可执行的机器视觉学习路线如果想系统入门我建议按这个顺序第一周熟悉相机 SDK 和打光拍自己的工件第二周用 OpenCV 做阈值分割和形态学跑通一个划痕检测脚本第三周学卷积神经网络从 LeNet 看到 ResNet用自己的数据训练一个二分类第四周接触 3D 视觉用激光三角或结构光重建一个简单高度图。每一步都要落到“能不能在生产现场稳定运行”这个目标上。学习过程中把常见报错、调试记录写成笔记这些是面试时能讲出细节的资本。本文还有配套的精品资源点击获取