feature_register op• Datenarten: points × points → pose
• Aufruf: 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') (die Implementierung direkt: 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'); aus dem Register: ops3d.get("register_fpfh"))
Schätzt die starre Ausrichtung (R,t) ohne Startschätzung mit FPFH-Deskriptoren und RANSAC.
Die 3D-Version des spärlichen Feature-Matchings, entsprechend Harris/SIFT in 2D. Beide Wolken werden durch FPFH-Deskriptoren dargestellt, Korrespondenzen werden über den nächsten Nachbarn im Deskriptorraum gebildet (gefiltert mit gegenseitigem nächstem Nachbarn + Lowe ratio), und RANSAC löst eine gegen Ausreißer robuste Starrkörperpose. Anders als dichtes Matching (NCC/Hough) oder PCA liegt sein Wert darin, dass es auch bei großer Rotation (50-70°) +Translation + teilweiser Überlappung ohne Anfangsschätzung eine Pose liefert. Das erhaltene (R,t) kann ICP als Anfangswert (coarse init) übergeben werden, um auf Oberflächengenauigkeit nachzuschärfen (ICP-Konvention dst ≈ src @ R.T + t).
Pipeline:
1) voxel-Downsampling (bringt die Nachbarschaften von 2 unabhängig abgetasteten Wolken auf eine gemeinsame Auflösung; eine unverzichtbare Vorverarbeitung, die die Trefferquote der FPFH-Korrespondenzen stark beeinflusst).
2) Normalenschätzung (lokale PCA). Werden src_normals/dst_normals übergeben, werden diese verwendet.
3) FPFH-Deskriptor (SPFH → distanzgewichtete Kombination).
4) Deskriptor-NN-Matching (mutual + ratio).
5) RANSAC: 3-Punkt-Stichprobe → Vorfilter auf edge-length-Konsistenz → Kabsch → Bewertung per Fitness über alle Punkte (Anteil aller transformierten src-Punkte, deren nächster dst-Nachbar innerhalb des Schwellwerts liegt). Eine Bewertung nur über die Korrespondenzen (~100 Punkte) bleibt leicht an falschen Posen hängen, daher macht die Fitness über alle Punkte es robust.
6) Neuanpassung mit den Korrespondenz-Inliern der besten Pose.
Argumente:
src (N,3), dst (M,3): die 2 zu registrierenden Punktwolken (numpy/torch).
src_normals, dst_normals ((N,3)/(M,3) or None): vorgegebene Normalen. None bedeutet interne Schätzung
(bei voxel_size>0 ändern sich jedoch die Koordinaten, daher wird immer neu geschätzt).
voxel_size (float or None): Kantenlänge des Downsamplings. None übernimmt automatisch dst-Auflösung ×2.5.
0/None deaktiviert es (rohe Punktwolken unverändert; bei unabhängiger Abtastung nicht empfohlen).
normal_k (int): Nachbarzahl für die Normalenschätzung.
feature_k (int): Nachbarzahl für FPFH (je größer, desto stabiler und trennschärfer der Deskriptor; etwa 60 empfohlen).
n_bins (int): Histogramm-Bins pro 1 Merkmal (Deskriptordimension = 3*n_bins).
ransac_iters (int): Anzahl der RANSAC-Iterationen.
inlier_thr (float or None): Inlier-Distanzschwellwert. None nimmt (nach dem Downsampling) Auflösung ×3.
edge_sim (float): Toleranz des Kantenlängenverhältnisses von Tripeln (0<edge_sim<=1; je näher an 1, desto strenger).
mutual (bool): Filter für gegenseitige nächste Nachbarn. ratio (float or None): Lowe ratio.
seed (int): Zufalls-Seed für RANSAC (beim restart ändern). device (str): device der zurückgegebenen Tensoren.
Rückgabewert:
R (3,3) torch.Tensor (auf device), t (3,) torch.Tensor,
info dict: {"n_corr" (Anzahl Korrespondenzen), "inliers" (Anzahl Inlier), "inlier_ratio",
"fitness" (Fitness über alle Punkte = Kriterium zur Auswahl zwischen restarts), "rmse" (Inlier-RMSE),
"inlier_thr", "src_corr","dst_corr" (Korrespondenz-Indizes)}.
Hinweis (honest): FPFH ist eine coarse registration; unter den schweren Bedingungen unabhängige Abtastung + Rauschen + teilweise Überlappung bleibt ein Rotationsfehler von einigen Grad (gemessen: bei 62° Rotation, Überlappung ~64% und Rauschen 0.5× Auflösung nach RANSAC Median ~4.4°, ~90% liegen <8°, die restlichen ~10% an der Grenze von 8-9°. Nach Nachschärfen mit ICP liegen 100% bei <8° mit Median ~0.5°). Liegt das Rauschen in der Größenordnung des Punktabstands (Auflösung) oder darüber, brechen Normalen und Winkelmerkmale zusammen und der Deskriptor verliert seine Trennschärfe (gemessen: bei Rauschen ≥1.0× Auflösung sinkt die Erfolgsrate). RANSAC ist zufallsbasiert, daher sollte man im Praxisbetrieb einige restarts machen und das Ergebnis mit dem größten info["fitness"] nehmen.
• blas_threads_and_memory — Warum Matrixzerlegungen langsam sind — BLAS-Threads, Caches, Speicherlayout
• Katalog der Beispieldaten (Download-URLs / Lizenzen) — 2-D nutzt skimage.data (BSD/Public Domain) plus synthetische Bilder, 3-D nennt Download-URLs echter Datenquellen (Stanford, PDS, …).
• Herkunft und Literatur der Operatoren — die Quellen der Forschung/Verfahren, auf denen diese Operatorfamilie beruht.
• feature_register — py -3.11 examples_3d/feature_register.py
pose als Eingabe)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. Diese Notiz wird von tools/opdocs.py md erzeugt (nicht von Hand bearbeiten).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.