
机器视觉技术这四个字写在方案书里很轻落到产线上却是另一回事。光源差一格角度、镜头差两毫米工作距离、触发信号晚来半个毫秒最后都会变成“误检率下不来”这一个结果然后所有人围在设备旁边开会。我这里说的机器视觉技术指的是用工业相机把被测物拍成图像再用算法从图像里把尺寸、缺陷、位置、字符这些信息抠出来交给设备去做判断和动作的一整套方法。它解决的问题很实在人眼看不稳的、看得慢的、看久了会累的、看不进高温高危环境的活交给它。这篇文章适合三类人看——刚接手视觉工位、想搞清楚硬件怎么选的设备工程师手里有算法但一到现场就翻车的软件工程师以及要给产线做技改方案、需要判断供应商报价合不合理的项目负责人。下面这些内容是我把这些年踩过的坑按“方案—硬件—算法—排查”四段重新捋了一遍尽量把每个选择背后的账算给你看。1. 机器视觉项目的整体设计与思路拆解1.1 一套视觉系统到底由哪些环节拼起来我习惯把人眼当参照物来理解这套系统光源是台灯镜头是晶状体和瞳孔负责聚焦和进光量相机是视网膜把光变成电信号采集与传输链路是视神经算法是大脑皮层最后的 IO 输出和通信是手。缺一环都不行而且木桶效应极其明显——大脑再聪明视网膜糊了也白搭。按物理顺序拆一条完整的链路是被测物定位与输送 → 光源照明 → 镜头成像 → 相机感光 → 图像传输接口与线缆→ 触发与同步PLC、编码器、光电开关→ 图像处理预处理、定位、测量、判定→ 结果输出IO、串口、以太网、数据库→ 执行机构动作。这里面最容易被新手忽略的是“触发与同步”和“被测物定位”大家往往一上来就盯着算法结果相机在物体还没停稳的时候就拍了图像本身就是拖影的算法调一个月也没有意义。另外一个常被忽略的点是机械与光学的耦合。相机支架的刚性、镜头锁紧环有没有拧死、光源支架会不会被震动带偏这些看起来是结构件的事实际上是视觉系统稳定性的一部分。我见过一台设备算法端反复出现“同一样品今天判 OK 明天判 NG”查了三天最后发现是环形光源的支架螺丝松了半圈光源整体歪了两度高反光面上的亮斑位置变了阈值分割的边界自然就飘了。所以做方案的时候我一般会画一张链路图把每一环的“输入—输出—约束”写清楚光源需要什么安装空间、镜头需要多大工作距离、相机需要什么接口带宽、触发信号从哪取、算法允许的单帧耗时是多少。这张图不用多好看但它能让你在选型阶段就把后面 80% 的扯皮提前消化掉。1.2 为什么“先定方案再选硬件”——方案选型的三个判断锚点新手最容易犯的错是拿着一本相机选型手册从头翻到尾看到像素高的就选看到帧率快的就上最后拼出来的系统又贵又不准。正确的顺序是反过来的先把需求钉死再倒推硬件。我一般用三个锚点来判断锚点一你到底要“看什么”。这是最本质的问题。检测类型粗分五类有无/计数最简单一个 blob 分析搞定、尺寸测量对精度和标定要求高、位置与角度引导对重复定位精度要求高、表面缺陷最难受光照和纹理影响大、字符与条码识别对对比度和清晰度要求高。这五类对硬件的需求完全不同——测量类要优先保证分辨率和畸变控制缺陷类要优先保证照明方案和均匀性引导类要优先保证节拍和标定精度。锚点二精度和节拍能不能同时满足。这两个指标经常打架。想要更高精度就得上更高分辨率的相机像素一多单帧数据量变大传输和处理时间就上去了。所以方案阶段必须把“最小可辨识特征尺寸”和“单件允许耗时”这两个数写下来白纸黑字后面所有选型都围绕它们做减法。锚点三现场环境的硬约束。安装空间够不够放相机和镜头工作距离往往被机械结构卡死、现场有没有强振动、粉尘、水汽、油污、环境光变化大不大、被测物温度高不高热辐射会影响成像、有没有电磁干扰源变频器旁边走网线是经典翻车点。这些约束不是“优化项”是“否决项”——工作距离不够多好的镜头也装不上去。我在做方案评审时有个硬性要求任何视觉方案必须写清楚“最坏情况下的成像条件”。比如被测物表面最暗的那一批、环境光最强的那两个小时、镜头最脏的那个班次结束前系统还能不能稳定判对。写不出这一条方案就不算完成。1.3 传统算法与深度学习的边界在哪里这几年深度学习在视觉里铺得很快但我见过太多“明明一个阈值分割就能搞定的事非要训个模型”的例子最后交付周期翻倍、维护成本翻倍、现场换个批次的产品就崩了。我的判断标准很朴素规则能不能用语言描述清楚。如果缺陷的判定标准是“这条边是不是直的”“这个圆孔直径在 10.00±0.05 毫米之间”“这个区域里有没有黑色异物”那这就是几何和灰度问题传统算子更快、更稳、更好解释而且不需要样本。反过来如果判定标准连老师傅都说不清——“这个表面看起来发花”“这个纹理不对劲”“这批的划痕和上一批的划痕长得不一样”——那才是深度学习的主场因为它擅长从大量样本里拟合出一种人说不清楚的判别边界。更实际的做法往往是混合架构传统算法负责定位和粗筛用模板匹配把 ROI 摆正用几何工具把尺寸量出来深度学习负责在 ROI 内部做缺陷判别。定位交给传统算法是因为它确定性强、可解释、出问题能查判别交给模型是因为它对付外观类问题确实有优势。这个组合我在多个项目里用过工程上的好处是即使模型哪天判得不准你至少知道定位是对的问题范围能缩小一半。还有一个坑要提深度学习模型的“准确率 99%”和产线要的“连续 8 小时不误停”完全是两回事。离线测试集上的 99% 是在均衡样本上跑出来的产线上良品和不良品的比例可能是 1000:1模型的假阳性率会被放大成“每小时误报三次”。所以评估模型时我只看两个数在良品上的误报率和在极端样本最暗、最脏、最偏上的漏检率。2. 硬件选型的核心细节解析2.1 光源被低估的 80% 成功率如果让我给机器视觉的各环节按“投入产出比”排序光源绝对排第一。一套系统能不能做出来八成在打光阶段就决定了。算法是补救手段不是主要手段——图像里没有的信息算法变不出来。打光的本质是制造对比度。你要让“该看见的东西”和“不该看见的东西”在灰度上拉开差距。常见的手法有这么几类我按适用场景列一下打光方式原理典型适用场景常见坑环形光直射从四周斜上方均匀照射一般表面、字符、丝印高反光面会形成亮斑遮住缺陷低角度/暗场光几乎贴着表面掠射划痕、凹坑、毛刺、边缘破损平面上的污渍也会被照出来干扰大背光透射光从物体背面穿过轮廓尺寸、孔位、透明件内部异物不透光工件用不了边缘衍射会带来误差同轴光光与镜头同轴靠半反镜反射镜面、金属高反光面、芯片表面只对平整镜面有效曲面会失效穹顶光圆顶内壁多次漫反射形成无影照明曲面、反光回转体、铸件亮度偏低需要更长曝光条形光/线光局部高强度线状照明大幅面扫描、线扫相机配套均匀性难保证需要仔细调角度偏振光加偏振片滤除镜面反射分量塑料件、玻璃、油膜表面会损失大量光强需要更强光源实操里最重要的两个动作一是拿样品在暗室里试打光把光源角度从 0 度到 90 度一寸一寸转盯着图像看对比度什么时候最好二是看直方图不看画面人眼会被屏幕的自动亮度骗直方图上目标特征和目标背景的两个峰分得越开说明打光越成功。一个很省事的验证方法把同一批样品里“最难检的那几个”单独挑出来如果打光方案能让这几个的直方图双峰依然分离那这套光基本就稳了。只拿好样品验证打光是最常见的自欺欺人。光源还有两个隐性成本要注意衰减和散热。LED 用久了亮度会掉尤其是长期满功率工作的半年掉 10%~20% 很常见。所以打光方案要留余量控制器别长期跑在 100%。散热没做好光源附近的塑料件会变形角度就跑了——这也是为什么我坚持光源支架要用金属件、要有定位销。2.2 镜头焦距、视野、工作距离的换算镜头选型的核心就三个数的关系视野FOV、工作距离WD、焦距f。三者知道两个就能定第三个公式是f WD × h / FOV_h其中h是相机靶面在对应方向上的物理尺寸毫米FOV_h是该方向要拍到的实际视野。这个公式是薄透镜近似实际选型时要在算出来的焦距上往小取一档因为视野要留余量不能刚刚好。举个我实际算过的例子。要检测一个 90mm × 70mm 的区域机械结构给定的工作距离是 300mm相机是 1/1.8 英寸靶面约 7.2mm × 5.4mm长宽比 4:3。先算短边的视野余量70mm 的短边加 20% 余量取 85mm长边对应 85 × 4/3 ≈ 113mm。按长边算焦距f 300 × 7.2 / 113 ≈ 19.1mm。标准焦距里 20mm 最接近往小取一档就是 16mm 或 20mm。选 20mm 时实际视野FOV_h 300 × 7.2 / 20 108mm短边108 × 3/4 81mm比需求的 85mm 略小。这时候有两个选择把工作距离拉到 320mmFOV_h 320 × 7.2 / 20 115mm短边 86mm刚好够或者换 16mm 焦距FOV_h 300 × 7.2 / 16 135mm短边 101mm余量偏大但能用。我一般会选拉工作距离的方案因为焦距短的镜头畸变通常更大边缘分辨率也更差。但如果结构上拉不动就老老实实换短焦然后靠标定去校畸变。除了焦距还有三个参数不能忽略光圈F 值。光圈决定进光量和景深。F 值越小进光越多、景深越浅F 值越大景深越深、但光少了、而且光圈太小会出现衍射导致分辨率下降。一般工业检测用 F4~F8想要大景深就往上走但别超过 F11否则衍射会吃掉锐度。景深估算。粗略的经验公式是DOF ≈ 2 × F × δ × (WD/f)²其中F是光圈 F 值δ是允许弥散圆一般取 2~3 个像素的物理尺寸。代入上面的例子像素尺寸假设 3.45μmδ 2 × 3.45μm 6.9μmF 取 8WD/f 300/20 15则DOF ≈ 2 × 8 × 0.0069 × 225 ≈ 24.8mm。这个景深对于有高度差的工件比如冲压件边缘是够用的但如果工件上下起伏超过 25mm就得重新算或者改用远心镜头。畸变与远心。普通镜头边缘会有桶形或枕形畸变做大尺寸测量时边缘误差会很明显。精度要求高比如公差 0.02mm 以内而且测量区域靠近视野边缘时我建议直接上远心镜头——畸变小、没有透视误差、景深内放大倍率恒定。代价是贵、体积大、视野通常比较小工作距离也比较固定。选镜头时一定要问供应商要“MTF 曲线”和“畸变曲线”不要只看焦距和靶面。同样是 25mm 焦距不同设计的边缘分辨率能差一倍。便宜的镜头往往中心很锐、边缘一塌糊涂而测量往往恰恰发生在边缘。2.3 相机分辨率与精度的连锁计算相机选型被问得最多的问题是“我要多少万像素”。这个问题不能直接答得从精度需求倒推。计算逻辑是像素当量 视野短边 / 相机短边像素数然后要求最小可辨识特征至少覆盖 3~5 个像素这是工程经验值不是物理极限2 个像素也能检但稳定性会很差。继续用前面的例子视野 108mm × 81mm要求能检出 0.1mm 的缺陷。先按 3 像素算需要的像素当量0.1 / 3 ≈ 0.0333 mm/pixel。短边像素数81 / 0.0333 ≈ 2432。这就是 500 万像素约 2592×1944的量级勉强卡在线上。按 5 像素算更保险0.1 / 5 0.02 mm/pixel短边81 / 0.02 4050像素对应 1200 万像素4096×3000级别。所以结论很清楚这个需求下500 万像素是“理论上够、实际会飘”1200 万像素是“稳定够用”。如果客户对误检率要求苛刻我会选 1200 万甚至更高同时把视野再收一点比如只拍 80mm × 60mm 的关键区用降低视野来提升像素当量比单纯堆分辨率更划算。除了分辨率还有几个参数要一起看帧率与曝光时间。产线节拍如果是每件 200ms那相机帧率至少要 5fps但真正卡脖子的是曝光时间——物体在运动曝光期间会拖影。拖影量 速度 × 曝光时间。假设传送带速度 200mm/s曝光 1ms拖影 0.2mm曝光 10ms拖影 2mm直接糊掉。所以运动物体的曝光时间必须压到 1ms 以内这时候就得靠强光源和增益补偿而不是靠延长曝光。靶面尺寸与镜头匹配。相机靶面必须小于等于镜头支持的像面尺寸否则四角会有暗角。1/1.8 英寸的相机配 2/3 英寸镜头是安全的反过来就不行。这一条每年都有人踩。接口与带宽。千兆网口理论 1000Mbps实际有效带宽约 100MB/sUSB3.0 约 350MB/s万兆网口和 Camera Link 更高。算一下1200 万像素、8bit 灰度图一帧约 12MB千兆网口满打满算每秒 8 帧左右。如果节拍要求 20fps千兆网口就不够必须上万兆或者降分辨率、降位深。这个账一定要在选型阶段算不要等设备装好了才发现丢帧。2.4 触发、同步与通信链路这一块是典型的“平时不出事、出事就是大事”。我见过太多系统图像质量完美、算法效果很好就是偶尔丢一张图导致漏检查了两周查不出来。硬触发 vs 软触发。软触发是软件发命令让相机拍简单但有延迟抖动操作系统调度、网络延迟都可能引入几毫秒到几十毫秒的不确定高速产线上绝对不能用在关键位置。硬触发是光电开关或编码器直接给相机 IO 一个电平信号抖动在微秒级稳定得多。只要物体是运动的我一律要求硬触发。编码器同步。线扫相机的场景几乎必须用编码器因为线扫是“物体走多少、相机拍一行”行频必须和实际速度严格匹配否则图像会被拉伸或压缩。这里的坑是编码器分辨率与行频的匹配假设编码器 1000 线/转辊轮周长 200mm那么每线对应 0.2mm 的位移如果要求纵向像素当量 0.1mm/行就得每 0.5 线触发一次行采集——这就要求采集端支持分频行触发倍频/分频。配置错了图像纵向比例就错了测出来的尺寸全是错的而且这种错误很隐蔽因为图像看起来“挺正常”。IO 与通信链路。触发信号用屏蔽线、走独立线槽、远离变频器和伺服驱动器这几条是底线。我遇到过一次偶发丢触发最后发现是触发线和伺服动力线绑在同一根线槽里跑了三米伺服一启动就干扰。分开走线之后问题消失。另外PLC 输出的触发信号如果是 NPN 型相机输入如果是 PNP 型中间要加转换别硬接。一个很实用的验收动作让设备连续跑 8 小时空转统计相机实际采集帧数和触发信号次数两个数必须完全一致。差一帧都说明链路有问题。这个测试花不了多少时间但能提前暴露 90% 的同步问题。3. 算法实现与实操过程3.1 标定把像素翻译成毫米算法链路的第一步不是找缺陷是标定。因为量化的一切结论前提都是“一个像素对应多少毫米”而这个换算关系在不同位置、不同高度上是不一样的。标定分三层从简到繁第一层是像素当量标定。拿一块已知尺寸的标准件比如标准量块、校准板、印刷好的圆点阵列拍照测出它的像素宽度除以实际宽度得到mm/pixel。这一步最简单但只能用在“被测物和标定板在同一工作距离平面”的场合。工件高度变了放大倍率就变了像素当量就失效了。第二层是畸变校正。用棋盘格或圆点阵列标定板从不同角度拍多张一般 10~20 张解算出相机的内参焦距、主点、畸变系数。校正之后图像上任意一点的像素坐标都能映射到物理坐标。这一步对测量的意义很大——如果只在图像中心做标定、却在实际测量时用到边缘误差可能有几个像素甚至十几个像素。我做过对比同一块板中心区域测出来的尺寸和边缘测出来的能差 0.03mm而这个差距在 0.05mm 公差的场景里是致命的。第三层是手眼标定。如果视觉只是“看”不需要把结果交给机械臂去抓那前两层就够了。但如果要做引导抓取或定位打孔就必须标定相机坐标系和机械坐标系的变换关系。九点标定是最常用的做法让机械臂带着标定针走到 9 个不同位置每个位置记录机械坐标和图像坐标解一个仿射或透视变换矩阵。这里的关键是九个点要尽量铺满工作视野只在视野中心附近取点边缘的映射误差会很大。标定这件事的经验标定板一定要用高精度的而且要和被测物在同一平面、同一光照条件下拍。我见过有人用打印机打出来的棋盘格做标定打印机本身的走纸误差就有 0.1mm 量级标出来的结果自然是错的。另外标定完成后一定要用独立的验证件不是标定用的那块去反测一次看测量值和真值差多少这个“反测环节”是所有标定必须做的闭环。3.2 传统算子的组合拳传统视觉算法的核心不在于某一个算子有多强而在于怎么把几个简单算子组合成一条稳定、可解释的流水线。我一般的套路是预处理 → 定位 → ROI 提取 → 特征提取 → 判定。预处理主要是为了把图像“标准化”。常见动作有高斯滤波去噪、中值滤波去椒盐噪声但会吃掉细小的缺陷慎用在缺陷检测的前段、直方图均衡或灰度拉伸拉对比度、形态学开闭运算去毛刺、填小孔。这里有个原则预处理越少越好。每加一步预处理就多一份信息损失和一份参数需要调而且调参的人往往不是写代码的人半年后谁来维护是个现实问题。定位环节我几乎必用模板匹配但不是灰度匹配是形状匹配基于边缘梯度。原因是灰度匹配对光照变化极其敏感车间灯光一变、或者工件表面批次有差异匹配分数就掉形状匹配只依赖边缘梯度方向对光照变化鲁棒得多还能处理部分遮挡。定位的作用是把后续所有 ROI 都建立在“相对工件”的坐标系上而不是“相对图像”的固定坐标。这一条是工业视觉和实验室视觉最大的区别——实验室里相机和物体都是固定的车间里工件每次摆放的位置、角度都可能有偏差。特征提取按检测类型分尺寸测量用卡尺工具 亚像素边缘拟合。卡尺沿一条指定的搜索线扫灰度投影找出边缘的亚像素位置用插值或拟合然后把多个边缘点拟合成直线或圆再算距离、角度、半径。亚像素拟合能把测量精度做到像素当量的 1/5~1/10这是为什么 3 像素覆盖就够用的原因——因为你不是在数像素是在拟合。缺陷检测用blob 分析 形态学筛选。二值化之后把连通的亮区或暗区找出来按面积、长宽比、圆度、灰度均值过滤。这套方法对“异物、脏污、缺料”这类对比度明显的缺陷非常有效而且速度快、可解释。字符识别用分割 模板比对或轻量分类模型。如果是固定字体的喷码模板比对就够了比训练 OCR 模型省事得多。代码层面这类流水线一般长这样示意省略具体库# 伪代码一个典型的尺寸测量流水线 img grab_image() # 硬触发采集 img gaussian_blur(img, sigma1.5) # 轻量去噪别过度 # 形状匹配定位得到工件位姿 pose shape_match(img, template, angle_range(-15, 15), min_score0.7) if pose.score 0.7: return NG(定位失败) # 定位不可信时不硬判 # 在工件坐标系下提取 ROI roi transform_roi(base_roi, pose) # 卡尺找边 亚像素拟合直线 edges_1 caliper_scan(img, roi.line_1, polaritydark_to_light, sigma1.0) edges_2 caliper_scan(img, roi.line_2, polaritydark_to_light, sigma1.0) line_1 fit_line_subpixel(edges_1) line_2 fit_line_subpixel(edges_2) # 换算物理尺寸 distance_px distance_between_lines(line_1, line_2) distance_mm distance_px * calibration_scale(pose) # 按位置查当量 return OK if abs(distance_mm - 10.0) 0.05 else NG(distance_mm)这段代码里有几个细节值得说min_score的阈值不能设太高设 0.9 会因为光照波动频繁报定位失败polarity要写清楚是从暗到亮还是从亮到暗写反了找到的是另一条边尺寸直接错calibration_scale如果做成按位置查表能修正畸变带来的当量变化比全局一个常数准得多。传统算法的调试顺序我坚持“先静态、后动态先单件、后批量”。先拿一个标准件在静止状态下把所有阈值调到完美再放上流水线跑先跑 10 件看单件结果再跑 1000 件看统计分布。一上来就跑大批量出了问题根本不知道是哪一环。3.3 深度学习缺陷检测的落地姿势深度学习在视觉里真正创造价值的场景基本集中在“外观缺陷”这一块因为这块传统算法最难做。但它的落地门槛比很多人想象的高我把关键点捋一遍。第一是问题定义。到底做分类、检测还是分割如果只是判“这件有没有缺陷”用分类模型最省事如果要框出缺陷位置让操作员复核用目标检测如果要精确算出缺陷面积用语义分割。我的经验是能用分类就不用检测能用检测就不用分割因为标注成本是按这个顺序指数级上升的。第二是样本。这是最要命的环节。缺陷样本天然稀少而且“缺陷”的定义往往不稳定——不同质检员对同一道划痕的判定都可能不一样。我一般的做法是先跟质检的师傅一起挑出 200~500 张“确定的良品”和 100~300 张“确定的不良”把边界模糊的先剔掉用这批干净数据训第一版。然后用第一版去跑大量未标注数据把模型“犹豫”的那批挑出来人工复核逐步扩充。这个循环比一次性收集几万张样本有效得多。第三是数据一致性。这条比模型结构重要十倍。训练集和产线实拍的图像如果光照、相机、镜头、曝光参数有任何一项不同模型的效果都会掉得很厉害。我要求训练数据必须来自实际产线的那台相机、那套光源、那个工位而且要在不同班次、不同时间段各采一批覆盖环境光的变化。用实验室拍的图训模型搬到车间基本等于重来。第四是模型评估方式。前面说过别看总体准确率。我一般看四个数良品误报率FPR、不良漏检率FNR、在“困难样本集”上的表现、以及模型输出的置信度分布。如果大量样本的置信度集中在 0.5 附近说明模型其实没学到东西只是在对噪声做随机判断。这个分布图比任何单一指标都诚实。第五是部署与解释。模型上线后操作员一定会问“为什么这张判 NG”。如果你答不上来现场信任度就建立不起来。所以我会准备两张图一张是热力图模型关注区域一张是和“最相似的训练样本”的对比。哪怕只是给个参考也比“模型说的”这四个字强得多。深度学习模型最怕的不是精度不够是漂移。产线换了批次、换了供应商、光源老化了模型的输入分布就变了表现会慢慢下降。所以上线时必须配套一个“在线抽检”机制每天定时抽若干件人工复判把结果和模型判定对比一旦一致率跌破阈值就报警。这个机制不做模型就是一颗定时炸弹。3.4 节拍、内存与稳定性调优算法在开发机上跑 50ms到产线上跑 150ms这种情况太常见了。原因无非几个开发机的 CPU 更强、产线机上还跑着别的程序、图像从相机到内存多拷了几次、Python 的 GIL 卡住了。节拍优化的顺序我一般是这么排的先算预算。节拍 200ms要给机械动作留 80ms给通信留 20ms算法只有 100ms。这个预算写下来后面每加一个算子都要问“它占多少”。然后是减少数据搬运。图像从相机缓冲区到处理内存每拷一次就是几毫秒1200 万像素 12MB内存拷贝大约 2~5ms。能用零拷贝的接口就用零拷贝能直接在相机缓冲区上处理就别先转存。这一条经常能省掉 20% 的时间。再是降低无效计算。全图搜索模板匹配很慢但如果先用一个降采样的小图做粗定位再在原图的小窗口里做精定位时间能降一个数量级。测尺寸时也没必要处理整幅图ROI 只取需要的带状区域就行。最后才是并行。多相机可以用多线程一个相机的流水线内部也可以拆成“采集线程 处理线程 输出线程”三级流水让采集和处理重叠。但并行会带来资源竞争和调试复杂度我一般放到最后做而且做完必须做长时间稳定性测试——并发 bug 往往要跑几小时才暴露。内存管理这块长时间运行的系统最怕内存缓慢增长。图像对象、结果列表、日志缓存任何一个没释放跑一周就会 OOM。我的做法是处理流程里所有大对象预先分配好复用结果只保留最近 N 条日志异步写入并且按天切分。上线前跑一次 24 小时压测盯内存曲线必须是平的。4. 常见问题与排查技巧实录4.1 现场高频问题速查表我把这些年遇到的高频问题按“现象—可能原因—排查动作”整理成一张表现场调试时基本能覆盖大半现象优先怀疑的原因排查动作图像整体发暗、对比度低光源衰减、光圈太小、曝光太短看直方图右端是否被截断换新光源对比亮度高反光面出现大片死白直射光角度不对、缺少偏振改成低角度或加偏振片转动光源看亮斑是否移动边缘测量值忽大忽小亚像素边缘不稳定、光照波动打印边缘灰度剖面看过渡带宽度是否超过 3 像素同一样品重复测量差异大机械振动、支架松动、触发时机不对拍连续 10 张比差异手摸支架感受振动改硬触发偶发漏检跑几小时出现一次丢帧、触发丢失、通信超时统计触发次数与采集帧数是否一致看通信日志有无超时换批次后误检率暴涨表面工艺变化、颜色/纹理变了对比新旧批次直方图重新评估打光方案定位分数间歇性偏低工件摆放角度超出模板范围、部分遮挡放宽角度搜索范围检查模板是否包含了易变区域处理耗时随运行时间变长内存泄漏、日志堆积、句柄未释放跑 24 小时压测看内存曲线和句柄数图像出现规律性横纹光源频闪与曝光不同步、电源纹波改用恒流驱动曝光时间设为工频周期的整数倍相机偶尔断连网线质量、供电不稳、网卡节能设置换屏蔽网线关掉网卡节能检查供电电压这张表里我个人觉得最值得记住的是“偶发漏检”那一行。所有偶发问题第一反应都应该是查链路而不是查算法。算法是确定性的同样的输入一定给同样的输出链路是不确定的丢一帧、晚一拍算法根本不知道。所以先把“输入是否可靠”这件事钉死再谈算法优化。4.2 几个反复踩的坑坑一用调试时的参数直接上线。调试时是白天车间窗外的自然光很亮晚上窗外的光没了环境光变了图像整体亮度掉了一档所有基于灰度绝对值的阈值全部失效。解决办法很土但有效把工位用遮光罩围起来并且把参数按“最坏光照条件”调。调完之后在晚上再复测一遍。坑二把曝光时间当成万能调节旋钮。图像暗了就把曝光调长结果运动物体拖影边缘糊成一片测量值系统性偏大。正确的顺序是先加大光源功率或换更强光源再开光圈最后才动曝光而且曝光时间的上限要由运动速度倒推——拖影允许量除以速度就是曝光时间的上限。坑三标定只做一次然后永远用。相机被撞过一次、镜头被拧过、支架被震过标定就失效了但系统不会告诉你。我的做法是在标定板上做一个固定的参考标记每次开机拍一张检查这个标记的位置和尺寸是否在容差内超了就提示重新标定。这个自检动作只要几秒钟但能避免大量“莫名其妙的精度问题”。坑四ROI 写死成绝对坐标。工件摆放稍有偏移ROI 就框歪了测到的全是背景。所有 ROI 都必须建立在定位结果之上绝对不能写死。这一条在代码 review 时我会专门检查。坑五忽略温度。相机长时间工作会发热传感器温度升高会带来暗电流噪声增加长时间曝光的场景尤其明显。另外机械结构的热胀冷缩在测量精度要求 0.01mm 级别时是不能忽略的——一米长的铝型材温度变化 10 度长度变化约 0.23mm。所以高精度测量要么做温度补偿要么在恒温环境里做要么在开机稳定半小时后再标定。关于“注意事项”我最想强调的一条是所有参数都要有记录并且标明是什么条件下调出来的。我见过太多项目交接的时候只留下一堆配置文件没人知道里面那个 128 的阈值是为什么定的。半年后产品换了新来的人只能靠试。参数表加上“调参时的样品编号、光照条件、环境温度”这份记录的价值远超过代码注释。4.3 上线之后才是真正的开始很多项目在“验收通过”那一刻被当成终点实际上那只是起点。视觉系统是一个会随时间缓慢劣化的系统光源在衰减、镜头在积灰、相机传感器在老化、机械结构在松动、产品批次在变化。任何一个因素单独看都不致命叠加起来就是“用了半年之后误检率翻倍”。我一般会给每个项目配一套日常维护清单简单到操作员能执行每天开机做一次参考件复测记录测量值超过容差就报警每周擦一次镜头和光源出光面用无尘布加无水乙醇别用纸巾干擦每月对比一次当前参考件的图像和系统上线时保存的那张“基准图”用同一套算法跑看结果有没有漂移每季度检查一次支架螺丝、线缆接头、光源亮度用照度计或者干脆换新光源对比。这套清单看起来琐碎但它把“系统突然崩了”变成了“系统在缓慢变化我提前知道”。我在实际使用中发现凡是坚持做日常复测的项目出问题的频率和排查时间都明显更低——因为一旦出问题你手里有历史数据能一眼看出是“今天突然变的”还是“已经漂了一周了”。这个判断的差别往往就是半小时解决和三天解决的区别。最后一个很实用的建议给系统留一个“存档模式”。每次出现误判一键把当时的原图、定位结果、中间图像、算法参数、判定结果打包存下来。这些数据积累起来就是你后续优化的全部素材——调阈值有依据训模型有样本追责任有证据。没有这个机制所有现场问题到最后都只能靠回忆复现而人的回忆从来都不可靠。