annotate3d op• Data kinds: points → table
• Call: import fullseye as fs; fs.ledger.annotate3d_project(points, pose, K, depth=None, shape=None, occlusion_tol=0.01) (to call the implementation directly, import annotate3d; annotate3d.annotate3d_project(points, pose, K, depth=None, shape=None, occlusion_tol=0.01); from the registry, ops3d.get("annotate3d_project"))
Returns a table (dict): pixel coordinates, forward distance and in-frame/occluded verdicts for 3-D points (project_anchors).
A "projection only" op that does no drawing. It returns, as a table, the very tests that all annotate3d drawing ops use internally, so use it for your own plots, numerical verification, and "is this point visible?" branching.
Projection (closed form, same convention as render3d): X_c = R X + t (pose is a 4x4 object→camera, or a 2-tuple (R, t)). The camera looks along local -Z, so the forward distance is z = -X_c[2]. Pixels are u = fx X_c[0]/z + skew X_c[1]/z + cx, v = cy - fy X_c[1]/z (K is 3x3; the skew K[0,1] is used too. Pixel centres are integer coordinates, u = column, v = row).
Arguments:
• points: (N, 3) or (3,) (object coordinates, finite).
• depth: (H, W) forward-distance image (the depth of render3d.render_mesh; background is +inf). If given, shape is taken from it and occlusion is tested.
• shape: (H, W). Used for the in-image test when there is no depth.
• occlusion_tol: [0, 1). If the pixel depth d satisfies d < z * (1 - tol), the point is hidden (tolerance for z-buffer discretisation).
Return value (dict, all of length N):
• uv (N, 2) float -- (u, v) pixel coordinates. NaN for points behind.
• depth (N,) -- forward distance z (negative behind).
• in_front -- z > 1e-9.
• in_image -- 0 <= u <= W-1 and 0 <= v <= H-1 (points in front only). All True (untested) if there is neither shape nor depth.
• hidden -- tested only when depth is given (pixel by nearest-neighbour rounding). All False otherwise.
• visible = in_front & in_image & ~hidden.
Validation (ValueError): pose is neither 4x4 nor (R, t), is non-finite, or the determinant of the rotation part is almost 0 / K is not 3x3, is non-finite, or fx or fy is 0 / points has a bad shape or is non-finite / depth is not 2-D, does not match shape, or contains NaN / occlusion_tol is outside [0, 1). Points behind the camera are not an error here (they are returned with in_front=False; the drawing ops turn that into a ValueError).
Note: camera.project_points uses a different convention that looks along +Z (OpenCV style), so passing its pose makes every point count as behind. Pass the pose / intrinsics you gave to render3d.render_mesh unchanged.
• 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.
• annotate3d_figure — py -3.11 examples_3d/annotate3d_figure.py
table as input)fuse_to_voxel · mesh_select_lod
annotate3d)annotate3d_arrow · annotate3d_label · annotate3d_scale_bar · annotate3d_axes · annotate3d_bbox · annotate3d_measure
*Provenance: annotate3d.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.