feature_register op• Data kinds: points × points → pose
• Call: import fullseye as fs; fs.ledger.register_spin(src, dst, device='cpu', n_keypoints=220, normal_k=18, support_radius=None, n_alpha=16, n_beta=16, support_angle_deg=60.0, lowe_ratio=0.85, ransac_iters=4000, inlier_thr=None, min_inliers=8, seed=0) (to call the implementation directly, import feat_spin; feat_spin.register_spin(src, dst, device='cpu', n_keypoints=220, normal_k=18, support_radius=None, n_alpha=16, n_beta=16, support_angle_deg=60.0, lowe_ratio=0.85, ransac_iters=4000, inlier_thr=None, min_inliers=8, seed=0); from the registry, ops3d.get("register_spin"))
Sparse-feature rigid alignment without an initial guess, using Spin Image descriptors and RANSAC.
Registers 2 point clouds src (N,3), dst (M,3) without any prior on the initial pose. Using each point's normal (local PCA, sign unified outward from the centroid = invariant under rigid transforms) as the axis, neighbouring points are "spun" and accumulated into a 2D histogram of (α=distance from the axis, β=height along the axis), giving the Spin Image descriptor (Johnson & Hebert 1997) built per keypoint; matches are the nearest neighbours in descriptor space (filtered by the Lowe ratio test), and RANSAC (3-point minimal sample + Kabsch) estimates a rigid transform robust to outliers. Unlike dense matching (NCC/phase correlation/Hough) or PCA principal-axis alignment, it can recover the pose from local-feature correspondences even under large rotation + partial overlap, so it serves as the front end of ICP (supplying the coarse init). The returned pose follows the convention dst ~= src @ R.T + t (= R @ src_i + t) (same as icp_point2point_3d).
Args:
src: (N,3) moving point cloud (numpy.ndarray or torch.Tensor).
dst: (M,3) fixed (reference) point cloud.
device: torch device ("cpu" etc.). The SVD/final pose are solved on it.
n_keypoints: number of keypoints extracted from each point cloud (evenly spaced subsampling).
normal_k: number of neighbouring points used for normal estimation (local PCA).
support_radius: support radius of the Spin Image. None uses 0.30 times the bbox diagonal of each point cloud measured separately (the larger one)
(measured separately, not on the union, so that the unknown translation does not contaminate it).
n_alpha, n_beta: number of (α, β) bins of the Spin Image (the descriptor has n_alpha*n_beta dimensions).
support_angle_deg: support-angle threshold (degrees). Only support points whose normal is within this angle of the keypoint normal
are accumulated (robust to occlusion and back faces). >=90 disables it.
lowe_ratio: Lowe ratio-test threshold (only correspondences with d1 < ratio*d2 are kept).
ransac_iters: number of RANSAC iterations.
inlier_thr: RANSAC inlier distance threshold. None uses 0.04 times the bbox diagonal.
min_inliers: minimum number of inliers for a pose to count as valid (the ok decision).
seed: RANSAC random seed.
Returns:
R: (3,3) torch.Tensor. Rotation satisfying dst ~= src @ R.T + t.
t: (3,) torch.Tensor. Translation.
info: dict. "n_matches" (correspondences passing the ratio test), "inliers" (final RANSAC),
"inlier_ratio", "rmse" (RMSE over the inliers), "support_radius",
"inlier_thr", "ok" (whether at least min_inliers).
Notes:
• The descriptor depends on the normal sign. Unifying the sign outward from the centroid works for shapes whose normals are roughly radial and where the sign of n·(p-centroid) is stable (lumpy closed surfaces etc.). On shapes with many regions where n·(p-centroid)≈0, such as thin plates or tubes, the sign can flip between the 2 clouds.
• Regions of spatially uniform curvature, such as planes and spheres, give degenerate descriptors and the ratio test removes their correspondences (unsuitable for featureless shapes). Once overlap drops below roughly 60% the success rate falls sharply, and on failure RANSAC can lock onto a geometrically consistent but wrong solution, giving a catastrophic error (combining it with the ok / inlier_ratio gates is recommended).
• 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_fpfh · register_shot
*Provenance: feat_spin.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.