register_fpfh — 3D feature_register op

• 데이터 종류: points × points → pose

• 호출: import fullseye as fs; fs.ledger.register_fpfh(src, dst, src_normals=None, dst_normals=None, voxel_size=None, normal_k=16, feature_k=60, n_bins=11, ransac_iters=8000, inlier_thr=None, edge_sim=0.9, mutual=True, ratio=0.95, seed=0, device='cpu')(구현을 직접 호출하려면 import feat_fpfh; feat_fpfh.register_fpfh(src, dst, src_normals=None, dst_normals=None, voxel_size=None, normal_k=16, feature_k=60, n_bins=11, ransac_iters=8000, inlier_thr=None, edge_sim=0.9, mutual=True, ratio=0.95, seed=0, device='cpu'), 원장에서 가져오려면 ops3d.get("register_fpfh"))

사용법

FPFH 기술자 + RANSAC 으로 초기 추정 없이 강체 정합 (R,t) 를 추정합니다.

2D의 Harris/SIFT에 해당하는 희소 feature 매칭의 3D 버전. 두 점군을 FPFH 기술자로 나타내고, 기술자 공간의 최근접으로 대응을 잇고(상호 최근접 + Lowe ratio로 필터), RANSAC으로이상값에 강건한 강체 자세를 푼다. 밀집 매칭(NCC/Hough)이나 PCA와 달리, 대회전(50-70°) +병진+부분 중첩에서도 초기 추정 없이 자세를 낼 수 있다는 것이 가치. 얻은 (R,t)를 ICP의 초기값(coarse init)으로 넘기면 표면 정밀도까지 조일 수 있다(dst ≈ src @ R.T + t의 ICP 관례).

파이프라인:

1) voxel 다운샘플(독립 샘플링된 2 개 점군의 근방을 공통 해상도로 맞춘다. FPFH의 대응 정답률을 크게 좌우하는 필수 전처리).

2) 법선 추정(국소 PCA). src_normals/dst_normals를 넘기면 그것을 쓴다.

3) FPFH 기술자(SPFH→거리 가중 합성).

4) 기술자 NN 매칭(mutual + ratio).

5) RANSAC: 3 점 샘플 → edge-length 정합 사전 필터 → Kabsch → 전체 점 피트니스 (src 전체 점을 변환해 dst 최근접이 임계값 안에 드는 비율)로 채점. 대응(~100점)만으로의채점은 잘못된 자세에 고착되기 쉬우므로 전체 점 피트니스로 강건화한다.

6) 최선 자세의 대응 인라이어로 재피팅.

인수:

src (N,3), dst (M,3): 위치 맞춤할 2 개 점군(numpy/torch).

src_normals, dst_normals ((N,3)/(M,3) or None): 사전 법선. None이면 내부 추정

(단, voxel_size>0일 때는 좌표가 바뀌므로 항상 재추정).

voxel_size (float or None): 다운샘플 변 길이. None이면 dst 해상도×2.5를 자동 채택.

0/None이면 무효화(원시 점군 그대로. 독립 샘플링에서는 비권장).

normal_k (int): 법선 추정의 근방 수.

feature_k (int): FPFH의 근방 수(클수록 기술자가 안정적·변별적. 60 전후를 권장).

n_bins (int): 특징 1 개당 히스토그램 빈 수(기술자 차원 = 3*n_bins).

ransac_iters (int): RANSAC 반복 수.

inlier_thr (float or None): 인라이어 거리 임계값. None이면 (다운샘플 후) 해상도×3.

edge_sim (float): 삼조의 변 길이 비 허용치(0<edge_sim<=1, 1에 가까울수록 엄격).

mutual (bool): 상호 최근접 필터. ratio (float or None): Lowe ratio.

seed (int): RANSAC 난수 시드(restart 시 바꾼다). device (str): 반환 텐서의 device.

반환값:

R (3,3) torch.Tensor(device 위), t (3,) torch.Tensor,

info dict: {"n_corr"(대응 수), "inliers"(인라이어 수), "inlier_ratio",

"fitness"(전체 점 피트니스=restart 선택 지표), "rmse"(인라이어 RMSE),

"inlier_thr", "src_corr","dst_corr"(대응 index)}.

주의(honest): FPFH는 coarse registration이며, 독립 샘플링+잡음+부분 중첩의 어려운 조건에서는 회전 오차가 수 도 남는다(실측: 62°회전·중첩~64%·잡음0.5×해상도에서 RANSAC 후 중앙값 ~4.4°, ~90%가 <8°, 나머지 ~10%는 8-9°의 경계. ICP로 조이면 100% 가 <8°·중앙값 ~0.5°). 잡음이 점 간격(해상도) 수준 이상이 되면 법선·각 특징이무너져 기술자가 변별력을 잃는다(실측: 잡음≥1.0×해상도에서 성공률이 저하). RANSAC은 무작위이므로 실운용에서는 몇 번 restart하여 info["fitness"]가 최대인 결과를 채택하면 좋다.

배경 지식 가이드(이 연산자 앞에 있는 물리·규약)

• blas_threads_and_memory — 행렬 분해가 느린 이유 — BLAS 스레드·캐시·메모리 배치

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

• 샘플 데이터 카탈로그(DL URL / 라이선스) —— 2-D 는 skimage.data(BSD/public)+ 합성, 3-D 는 실데이터 소스(Stanford/PDS 등)의 DL URL.

• 연산자의 내력·참고문헌 —— 이 연산자 족의 바탕이 된 연구/기법의 출처.

실행 가능한 예제(이 연산자를 실제로 호출하는 검증된 샘플)

• feature_register — py -3.11 examples_3d/feature_register.py

타입이 이어지는 다음 연산자(pose 를 입력으로 받는 것)

fuse_to_voxel · pose_error · bundle_adjust · mean_reprojection_error · optimize_pose_graph · relative_pose · mean_edge_error · rotation_translation_error

같은 카테고리(feature_register)

harris3d_keypoints · iss_keypoints · compute_fpfh · shot_descriptor · register_spin · register_shot


*Provenance: feat_fpfh.py — 3D 연산자 레지스트리. 이 op 노트는 tools/opdocs.py md 가 자동 생성합니다(직접 편집하지 마세요).*

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