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 的理由
卷積在端部需要核半徑 λc/2 範圍內「不存在之處的資料」。
標準(ISO 16610-28)以評定區域兩端各削去 λc/2 為前提。
• "reject"(預設)—— 捨棄兩端各 ceil(λc/2/pitch) 個樣本。輸出是比輸入小的陣列。被捨棄的區域「沒有量測」,所以這是唯一不說謊的選項。
• "mirror" —— 以鏡像延拓並回傳相同形狀。假定面在端部是偶函數。
• "wrap" —— 循環卷積(與 FFT 相同)。假定左端的延續就是右端。
實測。真值是對 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 時捨棄 28.8 % (剩下 432x432)。捨棄比例按 1 - (1 - λc/L)² 增長,因此 λc 超過評定長度的 1/4 時會失去近一半。
★ 傳遞率是否符合標準(實測,λc=80,dx=1,用投影量測整數週期的正弦)
λ 波紋度側 ISO 標準值 差
16 0.000806 0.000000 +8.1e-04
32 0.017206 0.013139 +4.1e-03
40 0.058676 0.062500 -3.8e-03
64 0.342826 0.338564 +4.3e-03
80 0.509549 0.500000 +9.6e-03 ← 最大
128 0.772150 0.762799 +9.4e-03
256 0.937944 0.934550 +3.4e-03
在截止波長本身處不是 0.5000 而是 0.5095(相對 +1.9 %)。原因是
標準規定的截斷 ±λc/2(= 2.67 σ),使尾部的 0.8 % 被丟掉。
若把截斷放寬到 4 σ(±0.75 λc),最大誤差降到 9e-05
(實測),但 reject 捨棄的帶會變成 1.5 倍。選擇了遵循標準、並寫明偏差的做法。粗糙度與波紋度之和始終與輸入嚴格一致
(上表中 roughness + waviness = 1.000000),所以只是分配的分界
偏移 1.9 %,能量既不會消失也不會憑空出現。
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_surface_roughness — py -3.11 examples/poc_surface_roughness.py
depth 作為輸入)surface_form_remove · surface_params · surface_psd
prepare)*Provenance: roughness.py — ROUGHNESS 運算子登記表。本條目由 tools/opdocs.py md 自動產生(請勿手動編輯)。*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.