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 → 以全点 fitness (将 src 全部点变换后,其 dst 最近邻落在阈值内的比例)评分。只用对应(~100点) 评分容易固着于错误位姿,因此用全点 fitness 使其鲁棒。
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"(全点 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 线程、缓存、内存布局
• 示例数据目录(下载 URL / 许可证) —— 2-D 用 skimage.data(BSD/公有领域)加合成图,3-D 给出真实数据源(Stanford/PDS 等)的下载 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 算子登记表。本条目由 tools/opdocs.py md 自动生成(请勿手工编辑)。*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.