feature_register op• Data kinds: points × points → pose
• Call: import fullseye as fs; fs.ledger.register_shot(src, dst, radius=None, normal_k=16, ratio=0.9, ransac_iters=2000, inlier_thr=None, refine_icp=True, max_kp=400, device='cpu', seed=0) (to call the implementation directly, import feat_shot; feat_shot.register_shot(src, dst, radius=None, normal_k=16, ratio=0.9, ransac_iters=2000, inlier_thr=None, refine_icp=True, max_kp=400, device='cpu', seed=0); from the registry, ops3d.get("register_shot"))
Sparse feature matching with SHOT descriptors plus RANSAC rigid pose estimation (the whole pipeline).
Without an initial estimate, puts 2 point clouds with large rotation and partial overlap into correspondence and returns the rigid transform (rotation R + translation t). Unlike dense matching (NCC/Hough/PCA), it sets up a local reference frame (LRF) at each ISS keypoint, describes it with histograms of normal angles over spherically partitioned cells (SHOT) → matches with the Lowe ratio test + mutual nearest neighbour → estimates the pose robustly to outliers with RANSAC. The obtained pose can also supply the coarse initial value (coarse init) for ICP.
LRF sign ambiguity: the eigenvectors of the distance-weighted covariance have undetermined signs, so each axis (x=largest, z=smallest eigenvalue) is aligned to the majority of the projections of the neighbour vectors (p_i-p) (Tombari's sign rule), and y=z×x builds a right-handed system. Point normals are also unified by the same rule to point away from the neighbourhood mass (locally outward), so they are covariant with rotation and stable under partial overlap. Applying the same rule to both point clouds secures the repeatability of the descriptor.
Args:
src, dst: (N,3)/(M,3) point clouds (numpy or torch). src is aligned to dst.
radius: SHOT support radius. None uses 0.15 times the bbox diagonal of each point cloud itself (the smaller one)
(the joint bbox is not used, because translation inflates its diagonal and throws off the scale).
normal_k: knn count for normal estimation.
ratio: Lowe ratio-test threshold (smaller is stricter).
ransac_iters: number of RANSAC iterations.
inlier_thr: RANSAC inlier distance. None uses 0.03 times the bbox diagonal.
refine_icp: if True, refines the obtained pose with Trimmed ICP (icp_point2point_3d) using it as the initial value.
max_kp: upper limit on keypoints.
device: torch device ("cpu" etc.). SVD/ICP are solved on it.
seed: RANSAC random seed.
Returns:
R: (3,3) numpy. Rotation satisfying dst ≈ src @ R.T + t (same convention as icp).
t: (3,) numpy. Translation.
info: dict. "n_kp_src","n_kp_dst","n_matches","n_inliers","inlier_ratio",
"icp_rmse" (with refine_icp),"ok" (True=estimation succeeded; fewer than 4 inliers is
treated as unreliable and returns False + the identity transform).
• blas_threads_and_memory — Why matrix decompositions are slow — BLAS threads, caches, memory layout
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• feature_register — py -3.11 examples_3d/feature_register.py
pose as input)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_fpfh
*Provenance: feat_shot.py — 3D operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.