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" 로 깎은 뒤 배열이 남지 않는다.
• 샘플 데이터 카탈로그(DL URL / 라이선스) —— 2-D 는 skimage.data(BSD/public)+ 합성, 3-D 는 실데이터 소스(Stanford/PDS 등)의 DL 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 연산자 레지스트리. 이 op 노트는 tools/opdocs.py md 가 자동 생성합니다(직접 편집하지 마세요).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.