prepare op• 資料種類:depth → depth
• 呼叫: import fullseye as fs; fs.ledger.surface_filter(z, dx, lambda_c=None, lambda_s=None, kind='gaussian', end_effect='reject', dy=None)(要直接呼叫實作,import roughness; roughness.surface_filter(z, dx, lambda_c=None, lambda_s=None, kind='gaussian', end_effect='reject', dy=None);從台帳取用則 opsroughness.get("surface_filter"))
• 經台帳呼叫的回傳值: fullseye.ledger.surface_filter(...) 只回傳宣告的 out 型別 depth 的值(底層函式還會回傳輔助資訊)。需要被捨棄的部分時,請用 fullseye.ledger.surface_filter.raw(...),或直接呼叫 roughness.surface_filter。
• 底層回傳: (roughness, waviness)
將高度場分解為粗糙度與波紋度(ISO 16610-21 的高斯濾波器)。
回傳值為 (roughness, waviness)。roughness 是比 λc 短的成分,waviness 是長的成分;只要不是 end_effect="reject",roughness + waviness 就與輸入(套用 λs 之後的原始形狀)嚴格一致。
參數
z 高度場 z[i, j](列 = y,行 = x)。
dx, dy 取樣間隔。dy=None 為正方形像素。
lambda_c 長波長側截止(粗糙度 / 波紋度的分界)。為 None 時不分離
(waviness 為全零陣列)。
lambda_s 短波長側截止(去除雜訊的 S 濾波器)。None 時無效。
kind 僅 "gaussian"。傳入其他值時不會悄悄替代,而是拋出例外。
end_effect "reject"(預設) / "mirror" / "wrap"。見下文。
dy 列方向的取樣間隔(None = dx)。
★ 端部處理(end_effect)—— 這正是撰寫此 op 的理由
卷積在端部需要核半徑(GAUSS_TRUNCATE·λc = 0.75 λc,4 σ)範圍內「不存在之處的資料」。
標準(ISO 16610-28)以評定區域兩端各被削去一段為前提。
• "reject"(預設)—— 捨棄兩端各 ceil(0.75 λc/pitch) 個樣本。輸出是比輸入小的陣列。被捨棄的區域「沒有量測」,所以這是唯一不說謊的選項。
• "mirror" —— 以鏡像延拓並回傳相同形狀。假定面在端部是偶函數。
• "wrap" —— 循環卷積(與 FFT 相同)。假定左端的延續就是右端。
實測(★下表是截斷為 ±λc/2 的 2026-10-18 之前的量測。把核放寬到 ±0.75 λc 後,
1.~3. 的趨勢相同,只是端部帶從 40 個樣本增至 60 個。數值未重新量測)。
真值是對 704x704 的面先濾波、再切出中央 512x512
的結果(在端部外側有真實資料的狀態下計算的答案)。dx=1,λc=80,
端部帶 = 外周 40 個樣本,該處真值的 rms 為 0.1932。
面的狀態 end_effect 端部帶的 rms 誤差 中央部的 rms 誤差
有傾斜 wrap 4.3883 (2272 %) 0.0e+00 (0.000 %)
有傾斜 mirror 0.1765 ( 91 %) 0.0e+00 (0.000 %)
已去傾斜 wrap 0.0111 ( 5.7 %) 4.4e-15 (0.000 %)
已去傾斜 mirror 0.0115 ( 5.9 %) 4.4e-15 (0.000 %)
(任意) reject —— 不回傳 —— 0.0e+00 (0.000 %)
可以讀出 4 點:
1. 端部處理只在端部起作用。 中央部無論哪種都與真值嚴格一致(核碰不到端部,這是理所當然的,但做了確認)。
2. 最糟的組合是「保留傾斜直接 wrap」 —— 端部誤差達到真值本身的 23 倍。因為假定左端的延續就是右端,在高度不同的 2 條邊的接縫處會出現台階。
3. 只要去掉傾斜,wrap 與 mirror 就沒有差別(5.7 % 對 5.9 %,wrap 略好)。正確的說法不是「循環卷積總是不好」,而是「不去傾斜就使用才不好」。
4. reject 的代價是面積。512x512、λc=80 時捨棄 41.4 % (剩下 392x392;截斷為 ±λc/2 時是 28.8 %)。捨棄比例按 1 - (1 - 1.5 λc/L)² 增大,λc 超過評定長度的 1/6 時將損失近一半。
★ 傳遞率是否符合標準(實測,λc=80,dx=1,用投影量測整數週期的正弦。2026-10-18 已修正)
λ 波紋度側 ISO 標準值 差 (修正前的波紋度側 / 差)
16 0.000030 0.000000 +3.0e-05 0.000806 / +8.1e-04
32 0.013094 0.013139 -4.5e-05 0.017206 / +4.1e-03
40 0.062544 0.062500 +4.4e-05 0.058676 / -3.8e-03
64 0.338531 0.338564 -3.3e-05 0.342826 / +4.3e-03
80 0.500012 0.500000 +1.2e-05 0.509549 / +9.6e-03 ← λc
128 0.762894 0.762799 +9.5e-05 0.772150 / +9.4e-03
256 0.934601 0.934550 +5.1e-05 0.937944 / +3.4e-03
修正前,在截止波長本身處不是 0.5000 而是 0.5095(相對 +1.9 %)。原因不是常數 α(√(ln2/π)),
也不是取樣後的歸一化,而是標準文面中的截斷 ±λc/2(= 2.67 σ):尾部的 0.8 % 被丟掉,
再把剩餘部分歸一化為 1,低通的份額就變大了。
把截斷放寬到 ±0.75 λc(4 σ)後,λc 處為 0.500012,全部波長的最大誤差降到 9.5e-05(上表)。
代價是 reject 捨棄的端部帶變為 1.5 倍。粗糙度與波紋度之和在兩種情況下都與輸入嚴格一致。
fail-closed(失敗即拒絕)
• kind 不是 "gaussian" / end_effect 不是已知的 3 種之一。
• lambda_c 與 lambda_s 都是 None(什麼也不做的呼叫)。
• 截止低於 Nyquist 波長 2*pitch,或超過評定長度。
• lambda_s >= lambda_c(頻帶為空)。
• "reject" 削去後陣列一點不剩。
• 範例資料目錄(下載 URL / 授權) —— 2-D 用 skimage.data(BSD/公有領域)加合成圖,3-D 給出真實資料源(Stanford/PDS 等)的下載 URL。
• 運算子來歷與參考文獻 —— 該運算子族所依據的研究/方法出處。
• 演算法的正典(作者、年份)與用途見上面的族使用指南。
• poc_robust_profile_filter — py -3.11 examples/poc_robust_profile_filter.py
• poc_surface_roughness — py -3.11 examples/poc_surface_roughness.py
depth 作為輸入)surface_form_remove · robust_gaussian_surface · surface_params · surface_psd
prepare)surface_form_remove · robust_gaussian_profile · robust_spline_profile · robust_gaussian_surface
*Provenance: roughness.py — ROUGHNESS 運算子登記表。本條目由 tools/opdocs.py md 自動產生(請勿手動編輯)。*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.