register_fpfh — 3D feature_register op

• Data kinds: points × points → pose

• Call: 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') (implementation को सीधे call करना हो तो 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'), registry से लेना हो तो ops3d.get("register_fpfh"))

उपयोग

FPFH descriptor + RANSAC से initial guess के बिना rigid alignment (R,t) का अनुमान लगाता है।

2D के Harris/SIFT के समतुल्य sparse feature matching का 3D संस्करण। दोनों cloud को FPFH descriptor से दर्शाया जाता है, descriptor space में nearest neighbour से correspondence बनाए जाते हैं (mutual nearest neighbour + Lowe ratio से filter), और RANSAC outlier के प्रति robust rigid pose हल करता है। dense matching (NCC/Hough) या PCA से अलग, इसका मूल्य यह है कि बड़े rotation (50-70°) +translation + आंशिक overlap में भी बिना प्रारंभिक अनुमान के pose देता है। प्राप्त (R,t) को ICP के प्रारंभिक मान (coarse init) के रूप में देने पर surface accuracy तक कसा जा सकता है (dst ≈ src @ R.T + t की ICP convention)।

Pipeline:

1) voxel downsampling (स्वतंत्र रूप से sample किए गए 2 cloud के neighbourhood को एक साझा resolution पर लाता है। FPFH correspondence की सही-दर को बहुत प्रभावित करने वाला अनिवार्य preprocessing)।

2) normal estimation (local PCA)। src_normals/dst_normals दिए जाएँ तो वही उपयोग होते हैं।

3) FPFH descriptor (SPFH → दूरी-भारित संयोजन)।

4) descriptor NN matching (mutual + ratio)।

5) RANSAC: 3 point sample → edge-length संगति prefilter → Kabsch → सभी points की fitness से scoring (src के सभी points को transform करने पर जिनका dst nearest neighbour threshold के भीतर आए उनका अनुपात)। केवल correspondence (~100 points) पर scoring गलत pose पर अटक जाती है, इसलिए सभी points की fitness से इसे robust बनाया जाता है।

6) सर्वश्रेष्ठ pose के correspondence inliers पर फिर से fit।

Args:

src (N,3), dst (M,3): register किए जाने वाले 2 point cloud (numpy/torch)।

src_normals, dst_normals ((N,3)/(M,3) or None): पहले से दिए normal। None हो तो भीतर अनुमान

(पर voxel_size>0 होने पर निर्देशांक बदलते हैं, इसलिए हमेशा फिर से अनुमान)।

voxel_size (float or None): downsampling की edge length। None हो तो dst resolution ×2.5 अपने आप लिया जाता है।

0/None पर निष्क्रिय (raw point cloud जैसा है वैसा; स्वतंत्र sampling में अनुशंसित नहीं)।

normal_k (int): normal estimation के पड़ोसियों की संख्या।

feature_k (int): FPFH के पड़ोसियों की संख्या (जितनी बड़ी, descriptor उतना स्थिर और विभेदक; लगभग 60 अनुशंसित)।

n_bins (int): प्रति 1 feature histogram bin (descriptor का आयाम = 3*n_bins)।

ransac_iters (int): RANSAC iterations की संख्या।

inlier_thr (float or None): inlier distance threshold। None हो तो (downsampling के बाद) resolution ×3।

edge_sim (float): triple के edge-length अनुपात की सहनशीलता (0<edge_sim<=1, 1 के जितना पास उतना सख्त)।

mutual (bool): mutual nearest neighbour filter। ratio (float or None): Lowe ratio।

seed (int): RANSAC का random seed (restart पर बदलें)। device (str): लौटाए गए tensor का device।

Returns:

R (3,3) torch.Tensor (device पर), t (3,) torch.Tensor,

info dict: {"n_corr" (correspondence की संख्या), "inliers" (inlier की संख्या), "inlier_ratio",

"fitness" (सभी points की fitness = restart चुनने का मापदंड), "rmse" (inlier RMSE),

"inlier_thr", "src_corr","dst_corr" (correspondence index)}।

ध्यान दें (honest): FPFH एक coarse registration है; स्वतंत्र sampling + noise + आंशिक overlap की कठिन स्थितियों में कुछ डिग्री की rotation त्रुटि बनी रहती है (मापा गया: 62° rotation, overlap ~64%, noise 0.5× resolution पर RANSAC के बाद median ~4.4°, ~90% <8° हैं, बाकी ~10% 8-9° की सीमा पर। ICP से कसने पर 100% <8° और median ~0.5°)। noise जब point spacing (resolution) के बराबर या अधिक हो जाता है, तो normal और कोणीय feature टूट जाते हैं और descriptor अपनी विभेदन क्षमता खो देता है (मापा गया: noise ≥1.0× resolution पर सफलता दर घटती है)। RANSAC random है, इसलिए व्यवहार में कुछ बार restart करें और सबसे बड़े info["fitness"] वाला परिणाम लें।

पृष्ठभूमि guides (इस op के पीछे की physics और conventions)

• blas_threads_and_memory — Matrix decompositions धीमे क्यों हैं — BLAS threads, caches, memory layout

संदर्भ (sample data, साहित्य)

• Sample data catalog (DL URL / license) — 2-D के लिए skimage.data (BSD/public) + synthetic, 3-D के लिए real data sources (Stanford/PDS आदि) के DL URL।

• Operators का स्रोत और संदर्भ — इस op family के मूल research/methods के स्रोत।

चलाए जा सकने वाले उदाहरण (verified samples जो सच में यह op call करते हैं)

• feature_register — py -3.11 examples_3d/feature_register.py

वे अगले ops जिनसे type जुड़ता है (pose को input के रूप में लेते हैं)

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

इसी category के (feature_register)

harris3d_keypoints · iss_keypoints · compute_fpfh · shot_descriptor · register_spin · register_shot


*Provenance: feat_fpfh.py — 3D operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*

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