20 卡尺测量与亚像素定位
从本章起,我们正式进入测量的领地。前面的章节回答”目标是什么、在哪里”,测量章要回答的是”它有多宽、多远、多圆”——把像素换算成毫米。章节 5 的标定给出了比例尺,但”用像素去量毫米”还有最后一公里:一套微米级分辨率的系统要做严苛的尺寸判定,边缘位置必须量到远小于一个像素。走完这最后一公里的标准工具就是卡尺(caliper):一个定向的一维测量器——给定一个 ROI、一个搜索方向和边缘极性,它沿搜索方向提取灰度剖面,找到一条边缘或一对边缘,直接输出亚像素位置与宽度。本章用一幅真实工业样图——Micro-USB 连接器的侧切面金相图——把卡尺的三个核心问题逐一量化:亚像素精度从哪里来、重复性由什么决定、精密度与准确度为何必须分开验。
实验对象如 图 20.1:2592×1944 的灰度图上,暗背景中是一只 Micro-USB 连接器的侧剖面,明亮的金属外壳里立着一排接触端子(pin)。每个端子是一条明亮的竖直金属条(灰度约 240),两侧是暗背景(灰度约 70),对比鲜明、边界陡峭——这正是卡尺的本职场景:沿水平方向搜索,量端子的宽度与端子间的间距。连接器装配的良率高度依赖端子的几何一致性,端子偏宽、偏窄或错位都会导致插接力异常或接触不良,因此端子宽度与节距(pitch)是这类零件的关键尺寸。本章取相邻两枚端子(记作端子 A、端子 B)作为测量靶标。
20.1 卡尺的工作原理
卡尺与 章节 14 的搜索线机制同根同源:在 ROI 内沿搜索方向取灰度剖面,垂直方向投影平均抑噪,对剖面求一阶导数,导数极值处做抛物线插值得到亚像素边缘位置。如果说边缘点提取器输出的是”一串点,留给你去拟合”,卡尺的差异化在于三点:其一,它原生面向边缘对(edge pair)——定位两条边缘并直接给出二者距离,即宽度;其二,当剖面上出现多个候选边缘时,它按强度、期望距离等评分规则选边,对油污、划痕造成的假边缘有内建的免疫力;其三,它的输出就是测量值本身,无需后处理。与 章节 13 的关系一句话即可说清:边缘检测回答”图中哪里有边”,卡尺则是”已经知道边大概在哪、要把它量准”时的一维特化——搜索范围从二维全图坍缩到一条线,速度与精度都因此受益。
“卡尺”得名于机械量具游标卡尺(vernier caliper):两个卡爪夹住工件读出宽度。软件卡尺是它的虚拟翻版——ROI 是卡身,两条边缘是卡爪的接触点。游标卡尺靠游标细分刻度,软件卡尺靠抛物线插值细分像素,思想一脉相承。
先把测量结果摆出来(图 20.2)。SciVision 的 SDK 卡尺给出端子 A 的左缘 x=1003.42、右缘 x=1036.15,宽度 32.73 px;端子 B 左缘 x=1076.68、右缘 x=1108.92,宽度 32.24 px。两端子中心间距(pitch)73.02 px,端子 A 右缘到端子 B 左缘的暗间隙宽度 40.53 px。这些是在像素域里的直接读数;若系统标定为 \(s\) μm/像素,端子节距即 \(73.02\,s\) μm。注意该 SDK 的卡尺拟合线恒为竖直(小节 20.5 详述),量出的是水平方向的距离;端子近乎竖直(用 LinePointsLocator 实测倾角仅 0.16°),水平宽度与垂直宽度之差在小数点后第二位才显现。
本章 SDK 输出采用像素角点坐标约定(整像素边界为整数,像素中心为 x.5):端子 A 左缘 x=1003.42 即位于第 1003 与 1004 列之间。比较不同库的亚像素结果时,先对齐坐标约定,否则会凭空多出 0.5 px 的”误差”。
20.2 亚像素精度从哪来
像素栅格的间距是 1,凭什么能把边缘量到 0.1 像素以内?答案藏在边缘的物理本质里:真实图像中的边缘从来不是数学上的阶跃。镜头的点扩散函数把锐利的物理边界抹成渐变,像元在自己的感光面积上对光强积分又进一步平滑(章节 3)——到达数字图像时,边缘已是一段横跨一到数个像素的灰度斜坡。图 20.3 把端子 A 左缘放大 8 倍:暗背景到亮端子之间不是一刀切,而是一条平滑过渡的灰度带,其间的”半灰”像素清晰可见。渐变正是信息所在:边缘的真实位置连续地决定了过渡带每个像素的灰度值——边缘向右挪 0.1 px,过渡带像素的灰度就按比例变化。亚像素定位做的事情,就是从这几个半灰像素的具体数值中把连续位置解码出来。
解码工具是 章节 14 已经用过的抛物线插值(其最小二乘根源见 章节 2):对剖面一阶导数幅值的离散极值点及左右邻 \(g_{-1},g_0,g_{+1}\) 拟合抛物线,顶点偏移 \(\delta=\dfrac{g_{-1}-g_{+1}}{2(g_{-1}-2g_0+g_{+1})}\) 即亚像素修正。图 20.4 把这一过程摊开在端子 A 左缘上:灰点是单行(y=845)的原始灰度采样,被传感器噪声抖得参差不齐;黑色折线是 111 行投影平均后的剖面,斜坡轮廓干净利落;竖直虚线即对平均剖面插值得到的亚像素边缘位置 x=1002.91。
插值公式本身是封闭的,精度的成色取决于喂给它的剖面有多干净。在端子 A 左缘逐行提取亚像素边缘,111 条搜索行的位置均值为 1002.96 px、标准差 0.37 px——这 0.37 px 既含传感器噪声,也含真实工件几何(见 小节 20.4)。而卡尺把这 20 条搜索行联合拟合成一条竖直线,单点估计的抖动被 \(\sqrt{N}\) 平均压低,最终输出的稳定度远胜单行。这正是 小节 20.3 要量化的主题。
20.3 重复性:测量的生命线
工业测量最关心的量之一是:同一工件反复测量,结果散布有多大——重复性(repeatability)。精密度说的是”测得稳”(方差小),准确度说的是”测得准”(均值离真值近);产线判定逻辑建立在”测量值的波动远小于公差带”之上,重复性差的系统哪怕均值无偏,也会把合格品误判为不良、把不良放进合格堆。
测得准 vs 测得稳:准确度偏差(bias)可以靠标定与标准件修正,随机散布却只能靠改善测量系统本身压低。量具能力分析(GR&R)的经验法则:测量系统的重复性(常取 ±3σ 散布)应不超过公差带的 1/10,否则测量误差会显著侵蚀判定的可信度。
真实样图只有一张、没有噪声集合可供蒙特卡洛,因此我们用ROI 微移复现重复性:把卡尺 ROI 沿端子方向上下平移 ±8 px(共 17 个位置,每次采样到的搜索行集合略有不同),统计四个测量量的散布:
| 测量量 | 单次测量 (px) | 重复性 σ (px, 17 次 ROI 微移) |
|---|---|---|
| 端子 A 宽度 | 32.73 | 0.073 |
| 端子 B 宽度 | 32.24 | 0.052 |
| 端子间距(中心) | 73.02 | 0.373 |
| 间隙宽度 | 40.53 | 0.362 |
两个端子宽度的重复性都在 0.05–0.07 px:换算到典型几微米/像素的系统,这相当于亚 0.5 μm 的单次测量散布。最值得咀嚼的是它与单行散布的对比——小节 20.2 测得逐搜索行的亚像素边缘散布是 0.37 px,而卡尺把 20 条搜索行联合拟合后,宽度重复性降到 0.073 px,约为单行散布的 1/5;这正是 章节 2 的 \(\sqrt{N}\) 定律:\(0.37/\sqrt{20}\approx 0.083\),与实测的 0.073 同量级。多搜索行的投影/拟合,是几乎免费的重复性放大器——把 ROI 沿边缘拉长、增加搜索行数,就能等比例压低位置估计的方差,上限由边缘与搜索线的垂直程度决定。
为何端子间距与间隙的 σ(0.37、0.36 px)比单个端子宽度大近五倍?因为它们各自由两枚不同端子、两个独立 ROI 的边缘相减得到,两端的拟合误差不再像同一端子的左右缘那样高度相关,散布按近似独立叠加放大。这是组合量测量的通则:误差随参与边缘的数目与独立性增长,量节距比量单个宽度更”娇气”。
20.4 精密度不等于准确度
上一节量到的 0.07 px 重复性很漂亮,但它只回答了”测得稳不稳”,没有回答”测得准不准”。这是真实样图与合成场景最根本的区别:合成图自带真值,可以直接算偏差(bias);这张连接器样图没有任何认证过的端子宽度真值,我们只能给出精密度(precision),给不出准确度(accuracy)。报告 32.73 px 这个数时必须诚实——它的重复性是 0.07 px,但它离真实物理宽度有多远,本图无从判定。产线上补全这一环的办法只有一个:放置一枚尺寸经计量院认证的标准量块,用它把像素读数锚定到物理单位并校正系统偏差——这与 章节 5 强调的”标定给比例尺、标定会过期”是同一件事。
真实数据还揭示了一个合成图上看不到的细节:那 0.37 px 的逐行散布不全是噪声。端子 A 左缘 111 行的亚像素位置最小 1002.42、最大 1004.59,跨越约 2 px——这不是随机抖动,而是冲压成形的金属端子边缘本身有轻微的锥度与弯曲,是真实工件几何。卡尺的竖直直线拟合把这段略带弧度的边缘”压”成一条代表性直线,0.37 px 里混着传感器噪声与零件形貌两种成分。这是一条重要的工程教训:不要把所有散布都当噪声——有时散布里藏着零件的真实形状信息。若关心端子是否弯曲,恰恰要把这段残差从拟合里挖出来分析,而不是一味用更多平均把它抹平。
合成场景能算偏差是因为真值由我们写定;真实样图测的是”未知零件”,没有真值就只有精密度。这并非缺陷而是常态:产线绝大多数测量都没有逐件真值,靠的是标准件标定 + 重复性监控这套组合拳来保证可信度。
由此得到本章的实践纲领:用真实零件评估算法时,把精密度与准确度分开报告。重复性可以从单张图的 ROI 微移、或同一工件的多次取像中直接量出;准确度则必须引入外部标准件。把二者混为一谈——拿无真值的样图谈”精度”、或拿理想合成图的偏差冒充真实表现——都会得出与产线实况脱节的结论。
20.5 SciVision 实现
卡尺由 SCIMV::SciSvCaliper 提供,但这个模块的现状需要如实交代。手册 7.1 节描述的旧接口在头文件中被 #if 0 整段屏蔽,实际可用的是现行 Caliper()。实测它有几条与文档不符的行为:极性参数只有 polarity1=2 能找到边缘,其实测语义是”沿搜索方向由暗到亮”——与头文件注释恰好相反,传 0 或 1 一律报错 122504007;边缘对模式(edge2Idx>=1)从不输出宽度(widthArr 恒为 0);微分卡尺 mode=1 恒失败;拟合的边缘线恒为竖直(角度输出恒 90°)。“卡尺量宽度”这一本职功能,工程上用两次单边调用绕行实现:在仅含单枚端子的 ROI 内,direction=2 从左向右、direction=3 从右向左各搜一次(暗→亮极性各命中端子一侧),两条竖直拟合线的 x 之差即水平宽度:
EdgeDirection dir;
dir.direction1 = direction; // 2=从左向右;3=从右向左(两次调用分别命中端子两侧)
dir.polarity1 = 2; // 实测唯一可用:沿搜索方向暗->亮(与头文件注释相反)
EdgeFilter filter;
filter.searchLineCount = 20; // ROI 内 20 条搜索行
filter.edgeWidth = 3; filter.projectWidth = 1; // mode=0 已对全 ROI 投影,勿再加大
filter.sensitivity = 30; filter.strengthThresh = 30; filter.strengthLimit = 255;
EdgeScoring scoring;
scoring.maxResultNum = 5; scoring.expectDist = 34; scoring.sortMethod = 0;
SCIMV::SciSvCaliper cal;
long rc = cal.Caliper(src, roi, region, /*mode 卡尺*/0, dir, filter, /*trend*/0,
/*pattern 指定边缘*/0, /*edge1Idx*/1, /*edge2Idx 单边*/0, scoring,
&avg, &widthArr, &scoreArr, &mxi, &mni, &pos1, &ang1Arr, &pos2, &ang2Arr);
double edgeX = 0.5 * (pos1[0].x + pos1[1].x); // 拟合线恒竖直,两端点 x 相同
// 端子宽度 = max(e2,e3) - min(e2,e3);端子中心 = 两缘均值;节距 = 两端子中心之差strengthThresh=30 是一阶导数幅值门槛;expectDist=34 告诉评分器端子的期望宽度尺度;edge1Idx=1, edge2Idx=0 表示只取第 1 条边、不组边对。小节 20.1 的 32.73 px 宽度就出自端子 A 的这两次调用。一个实测要点:端子的左缘梯度仅在 y∈[780,920] 强而稳定,此区间外端子顶/根部对比度骤降会令卡尺报 122504007;ROI 与搜索带必须落在边缘清晰的区段内——这是真实样图相对理想合成图多出来的一道功课。
LinePointsLocator 对照路线的价值有三重:它量的是垂直于边缘的真实宽度(SDK 卡尺只能量水平宽度,倾角越大失真越大);它把每条搜索线的亚像素点交还用户,便于自算逐行散布与直线度;它还顺带给出边缘倾角(端子 A 实测 0.16°)。实现上有一处细节:近竖直边缘改拟合 \(x = ay + b\),规避 FitLine 对竖直点集的缺陷(章节 14):
SCIMV::SciSvLineLocator loc;
SciPointArray pts;
long rc = loc.LinePointsLocator(src, roi, region, /*strengthThresh*/30,
/*direction 左->右*/2, /*polarity 暗->亮*/0, /*edgeWidth*/3,
/*projectWidth*/1, /*edgeType 最佳*/2, /*searchLineCount*/16,
/*findPointType 一阶导*/1, &pts);
// 对 pts 自拟合 x = a*y + b;两侧拟合线在 ROI 中心高度的距离 / sqrt(1+a^2) 即垂直宽度商用 SDK 的卡尺模块带着这些怪癖并不罕见,对策与 章节 14 一致:用关键量从原始输出自行复算,并在真实样图上逐参数实测可用区间。完整可运行工程位于 code/caliper_measurement/。
工业案例:0.01mm 公差的玻璃宽度测量
某盖板玻璃磨边线要求宽度公差 ±10 μm,成像分辨率 5 μm/像素——公差带折合 ±2 px,按 1/10 法则重复性须达 0.2 px。投影平均后的卡尺单次重复性约 0.07 px(0.35 μm),看似余量充足,量产数据却暴露另一个敌人:车间昼夜温差让镜筒与机架热胀冷缩,测量均值在一天内漂移 0.5 μm——是重复性散布的五倍。精密度好不等于准确度高:散布是”今天测一百次差多少”,漂移是”早上和下午各测一次差多少”,后者恰恰是重复性指标看不见的。最终方案是在线放置标准量块,每两小时复测一次、实时修正比例尺——量具校准才是测量的地基,这与本章 小节 20.4 强调的”精密度不等于准确度”是同一回事。
20.6 小结
- 卡尺是定向一维测量工具:ROI + 搜索方向 + 极性圈定问题,投影、求导、抛物线插值给出亚像素边缘——它与搜索线机制同根,是”已知边在哪、要量准”场景的一维特化。本章在真实 Micro-USB 连接器上测得相邻端子宽度 32.73 / 32.24 px、中心间距 73.02 px、间隙 40.53 px。
- 亚像素信息藏在渐变里:镜头 PSF 与像元积分把边缘抹成灰度斜坡,斜坡像素的数值连续编码边缘相位;真实端子边缘 8 倍放大可见清晰的过渡带,抛物线插值即从中解出亚像素位置。
- 重复性是测量的生命线,多搜索行平均是它最便宜的放大器:逐行亚像素散布 0.37 px,经 20 行直线拟合后端子宽度重复性降到 0.073 px(≈ 0.37/√20),机理是 \(\sqrt{N}\) 定律;组合量(节距、间隙)因合并两个独立 ROI 的误差,散布放大近五倍至 0.37 px。
- 精密度不等于准确度:无认证真值的真实样图只能给精密度(0.07 px)、给不出准确度;准确度需外部标准件锚定。逐行散布里还混着冲压端子的真实锥度(约 2 px),不可一概当噪声平均掉。
- 对 SDK 的卡尺模块保持实测态度:本版
Caliper()的极性语义与注释相反、边缘对不输出宽度、拟合线恒竖直,工程上用两次单边调用绕行;并须在样图上实测边缘清晰的可用区段(端子仅 y∈[780,920] 可测)。LinePointsLocator自拟合路线提供垂直宽度与倾角,是更可控的对照。
边缘定位的精度极限、各种亚像素方法的偏差与方差分析,可进一步阅读 Steger 等人著作中关于一维边缘提取与精度评估的章节 (Steger, Ulrich, 和 Wiedemann 2018)。亚像素边缘定位的经典源头之一是 Haralick 用二阶方向导数过零点配合面元(facet)模型的阶跃边缘检测,它系统刻画了边缘相位如何从局部灰度多项式中解析地恢复出来 (Haralick 1984)。至于本章反复强调的”精密度不等于准确度”与重复性—再现性(GR&R)评定,则属于量具能力分析的范畴:AIAG 的《测量系统分析》参考手册给出了重复性、再现性、偏差与线性的标准评估流程,是把本章的散布数字接到产线判定规范的权威依据 (Automotive Industry Action Group 2010)。



