Line detection, description and matching
Line segments are detected, optionally described, and matched across image pairs. Methods are selected by name through the registries below; each returns an implementation of the base interfaces.
Instantiate a line detector / descriptor
- limap.image.line.get_detector(method: str, loptions: DetectorOptions)
- limap.image.line.get_extractor(method: str, loptions: ExtractorOptions)
Get a line descriptor speicified by cfg_extractor[“method”]
- Parameters:
cfg_extractor – config for the line extractor
- limap.image.line.get_uncertainty2d(method: str) float
Get the default 2D uncertainty for a line detector.
- Parameters:
method – Name of the line detector (e.g., “lsd”, “deeplsd”, “sold2”).
- Returns:
Default 2D uncertainty value in pixels for the specified detector.
- Raises:
ValueError – If the detector method is not recognized.
- class limap.image.line.DetectorOptions(base_options: limap.image.line.base_detector.BaseDetectorOptions = <factory>)
- __init__(base_options: BaseDetectorOptions = <factory>) None
- base_options: BaseDetectorOptions
- class limap.image.line.ExtractorOptions(base_options: limap.image.line.base_detector.BaseDetectorOptions = <factory>)
- __init__(base_options: BaseDetectorOptions = <factory>) None
- base_options: BaseDetectorOptions
Instantiate a line matcher
- limap.image.line.get_matcher(method: str, loptions: MatcherOptions, extractor: Any)
- class limap.image.line.MatcherOptions(base_options: limap.image.line.base_matcher.BaseMatcherOptions = <factory>, superglue_options: limap.image.line.register_matcher.SuperGlueMatcherOptions = <factory>, dense_options: limap.image.line.register_matcher.DenseMatcherOptions = <factory>)
- __init__(base_options: BaseMatcherOptions = <factory>, superglue_options: SuperGlueMatcherOptions = <factory>, dense_options: DenseMatcherOptions = <factory>) None
- base_options: BaseMatcherOptions
- dense_options: DenseMatcherOptions
- superglue_options: SuperGlueMatcherOptions
Base interfaces
Implemented by every method under limap/image/line/; a new method needs a
subclass of these plus one branch in the registry above.
- class limap.image.line.base_detector.BaseDetector(options=BaseDetectorOptions(set_gray=True, max_num_2d_segs=3000, do_merge_lines=False, visualize=False, weight_path=None))
Virtual class for line detector
- __init__(options=BaseDetectorOptions(set_gray=True, max_num_2d_segs=3000, do_merge_lines=False, visualize=False, weight_path=None))
- detect(image_path: Path) ndarray
Virtual method (for detector) - detect 2D line segments
- Parameters:
image_path – full path to the image
- Returns:
line detections. Each row corresponds to x1, y1, x2, y2 and score.
- Return type:
np.arrayof shape (N, 5)
- detect_all_images(output_folder, image_paths, skip_exists=False)
Perform line detection on all images and save the line segments
- Parameters:
output_folder (str) – The output folder
image_paths (dict[int, pathlib.Path]) – mapping from image id to full image path
skip_exists (bool) – Whether to skip already processed images
- Returns:
The line detection for each image indexed by the image id. Each segment is with shape (N, 5). Each row corresponds to x1, y1, x2, y2 and score.
- Return type:
dict[int ->
np.array]
- detect_and_extract(image_path: Path) tuple[ndarray, Any]
Virtual method (for dual-functional class that can perform both detection and extraction) - Detect and extract on a single image
- Parameters:
image_path – full path to the image
- Returns:
of shape (N, 5), line detections. Each row corresponds to x1, y1, x2, y2 and score. Computed from the detect method. descinfo: The features extracted from the function extract
- Return type:
segs (
np.array)
- detect_and_extract_all_images(output_folder, image_paths, skip_exists=False)
Perform line detection and description on all images and save the line segments and descriptors
- Parameters:
output_folder (str) – The output folder
image_paths (dict[int, pathlib.Path]) – mapping from image id to full image path
skip_exists (bool) – Whether to skip already processed images
- Returns:
The line detection for each image indexed by the image id. Each segment is with shape (N, 5). Each row corresponds to x1, y1, x2, y2 and score. descinfo_folder (str): Path to the extracted descriptors.
- Return type:
all_segs (dict[int ->
np.array])
- extract(image_path: Path, segs: ndarray) Any
Virtual method (for extractor) - extract the features for the detected segments
- Parameters:
image_path – full path to the image
segs –
np.arrayof shape (N, 5), line detections. Each row corresponds to x1, y1, x2, y2 and score. Computed from the detect method.
- Returns:
The extracted feature
- extract_all_images(output_folder, image_paths, all_2d_segs, skip_exists=False)
Line descriptor extraction on all images and save the descriptors.
- Parameters:
output_folder (str) – The output folder.
image_paths (dict[int, pathlib.Path]) – mapping from image id to full image path
all_2d_segs (dict[int ->
np.array]) – The line detection for each image indexed by the image id. Each segment is with shape (N, 5). Each row corresponds to x1, y1, x2, y2 and score. Computed from detect_all_imagesskip_exists (bool) – Whether to skip already processed images.
- Returns:
The path to the saved descriptors.
- Return type:
descinfo_folder (str)
- get_descinfo_fname(descinfo_folder: Path, img_id: int) Path
Virtual method (for extractor) - Get the target filename of the extracted feature
- Parameters:
descinfo_folder (pathlib.Path) – The output folder
img_id (int) – The image id
- Returns:
target filename
- Return type:
pathlib.Path
- get_descinfo_folder(output_folder: Path) Path
Return the folder path to the extracted descriptors
- Parameters:
output_folder (pathlib.Path) – The output folder
- Returns:
The path to the saved descriptors
- Return type:
path_to_descinfos (pathlib.Path)
- get_module_name() str
Virtual method (need to be implemented) - return the name of the module
- get_segments_folder(output_folder: Path) Path
Return the folder path to the detected segments
- Parameters:
output_folder (pathlib.Path) – The output folder
- Returns:
The path to the saved segments
- Return type:
path_to_segments (pathlib.Path)
- merge_lines(segs)
- read_descinfo(descinfo_folder: Path, img_id: Any) Any
Virtual method (for extractor) - Read in the extracted feature. Dual function for save_descinfo.
- Parameters:
descinfo_folder (pathlib.Path) – The output folder
img_id (int) – The image id
- Returns:
The extracted feature
- sample_descinfo_by_indexes(descinfo: Any, indexes: list[int]) Any
Virtual method (for dual-functional class that can perform both detection and extraction) - sample descriptors for a subset of images
- Parameters:
descinfo – The features extracted from the function extract.
indexes (list[int]) – List of image ids for the subset.
- save_descinfo(descinfo_folder: Path, img_id: int, descinfo: Any) None
Virtual method (for extractor) - Save the extracted feature to the target folder
- Parameters:
descinfo_folder (pathlib.Path) – The output folder
img_id (int) – The image id
descinfo – The features extracted from the function extract
- take_longest_k(segs, max_num_2d_segs=3000)
- visualize_segs(output_folder, image_paths, first_k=10)
- class limap.image.line.base_detector.BaseDetectorOptions(set_gray: bool = True, max_num_2d_segs: int = 3000, do_merge_lines: bool = False, visualize: bool = False, weight_path: Path | None = None)
Base options for the line detector
- Parameters:
set_gray – whether to set the image to gray scale (sometimes depending on the detector)
max_num_2d_segs – maximum number of detected line segments (default = 3000)
do_merge_lines – whether to merge close similar lines at post-processing (default = False)
visualize – whether to output visualizations into output folder along with the detections (default = False)
weight_path – root directory to load/store weights (at default,
~/.cache/limap, overridable with theLIMAP_WEIGHTS_PATHenvironment variable)
- __init__(set_gray: bool = True, max_num_2d_segs: int = 3000, do_merge_lines: bool = False, visualize: bool = False, weight_path: Path | None = None) None
- do_merge_lines: bool = False
- max_num_2d_segs: int = 3000
- set_gray: bool = True
- visualize: bool = False
- weight_path: Path | None = None
- class limap.image.line.base_matcher.BaseMatcher(extractor, options=BaseMatcherOptions(topk=0, n_neighbors=20, n_jobs=1, weight_path=None))
Virtual class for line matcher
- __init__(extractor, options=BaseMatcherOptions(topk=0, n_neighbors=20, n_jobs=1, weight_path=None))
- get_match_filename(matches_folder: Path, idx: int) Path
Return the filename of the matches specified by an image id
- Parameters:
matches_folder (pathlib.Path) – The output matching folder
idx (int) – image id
- get_matches_folder(output_folder: Path) Path
Return the folder path to the output matches
- Parameters:
output_folder (pathlib.Path) – The output folder
- Returns:
The path to the saved matches
- Return type:
path_to_matches (pathlib.Path)
- get_module_name()
Virtual method (need to be implemented) - return the name of the module
- match_all_exhaustive_pairs(output_folder, image_ids, descinfo_folder, skip_exists=False)
Match all images exhaustively
- Parameters:
output_folder (pathlib.Path) – The output folder
image_ids (list[int]) – list of image ids
descinfo_folder (pathlib.Path) – The folder storing all descriptors
skip_exists (bool) – Whether to skip already processed images
- Returns:
The output matching folder
- Return type:
matches_folder
- match_all_neighbors(output_folder, image_ids, neighbors, descinfo_folder, skip_exists=False)
Match all images with its visual neighbors
- Parameters:
output_folder (pathlib.Path) – The output folder
image_ids (list[int]) – list of image ids
neighbors (dict[int -> list[int]]) – visual neighbors for each image
descinfo_folder (str) – The folder storing all the descriptors
skip_exists (bool) – Whether to skip already processed images
- Returns:
The output matching folder
- Return type:
matches_folder
- match_pair(descinfo1, descinfo2)
Virtual method (need to be implemented) - match two set of lines based on the descriptors
- read_descinfo(descinfo_folder, idx)
- read_match(matches_folder: Path, idx: int) dict[int, ndarray]
Read the matches for one image with its neighbors
- Parameters:
matches_folder (pathlib.Path) – The output matching folder
idx (int) – image id
- Returns:
The output matches for each neighboring image, each with shape (N, 2)
- Return type:
matches (dict[int ->
np.array])
- save_match(matches_folder: Path, idx: int, matches: dict[int, ndarray]) None
Save the output matches from one image to its neighbors
- Parameters:
matches_folder (pathlib.Path) – The output matching folder
idx (int) – image id
matches (dict[int ->
np.array]) – The output matches for each neighboring image, each with shape (N, 2)
- class limap.image.line.base_matcher.BaseMatcherOptions(topk: int = 0, n_neighbors: int = 20, n_jobs: int = 1, weight_path: Path | None = None)
Base options for the line matcher
- Parameters:
topk – number of top matches for each line (if equal to 0, do mutual nearest neighbor matching)
n_neighbors – number of visual neighbors, only for naming the output folder
n_jobs – number of jobs at multi-processing (please make sure not to exceed the GPU memory limit with learning methods)
weight_path – root directory to load/store weights (at default,
~/.cache/limap, overridable with theLIMAP_WEIGHTS_PATHenvironment variable)
- __init__(topk: int = 0, n_neighbors: int = 20, n_jobs: int = 1, weight_path: Path | None = None) None
- n_jobs: int = 1
- n_neighbors: int = 20
- topk: int = 0
- weight_path: Path | None = None
Detection and matching over a set of images
The batch helpers the pipelines call, writing their output into the structure database.
- class limap.image.line.LineDetectionOptions(skip_exists: bool = True, compute_descinfo: bool = True, weight_path: pathlib.Path = PosixPath('/local/home/shaoliu/.limap/models'), detector_method: str = 'deeplsd', extractor_method: str | None = 'wireframe', _detector_options: limap.image.line.register_detector.DetectorOptions = <factory>, _extractor_options: limap.image.line.register_detector.ExtractorOptions = <factory>)
- __init__(skip_exists: bool = True, compute_descinfo: bool = True, weight_path: Path = PosixPath('/local/home/shaoliu/.limap/models'), detector_method: str = 'deeplsd', extractor_method: str | None = 'wireframe', _detector_options: DetectorOptions = <factory>, _extractor_options: ExtractorOptions = <factory>) None
- compute_descinfo: bool = True
- detector_method: str = 'deeplsd'
- property detector_options: DetectorOptions
- extractor_method: str | None = 'wireframe'
- property extractor_options: ExtractorOptions
- skip_exists: bool = True
- weight_path: Path = PosixPath('/local/home/shaoliu/.limap/models')
- limap.image.line.line_detection(image_paths: dict[int, Path], output_dir, options: LineDetectionOptions) tuple[dict[int, ndarray], Path | None]
- class limap.image.line.LineMatcherOptions(skip_exists: bool = True, weight_path: pathlib.Path = PosixPath('/local/home/shaoliu/.limap/models'), method: str = 'gluestick', _matching_options: limap.image.line.register_matcher.MatcherOptions = <factory>)
- __init__(skip_exists: bool = True, weight_path: Path = PosixPath('/local/home/shaoliu/.limap/models'), method: str = 'gluestick', _matching_options: MatcherOptions = <factory>) None
- property matching_options: MatcherOptions
- method: str = 'gluestick'
- skip_exists: bool = True
- weight_path: Path = PosixPath('/local/home/shaoliu/.limap/models')
- limap.image.line.line_matching(descinfo_folder: Path, output_dir: Path, neighbors: dict[int, list[int]], det_options: LineDetectionOptions, options: LineMatcherOptions) Path
- limap.image.line.exhaustive_line_matching(descinfo_folder: Path, output_dir: Path, image_ids: list[int], det_options: LineDetectionOptions, options: LineMatcherOptions) Path