pnp_ransac — 3D pose_estimation op

• Data kinds: points × keypoints → pose

• Call: import fullseye as fs; fs.ledger.pnp_ransac(points_3d, points_2d, K, thresh=2.0, iters=300, seed=0) (to call the implementation directly, import pnp3d; pnp3d.pnp_ransac(points_3d, points_2d, K, thresh=2.0, iters=300, seed=0); from the registry, ops3d.get("pnp_ransac"))

Usage

Outlier-robust PnP (RANSAC plus a final DLT refit). → (R, t, inlier_mask, info).

DLT on minimal samples of 6 points (no refinement) → maximise the inliers with reprojection error < thresh → refit with pnp_pose (with refinement) on all inliers.

Raises ValueError: points_2d is not (N,2) / points_3d is not (N,3) /

point counts mismatch / fewer than 6 points / non-finite.

Arguments:

• thresh: reprojection error threshold [px] (Euclidean distance, default 2.0). Errors below this count as inliers.

• iters: number of iterations (default 300). There is no early termination; it always runs this many times. Each iteration draws 6 points without replacement and solves only the initial pose (degenerate samples are discarded and the next is tried).

• seed: passed to numpy.random.default_rng(seed). With the same input and seed the result is reproducible.

Returns: R (3,3), t (3,) (convention Xc = R X + t), inlier_mask bool (N,), info dict. The keys of info are n_inliers / inlier_ratio / iters / rms (reprojection RMS [px] of the final pose, over the inlier set).

• When the best sample has fewer than 6 inliers, it enters a fallback that re-solves with all points, and info["fallback"] = True is attached. In that case inlier_mask is the actual value recounted with the fallback pose, so inlier_ratio may be returned still small (consensus is not fabricated). If the fallback also fails, ValueError.

• The inlier-count comparison updates only on "more", so on a tie the sample found first remains.

• The final pose is a refit on all inliers (with LM refinement).

• Raises ValueError: invalid shape / fewer than 6 points / point counts mismatch / non-finite (the same entry checks as dlt_pose).

• Evaluate with reprojection_error; compare with GT using pose_error.

References (sample data, literature)

• 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.

Runnable examples (verified samples that actually call this op)

• pnp_pose_outliers — py -3.11 examples_3d/pnp_pose_outliers.py

• pose_estimation — py -3.11 examples_3d/pose_estimation.py

Ops the type connects to (they accept pose as input)

fuse_to_voxel · pose_error · bundle_adjust · mean_reprojection_error · optimize_pose_graph · relative_pose · mean_edge_error · rotation_translation_error

Same category (pose_estimation)

dlt_pose · reprojection_error


*Provenance: pnp3d.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.