surface_form_remove — ROUGHNESS prepare op

• 数据种类:depth → depth

• 调用: import fullseye as fs; fs.ledger.surface_form_remove(z, dx, order=1, method='ls', thresh=None, dy=None, iters=200, seed=0)(要直接调用实现,import roughness; roughness.surface_form_remove(z, dx, order=1, method='ls', thresh=None, dy=None, iters=200, seed=0);从台账取用则 opsroughness.get("surface_form_remove"))

• 经台账调用的返回值: fullseye.ledger.surface_form_remove(...) 只返回声明的 out 类型 depth 的值(底层函数还会返回辅助信息)。需要被丢弃的部分时,使用 fullseye.ledger.surface_form_remove.raw(...),或直接调用 roughness.surface_form_remove。

• 底层返回: (residual, coeffs)

用法

直接在网格上去除平面 / 二次曲面。返回 (residual, coeffs)。

参数

z 高度场。

dx, dy 采样间隔。dy=None 为正方形像素。

order 1 = 平面,2 = 二次曲面。

method "ls"(最小二乘)或 "ransac"(鲁棒)。

thresh RANSAC 的内点阈值(高度单位)。为 None 时使用最小二乘残差的

鲁棒离散度 2.5 x 1.4826 x MAD。

iters RANSAC 的试行次数。由 seed 确定。

coeffs 是以场的中心为原点的物理坐标下的单项式系数。order=1 时为 [c0, gx, gy],gx/gy 直接就是梯度; order=2 时为 [c0, gx, gy, cxx, cxy, cyy](按 x^2, xy, y^2 的顺序)。

★ 为什么直接接收网格

现有的 fit_plane / fit_plane_ransac 只接收 (N,3) 点云。

要传入 512² 的高度场,每次都得用 column_stack 展开成 262144x3 = 6.3 MB

(实测)。这里把网格作为网格直接接收,基底也

用 1 维向量的外积构造,因此无需展开。

★ 开销(实测,1024x1024,iters=200)

method="ls" 47 ms,而 method="ransac" 为 1.8 秒(38 倍)。

RANSAC 每次都要重新统计 1024² 个点的残差,因此与 iters 成线性关系。

若只看粗糙度,“LS + λc 高通”能以 1/40 的开销得到相同答案

(见下方实测)—— 这就是不把 RANSAC 设为默认的原因。

★ 陷阱 —— 需要鲁棒性的不是“深划痕”,而是“宽的离群值”。

但当离群值成为多数时,RANSAC 也会一起失效。

在把 4 条深 3 µm 的划痕集中在一侧的 512x512 面上,只改变划痕的宽度的

实测(注入并去除 0.050/-0.025 的倾斜。真值是含划痕的面本身):

划痕半高半宽 面积比 LS 的 Sq 误差 RANSAC 的 Sq 误差 改善

4 µm 5.6 % -1.94 % -0.39 % 5.0 倍

12 µm 16.3 % -6.47 % -3.03 % 2.1 倍

24 µm 31.0 % -13.79 % -11.53 % 1.2 倍

40 µm 46.0 % -23.80 % -23.56 % 1.0 倍

可以读出 3 点:

• 起作用的不是深度而是面积比。“深划痕 = 必须鲁棒”是草率的结论,正确的是“宽的离群值 = 必须鲁棒”。

• 误差必定出现在偏小一侧 —— 因为最小二乘连“划痕集中在一侧所造成的真实不对称”也当作平面吸收掉了。在合格判定中会朝危险的方向失效。

• 面积比 46 % 时 RANSAC 也帮不上忙(改善 1.0 倍)。离群值占到近一半时,RANSAC 的多数表决本身就会选中划痕。鲁棒拟合是以“离群值是少数”为前提的工具,该前提失效之处只能用表来展示。

★ 陷阱 —— 把 λc 放在后级,LS 与 RANSAC 的差就消失了

对同一个面(半高半宽 4 µm)事后施加 λc=80 µm 的高通,

Sq 误差为 LS +0.00 % / RANSAC -0.00 %(上表中相差 5.0 倍)。

多去除的平面是纯粹的长波长,高通只是把同样的东西再

扔一次而已。拟合的鲁棒性起作用的是不施加 λc 的使用方式(平面度、形状偏差)时。 若只看粗糙度,靠顺序就能挽救。

另外,平面本身的恢复用 LS 也不错:对上面那个面中注入的梯度

0.050 / -0.025,返回 0.050006 / -0.025127(实测)。

fail-closed(失败即拒绝)

• order 不是 1 或 2 / method 不是 "ls"、"ransac"。

• thresh 非正、非有限。

• RANSAC 收集不到规定数量的内点(退化的面)。

详细使用指南

• surface_roughness 族使用指南

参考(示例数据、文献)

• 示例数据目录(下载 URL / 许可证) —— 2-D 用 skimage.data(BSD/公有领域)加合成图,3-D 给出真实数据源(Stanford/PDS 等)的下载 URL。

• 算子来历与参考文献 —— 该算子族所依据的研究/方法出处。

• 算法的正典(作者、年份)与用途见上面的族使用指南。

可运行的示例(实际调用该算子并已验证的样例)

• poc_polish_wipe_measure — py -3.11 examples/poc_polish_wipe_measure.py

• poc_pv_thermal_survey — py -3.11 examples/poc_pv_thermal_survey.py

• poc_surface_roughness — py -3.11 examples/poc_surface_roughness.py

类型可衔接的下一个算子(可接受 depth 作为输入)

surface_filter · surface_params · surface_psd

同类别(prepare)

surface_filter


*Provenance: roughness.py — ROUGHNESS 算子登记表。本条目由 tools/opdocs.py md 自动生成(请勿手工编辑)。*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.