limap.visualize package
Note
Everything here needs matplotlib, seaborn or open3d, which are
installed with the viz extra: python -m pip install "limap[viz]".
2D visualization
- limap.visualize.draw_2d_points(image: ndarray, points: ndarray, color: tuple[float, float, float] | None = None, thickness=1) ndarray
- limap.visualize.draw_2d_lines(image: ndarray, lines: list[ndarray] | list[Line2d], color: tuple[float, float, float] | None = None, thickness: int = 1, endpoints: bool = True) ndarray
- limap.visualize.draw_2d_vpresult(img: ndarray, lines: list[Line2d], vpres: VPResult, vp_id: float = -1, show_original: bool = False, endpoints: bool = False) ndarray
- limap.visualize.make_big_image(imgs: list[ndarray], pad=20) ndarray
make a big image with 2d image collections all images should have the same size
3D visualization
- limap.visualize.open3d_get_3d_points(points: ndarray, color: tuple[float, float, float] | None = None, ranges: tuple[ndarray, ndarray] | None = None) PointCloud
- limap.visualize.open3d_get_3d_lines(lines: list[Line3d], color: tuple[float, float, float] | None = None, ranges: tuple[ndarray, ndarray] | None = None) LineSet
- limap.visualize.open3d_get_camera_frustums(recon: Reconstruction, color: tuple[float, float, float] | None = None, ranges: tuple[ndarray, ndarray] | None = None, scale_cam_geometry: float = 1.0) LineSet
- limap.visualize.open3d_visualize_3d_lines(lines: list[Line3d], ranges: tuple[ndarray, ndarray] | None = None) None
Visualize a 3D line map with Open3D
- Parameters:
lines (list[
limap.geometry.Line3d]) – The 3D line mapwidth (float, optional) – width of the line
- limap.visualize.open3d_get_plane_mesh(plane_params: list[float], points: ndarray, color: tuple[float, float, float] | None = None, padding: float = 0.4, alpha: float = 0.5, manhattan_directions: ndarray | None = None, atlanta_gravity: ndarray | None = None) PlaneMesh | None
Create a plane rectangle mesh from plane parameters and associated points.
- Parameters:
plane_params – [a, b, c, d] where ax + by + cz + d = 0
points – Nx3 array of 3D points associated with the plane
color – RGB color tuple
padding – Relative padding around the bounding box (0.5 = 50% padding)
alpha – Transparency value (0.0 = fully transparent, 1.0 = opaque). Used with o3d.visualization.draw() API which supports transparency.
manhattan_directions – Optional Kx3 array of Manhattan world directions (e.g. VP directions). When provided, the plane bbox edges align with the two directions most orthogonal to the plane normal, and an axis-aligned bbox is used instead of an oriented bbox.
atlanta_gravity – Optional 3-vector for Atlanta world gravity direction. When provided, vertical planes (normal orthogonal to gravity) get their bbox aligned with gravity as one axis.
- Returns:
PlaneMesh containing the mesh, color, and alpha, or None if insufficient points
- limap.visualize.open3d_get_sphere_mesh(sphere_params: list[float], color: tuple[float, float, float] | None = None, alpha: float = 0.5, resolution: int = 20) SphereMesh | None
Create a sphere mesh from sphere parameters.
- Parameters:
sphere_params – [cx, cy, cz, log_r] where (cx, cy, cz) is the center and r = exp(log_r) is the radius
color – RGB color tuple
alpha – Transparency value (0.0 = fully transparent, 1.0 = opaque)
resolution – Number of subdivisions for the sphere
- Returns:
SphereMesh or None if invalid parameters
- limap.visualize.open3d_get_cylinder_mesh(cylinder_params: list[float], associated_points: ndarray, color: tuple[float, float, float] | None = None, alpha: float = 0.5, resolution: int = 20) CylinderMesh | None
Create a cylinder mesh from cylinder parameters and associated points.
The cylinder is parameterized using MinimalInfiniteLine3d + log-radius: [qx, qy, qz, qw, wvec0, wvec1, log_r] where the quaternion is in Eigen storage order (x, y, z, w).
The axis is recovered as a Plucker line (d, m) where: - d = R[:, 0] (direction = first column of rotation matrix) - m = (wvec1 / wvec0) * R[:, 1] (moment vector)
- Parameters:
cylinder_params – [qx, qy, qz, qw, wvec0, wvec1, log_r]
associated_points – Nx3 array of 3D points for height estimation
color – RGB color tuple
alpha – Transparency value (0.0 = fully transparent, 1.0 = opaque)
resolution – Number of subdivisions for the cylinder
- Returns:
CylinderMesh or None if invalid parameters or insufficient points
- class limap.visualize.PlaneMesh(mesh: TriangleMesh, color: tuple[float, float, float], alpha: float)
Wrapper for plane mesh with transparency info.
- __init__(mesh: TriangleMesh, color: tuple[float, float, float], alpha: float) None
- alpha: float
- color: tuple[float, float, float]
- mesh: TriangleMesh
- class limap.visualize.SphereMesh(mesh: TriangleMesh, color: tuple[float, float, float], alpha: float)
Wrapper for sphere mesh with transparency info.
- __init__(mesh: TriangleMesh, color: tuple[float, float, float], alpha: float) None
- alpha: float
- color: tuple[float, float, float]
- mesh: TriangleMesh
- class limap.visualize.CylinderMesh(mesh: TriangleMesh, color: tuple[float, float, float], alpha: float)
Wrapper for cylinder mesh with transparency info.
- __init__(mesh: TriangleMesh, color: tuple[float, float, float], alpha: float) None
- alpha: float
- color: tuple[float, float, float]
- mesh: TriangleMesh
Textured meshes
Meshes carrying the image texture of the group they were fitted to.
- limap.visualize.create_textured_plane_mesh(group3d_id: int, group, associated_points: ndarray, hrecon: HolisticReconstruction, start_ids: dict, group_workspace: Path, image_dir: Path, mesh_resolution: int = 50, padding: float = 0.2, use_all_masks: bool = False) TriangleMesh | None
Create a textured plane mesh with vertex colors from images.
Reuses the local (u, v) frame from open3d_get_plane_mesh but creates a dense grid mesh instead of 2 triangles.
- Parameters:
group3d_id – 3D group identifier
group – Group3d object with plane params
associated_points – (N, 3) 3D points on the plane
hrecon – HolisticReconstruction
start_ids – Mask offset dict
group_workspace – Path to group_description/ directory
image_dir – Undistorted images directory
mesh_resolution – Grid density (mesh_resolution x mesh_resolution)
padding – Relative padding around bounding box
use_all_masks – If True, scan all images with masks instead of track
- Returns:
Vertex-colored TriangleMesh, or None if insufficient data
- limap.visualize.create_textured_sphere_mesh(group3d_id: int, group, hrecon: HolisticReconstruction, start_ids: dict, group_workspace: Path, image_dir: Path, mesh_resolution: int = 50, use_all_masks: bool = False) TriangleMesh | None
Create a textured sphere mesh with vertex colors from images.
- Parameters:
group3d_id – 3D group identifier
group – Group3d object with sphere params
hrecon – HolisticReconstruction
start_ids – Mask offset dict
group_workspace – Path to group_description/ directory
image_dir – Undistorted images directory
mesh_resolution – Sphere subdivision resolution
use_all_masks – If True, scan all images with masks instead of track
- Returns:
Vertex-colored TriangleMesh, or None if insufficient data
- limap.visualize.create_textured_cylinder_mesh(group3d_id: int, group, associated_points: ndarray, hrecon: HolisticReconstruction, start_ids: dict, group_workspace: Path, image_dir: Path, mesh_resolution: int = 50, use_all_masks: bool = False) TriangleMesh | None
Create a textured cylinder mesh with vertex colors from images.
Reuses axis recovery from open3d_get_cylinder_mesh.
- Parameters:
group3d_id – 3D group identifier
group – Group3d object with cylinder params
associated_points – (N, 3) 3D points for height estimation
hrecon – HolisticReconstruction
start_ids – Mask offset dict
group_workspace – Path to group_description/ directory
image_dir – Undistorted images directory
mesh_resolution – Cylinder angular resolution
use_all_masks – If True, scan all images with masks instead of track
- Returns:
Vertex-colored TriangleMesh, or None if insufficient data
- limap.visualize.get_group_binary_mask(group3d_id: int, image_id: int, structure_recon, start_ids: dict, group_workspace: Path) ndarray | None
Get binary mask for a group3D in a specific image.
Resolves group3D -> track -> group2D_idx -> mask_label -> binary.
- Parameters:
group3d_id – 3D group identifier
image_id – Image to look up the mask in
structure_recon – StructureReconstruction instance
start_ids – Dict mapping {TYPE_NAME: {image_id: offset}}
group_workspace – Path to group_description/ directory
- Returns:
(H, W) bool array, or None if the group is not visible in image
- limap.visualize.project_points_to_image(points_3d: ndarray, image: Image, camera: Camera) tuple[ndarray, ndarray]
Project 3D points to 2D pixel coordinates.
- Parameters:
points_3d – (N, 3) array of 3D world points
image – pycolmap.Image with pose
camera – pycolmap.Camera with intrinsics
- Returns:
(N, 2) pixel coordinates valid: (N,) bool mask (in front of camera and within image bounds)
- Return type:
uv
Ranges
The visualizers clip to a range, which is best computed robustly from the reconstruction rather than from its extremes.
- limap.visualize.compute_robust_range_points(points: ndarray, range_robust: tuple[float, float] | None = None, k_stretch: float = 2.0) tuple[ndarray, ndarray]