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)

사용법

격자 그대로 평면 / 2차 곡면을 제거한다. (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 도 동시에 망가진다.

깊이 3 µm 흠집 4 개를 한쪽에 몰아 둔 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 패밀리 가이드

참고(샘플 데이터·문헌)

• 샘플 데이터 카탈로그(DL URL / 라이선스) —— 2-D 는 skimage.data(BSD/public)+ 합성, 3-D 는 실데이터 소스(Stanford/PDS 등)의 DL 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 연산자 레지스트리. 이 op 노트는 tools/opdocs.py md 가 자동 생성합니다(직접 편집하지 마세요).*

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