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') (to call the implementation directly, 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'); from the registry, ops3d.get("register_fpfh"))
• GPU: none (CPU reference implementation only)
Estimate the rigid alignment (R,t) without an initial guess using FPFH descriptors and RANSAC.
A 3D version of sparse feature matching, equivalent to the 2D Harris/SIFT. Both clouds are represented by FPFH descriptors, Create a correspondence using the nearest neighbors in the descriptor space (mutual nearest neighbors + filter by Lowe ratio), and use RANSAC to Solving rigid body poses that are robust to outliers. Unlike close match (NCC/Hough) and PCA, large rotation (50-70°) The value is that the pose can be determined without initial estimation even with +translation + partial overlap. The obtained (R,t) is the initial value of ICP (coarse init) tightens to surface precision (ICP convention of dst ≈ src @ R.T + t).
Pipeline:
1) Voxel downsampling (independent sampling 2 Align the vicinity of clouds to a common resolution. (Required preprocessing that greatly affects the correct response rate of FPFH).
2) Normal estimation (local PCA). If you pass src_normals/dst_normals, it will be used.
3) FPFH descriptor (SPFH → distance weight synthesis).
4) Descriptor NN match (mutual + ratio).
5) RANSAC: 3-point sample → edge-length matched prefilter → Kabsch → All-point fitness (src convert all points and dst the rate at which the nearest neighbor falls within the threshold). Compatible (~100 points) only Scoring tends to be fixed on incorrect postures, so it is made robust with all-point fitness.
6) Refit with the corresponding inlier for the best posture.
Arguments:
src (N,3), dst (M,3): Two point groups to align (numpy/torch).
src_normals, dst_normals ((N,3)/(M,3) or None): Prior normals. If None, internal estimation
(However, when voxel_size>0, the coordinates change, so it is always re-estimated).
voxel_size (float or None): Downsample side length. Automatically adopts DST resolution x 2.5 with None.
Disable with 0 (remains raw point cloud; not recommended for independent sampling).
normal_k (int): Number of neighbors for normal estimation.
feature_k (int): Number of neighbors of FPFH (the larger the number, the more stable and discriminative the descriptor is. Around 60 is recommended).
n_bins (int): Number of histogram bins per feature (descriptor dimension = 3*n_bins).
ransac_iters (int): RANSAC iteration number.
inlier_thr (float or None): Inlier distance threshold. None (after downsampling) resolution x 3.
edge_sim (float): Tolerance of triple edge length ratio (0<edge_sim<=1, closer to 1 is stricter).
mutual (bool): Mutual nearest neighbor filter. ratio (float or None): Lowe ratio.
seed (int): RANSAC random number seed (change at restart). device (str): device of return tensor.
Return value:
R (3,3) torch.Tensor(on device), t (3,) torch.Tensor,
info dict: {"n_corr"(number of correspondences), "inliers"(number of inliers), "inlier_ratio",
"fitness" (all-point fitness = restart selection index), "rmse" (inlier RMSE),
"inlier_thr", "src_corr", "dst_corr" (corresponding index)}.
Note (honest): FPFH is coarse registration, independent sampling + noise + partial overlap Under difficult conditions, a rotation error of several degrees remains (actual measurement: 62° rotation, overlap ~64%, noise 0.5 × resolution) Post-RANSAC median ~4.4°, ~90% <8°, remaining ~10% bordering 8-9°. 100% when tightened with ICP <8°, median ~0.5°). When the noise becomes equal to or higher than the point spacing (resolution), the normal and corner features become The collapsed descriptor loses its discriminative power (actual measurement: success rate decreases when noise ≥ 1.0 × resolution). RANSAC is random selection Therefore, in actual operation, it is recommended to restart several times and take the maximum result info["fitness"].
• 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_shot
*Provenance: feat_fpfh.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.