Group detection, description and matching
Vanishing points, planes and parametric primitives are detected per image and associated across images. Vanishing point and plane detectors have registries of their own, on the pages beside this one.
Detection and description
- class limap.image.groups.VPDetectionOptions(skip_exists: bool = True, method: str = 'jlinkage', options: limap.image.groups.vplib.register_vp_detector.DetectorOptions = <factory>)
- __init__(skip_exists: bool = True, method: str = 'jlinkage', options: DetectorOptions = <factory>) None
- method: str = 'jlinkage'
- options: DetectorOptions
- skip_exists: bool = True
- limap.image.groups.vp_detection(image_names: dict[int, Path], all_2d_lines: dict[int, list[Line2d]], output_dir: Path, options: VPDetectionOptions) dict[int, VPResult]
- class limap.image.groups.PlaneDetectionOptions(weight_path: pathlib.Path = PosixPath('/local/home/shaoliu/.limap/models'), skip_exists: bool = True, method: str = 'pxwplanar', visualize: bool = True, _options: limap.image.groups.planelib.register_plane_detector.DetectorOptions = <factory>)
- __init__(weight_path: Path = PosixPath('/local/home/shaoliu/.limap/models'), skip_exists: bool = True, method: str = 'pxwplanar', visualize: bool = True, _options: DetectorOptions = <factory>) None
- method: str = 'pxwplanar'
- property options: DetectorOptions
- skip_exists: bool = True
- visualize: bool = True
- weight_path: Path = PosixPath('/local/home/shaoliu/.limap/models')
- limap.image.groups.plane_detection(image_names: dict[int, Path], output_dir: Path, options: PlaneDetectionOptions)
Detect planar regions in images, yielding results one at a time.
This is a generator to avoid accumulating all plane masks and normal maps in memory (which can easily exceed 30 GB for large datasets).
- Parameters:
output_dir – Base directory (plane_info). Outputs go to: - output_dir/seg_labels/ for segmentation masks - output_dir/normal_maps/ for normal maps - output_dir/moge_outputs/ for MoGe-specific visualizations - output_dir/viz/ for visualizations (if options.visualize)
- Yields:
(img_id, plane_mask, normal_map) tuples per image
- class limap.image.groups.GroupDescriptionOptions(detect_vp: bool = True, vp_detection: limap.image.groups.specs.VPDetectionOptions = <factory>, detect_plane: bool = True, plane_detection: limap.image.groups.specs.PlaneDetectionOptions = <factory>, plane_min_line_overlap_length: float = 40, plane_dilation_radius: float = 2)
- __init__(detect_vp: bool = True, vp_detection: VPDetectionOptions = <factory>, detect_plane: bool = True, plane_detection: PlaneDetectionOptions = <factory>, plane_min_line_overlap_length: float = 40, plane_dilation_radius: float = 2) None
- detect_plane: bool = True
- detect_vp: bool = True
- plane_detection: PlaneDetectionOptions
- plane_dilation_radius: float = 2
- plane_min_line_overlap_length: float = 40
- vp_detection: VPDetectionOptions
- limap.image.groups.group_description(image_names: dict[int, Path], output_dir: Path, db_path: Path, structure_db_path: Path, options: GroupDescriptionOptions, recon=None) dict[str, dict[int, int]]
Detect groups (vanishing points, planes) and import into the structure DB.
Points and lines are read from the databases per-image to avoid holding all keypoints and line detections in memory simultaneously.
- Parameters:
recon – Optional pycolmap.Reconstruction. When provided, keypoints are read from recon.images[img_id].points2D instead of the COLMAP database. Use this when point detection was skipped and the database has no imported keypoints.
- Returns:
start ids (for each image) corresponding to each group type
- limap.image.groups.sam3_group_description(image_names: dict[int, Path], sam3_base_dir: Path, category_to_type: dict[str, GroupType], output_dir: Path, db_path: Path, structure_db_path: Path, existing_start_ids: dict | None = None, min_line_overlap_length: float = 40.0, dilation_radius: float = 2.0, recon=None) dict[str, dict[int, int]]
Load SAM3 segmentation results and import as Group2d into structure DB.
Creates groups for each GroupType found in category_to_type, associates keypoints and lines, saves label masks for dense matching, and imports the groups into the structure database.
- Parameters:
image_names – Mapping from COLMAP image_id to image path
sam3_base_dir – Base directory of SAM3 output
category_to_type – Mapping from SAM3 category name to GroupType, e.g. {“can”: GroupType.CYLINDER, “football”: GroupType.SPHERE}
output_dir – Workspace directory for saving label masks. Masks go to output_dir/{TYPE}_detections/seg_labels/
db_path – Path to COLMAP database (for reading keypoints)
structure_db_path – Path to structure database
existing_start_ids – Existing start_ids dict to merge with (e.g. from VP/plane detection)
min_line_overlap_length – Minimum overlap length for line association
dilation_radius – Dilation radius for point/line association
recon – Optional pycolmap.Reconstruction for reading keypoints
- Returns:
Merged start_ids dict (includes existing + new SAM3 group types)
Matching by voting
Groups that carry no descriptor can still be matched, by voting with the point and line correspondences that fall inside them.
- class limap.image.groups.GroupVotingOptions
- __init__(*args, **kwargs)
Overloaded function.
__init__(self: limap._limap._image._groups.GroupVotingOptions) -> None
__init__(self: limap._limap._image._groups.GroupVotingOptions, kwargs: dict) -> None
__init__(self: limap._limap._image._groups.GroupVotingOptions, **kwargs) -> None
- mergedict(self: object, kwargs: dict) None
- summary(self: limap._limap._image._groups.GroupVotingOptions, write_type: bool = False) str
- todict(self: limap._limap._image._groups.GroupVotingOptions, recursive: bool = True) dict
- property line_weight
1.0)
- Type:
(float, default
- property min_num_votes
- Type:
(int, default
- property point_weight
1.0)
- Type:
(float, default
- property use_feature_weights
True)
- Type:
(bool, default
- limap.image.groups.match_groups_by_voting(options: limap._limap._image._groups.GroupVotingOptions, point_matches: Annotated[numpy.typing.NDArray[numpy.int32], '[m, 2]', 'flags.f_contiguous'], line_matches: Annotated[numpy.typing.NDArray[numpy.int32], '[m, 2]', 'flags.f_contiguous'], structure1: limap._limap._scene.Structure2d, structure2: limap._limap._scene.Structure2d, matched_groups1: collections.abc.Set[SupportsInt | SupportsIndex], matched_groups2: collections.abc.Set[SupportsInt | SupportsIndex]) Annotated[numpy.typing.NDArray[numpy.int32], '[m, 2]']
Match unmatched groups by voting from matched points and lines.
- limap.image.group_voting.vote_unmatched_groups(options: GroupVotingOptions, neighbors: dict[int, list[int]], db_path: Path, structure_db_path: Path) None
Vote for unmatched groups using matched points and lines.
Group masks I/O
- limap.image.groups.get_group_mask_filename(folder: Path, image_id: int) Path
- limap.image.groups.read_group_mask(folder: Path, image_id: int) ndarray
- limap.image.groups.read_group_masks(folder: Path) dict[int, ndarray]
- limap.image.groups.write_group_mask(folder: Path, image_id: int, mask: ndarray) None
- limap.image.groups.write_group_masks(folder: Path, masks: dict[int, ndarray])
SAM 3 utilities
- limap.image.groups.load_sam3_data_for_image(sam3_base_dir: Path, categories: dict[str, GroupType], image_name: str) dict[GroupType, tuple[ndarray, list[float]]]
Load SAM3 masks and scores for a given image across all categories.
- Parameters:
sam3_base_dir – Base directory of SAM3 output (contains category subdirs)
categories – Mapping from category name to GroupType e.g. {“can”: GroupType.CYLINDER, “football”: GroupType.SPHERE}
image_name – Image filename, e.g. “output_0001.png”
- Returns:
Dict mapping GroupType to (binary_masks, scores) where binary_masks is (N_det, H, W) uint8 and scores is list[float]. Only types with at least one detection are included.
- limap.image.groups.convert_sam3_masks_to_groups2d(binary_masks: ndarray, group_type: GroupType, points: ndarray, lines: list[Line2d], scores: list[float] | None = None, min_line_overlap_length: float = 40.0, dilation_radius: float = 2.0, target_size: tuple[int, int] | None = None) tuple[list[Group2d], ndarray]
Convert SAM3 binary masks to Group2d objects and a label mask.
Generalized version of convert_plane_mask_to_groups2d that works with any group type and handles per-detection binary masks with overlap priority based on scores.
- Parameters:
binary_masks – (N_det, H, W) uint8 binary masks
group_type – GroupType for the created groups
points – (N, 2) array of 2D keypoint coordinates
lines – list of Line2d objects
scores – Optional per-detection scores for overlap priority (higher score wins the pixel). If None, earlier index wins.
min_line_overlap_length – minimum overlap length to associate a line
dilation_radius – radius for dilating regions
target_size – Optional (height, width) to resize masks to. Use when masks were generated at a different resolution than the working images (e.g. after –max_image_dim resizing).
- Returns:
Tuple of (list[Group2d], label_mask) where label_mask is (H, W) int array with labels 1..N_det (0 = background).