Dense matching

Dense matchers produce a pixel-wise warp between two images. It is used to associate points, lines and groups without relying on sparse descriptors.

Instantiate a dense matcher

limap.image.dense_matcher.get_dense_matcher(method: str)

Base interface and results

class limap.image.dense_matcher.base_dense_matcher.BaseDenseMatcher
__init__()
get_warping(img1, img2) DenseMatchingResult

return DenseMatchingResult from img1 to img2

get_warping_symmetric(img1, img2) BiDenseMatchingResult

return BiDenseMatchingResult

class limap.image.dense_matcher.DenseMatchingResult(device: str = 'cpu', sample_threshold: float | None = None, source_shape: tuple[int, int] | None = None, target_shape: tuple[int, int] | None = None, warp: torch.Tensor | None = None, certainty: torch.Tensor | None = None)
classmethod from_dict(data: dict) DenseMatchingResult
__init__(device: str = 'cpu', sample_threshold: float | None = None, source_shape: tuple[int, int] | None = None, target_shape: tuple[int, int] | None = None, warp: Tensor | None = None, certainty: Tensor | None = None) None
to_dict() dict
to_normalized_coordinates(coords, h, w)

coords: (…, 2) in the order x, y

to_unnormalized_coordinates(coords, h, w)

Inverse operation of to_normalized_coordinates

certainty: Tensor | None = None
device: str = 'cpu'
sample_threshold: float | None = None
source_shape: tuple[int, int] | None = None
target_shape: tuple[int, int] | None = None
warp: Tensor | None = None
class limap.image.dense_matcher.BiDenseMatchingResult(match_1to2: limap.image.dense_matcher.base_dense_matcher.DenseMatchingResult, match_2to1: limap.image.dense_matcher.base_dense_matcher.DenseMatchingResult)
classmethod from_dict(data: dict) BiDenseMatchingResult
__init__(match_1to2: DenseMatchingResult, match_2to1: DenseMatchingResult) None
to_dict() dict
match_1to2: DenseMatchingResult
match_2to1: DenseMatchingResult

Options

class limap.image.dense_matcher.DenseMatchingOptions(method: str = 'tiny_roma', point_matching: limap.image.dense_matcher.specs.PointDenseMatchingOptions = <factory>, line_matching: limap.image.dense_matcher.specs.LineDenseMatchingOptions = <factory>, group_matching: limap.image.dense_matcher.specs.GroupDenseMatchingOptions = <factory>, skip_point_matching: bool = False, skip_line_matching: bool = False, skip_group_matching: bool = False, save_warps: bool = False)
__init__(method: str = 'tiny_roma', point_matching: PointDenseMatchingOptions = <factory>, line_matching: LineDenseMatchingOptions = <factory>, group_matching: GroupDenseMatchingOptions = <factory>, skip_point_matching: bool = False, skip_line_matching: bool = False, skip_group_matching: bool = False, save_warps: bool = False) None
group_matching: GroupDenseMatchingOptions
line_matching: LineDenseMatchingOptions
method: str = 'tiny_roma'
point_matching: PointDenseMatchingOptions
save_warps: bool = False
skip_group_matching: bool = False
skip_line_matching: bool = False
skip_point_matching: bool = False
class limap.image.dense_matcher.PointDenseMatchingOptions(pixel_thresh: float = 4.0)
__init__(pixel_thresh: float = 4.0) None
pixel_thresh: float = 4.0
class limap.image.dense_matcher.LineDenseMatchingOptions(pixel_thresh: float = 4.0, n_samples: float = 21, min_segment_overlap: float = 0.2)
__init__(pixel_thresh: float = 4.0, n_samples: float = 21, min_segment_overlap: float = 0.2) None
min_segment_overlap: float = 0.2
n_samples: float = 21
pixel_thresh: float = 4.0
class limap.image.dense_matcher.GroupDenseMatchingOptions(overlap_thresh: float = 0.6, min_num_pixels: float = 1000)
__init__(overlap_thresh: float = 0.6, min_num_pixels: float = 1000) None
min_num_pixels: float = 1000
overlap_thresh: float = 0.6

Association

limap.image.dense_matcher.associate_via_dense_matching(options: DenseMatchingOptions, image_names: dict[int, Path], neighbors: dict[int, list[int]], group_workspace_path: Path, db_path: Path, structure_db_path: Path, warp_cache_dir: Path | None = None) None
limap.image.dense_matcher.match_points_via_dense_matching(options: PointDenseMatchingOptions, warp: BiDenseMatchingResult, points1: ndarray, points2: ndarray)
limap.image.dense_matcher.match_lines_via_dense_matching(options: LineDenseMatchingOptions, warp: BiDenseMatchingResult, lines1: list[Line2d], lines2: list[Line2d])
limap.image.dense_matcher.match_groups_via_dense_matching(options: GroupDenseMatchingOptions, warp: BiDenseMatchingResult, mask1: ndarray, mask2: ndarray)

Metrics

limap.image.dense_matcher.compute_point_distance_matrix(match: DenseMatchingResult, source_points: ndarray, target_points: ndarray) ndarray
limap.image.dense_matcher.compute_line_distance_matrix(match: DenseMatchingResult, source_lines: list[Line2d], target_lines: list[Line2d], n_samples: int = 21, min_segment_overlap: float = 0.2) ndarray
limap.image.dense_matcher.compute_mask_overlap_matrix(match: DenseMatchingResult, source_mask: ndarray, target_mask: ndarray, min_num_pixels: int = 200) ndarray

Calculate overlap (intersection size / smaller region size) on the source images by inverse warping the target image.