def test_real_sift_preextract(self, device, dtype, data): torch.random.manual_seed(0) # This is not unit test, but that is quite good integration test feat = SIFTFeature(2000) matcher = LocalFeatureMatcher(feat, DescriptorMatcher('snn', 0.8)).to(device) ransac = RANSAC('homography', 1.0, 2048, 10).to(device, dtype) data_dev = utils.dict_to(data, device, dtype) pts_src = data_dev['pts0'] pts_dst = data_dev['pts1'] lafs, _, descs = feat(data_dev["image0"]) data_dev["lafs0"] = lafs data_dev["descriptors0"] = descs lafs2, _, descs2 = feat(data_dev["image1"]) data_dev["lafs1"] = lafs2 data_dev["descriptors1"] = descs2 with torch.no_grad(): out = matcher(data_dev) homography, inliers = ransac(out['keypoints0'], out['keypoints1']) assert inliers.sum().item() > 50 # we have enough inliers # Reprojection error of 5px is OK assert_close(transform_points(homography[None], pts_src[None]), pts_dst[None], rtol=5e-2, atol=5)
def test_nomatch(self, device, dtype, data): matcher = LocalFeatureMatcher(GFTTAffNetHardNet(100), DescriptorMatcher('snn', 0.8)).to( device, dtype) data_dev = utils.dict_to(data, device, dtype) with torch.no_grad(): out = matcher({ "image0": data_dev["image0"], "image1": 0 * data_dev["image0"] }) assert len(out['keypoints0']) == 0
def test_jit(self, device, dtype): B, C, H, W = 1, 1, 32, 32 patches = torch.rand(B, C, H, W, device=device, dtype=dtype) patches2x = resize(patches, (48, 48)) inputs = {"image0": patches, "image1": patches2x} model = LocalFeatureMatcher(SIFTDescriptor(32), DescriptorMatcher('snn', 0.8)).to(device).eval() model_jit = torch.jit.script(model) out = model(inputs) out_jit = model_jit(inputs) for k, v in out.items(): assert_close(v, out_jit[k])
def test_gradcheck(self, device): matcher = LocalFeatureMatcher(SIFTFeature(5), DescriptorMatcher('nn', 1.0)).to(device) patches = torch.rand(1, 1, 32, 32, device=device) patches05 = resize(patches, (48, 48)) patches = utils.tensor_to_gradcheck_var(patches) # to var patches05 = utils.tensor_to_gradcheck_var(patches05) # to var def proxy_forward(x, y): return matcher({"image0": x, "image1": y})["keypoints0"] assert gradcheck(proxy_forward, (patches, patches05), eps=1e-4, atol=1e-4, raise_exception=True)
def test_real_keynet(self, device, dtype, data): torch.random.manual_seed(0) # This is not unit test, but that is quite good integration test matcher = LocalFeatureMatcher(KeyNetHardNet(500), DescriptorMatcher('snn', 0.9)).to( device, dtype) ransac = RANSAC('homography', 1.0, 2048, 10).to(device, dtype) data_dev = utils.dict_to(data, device, dtype) pts_src = data_dev['pts0'] pts_dst = data_dev['pts1'] with torch.no_grad(): out = matcher(data_dev) homography, inliers = ransac(out['keypoints0'], out['keypoints1']) assert inliers.sum().item() > 50 # we have enough inliers # Reprojection error of 5px is OK assert_close(transform_points(homography[None], pts_src[None]), pts_dst[None], rtol=5e-2, atol=5)
def __init__(self, initial_matcher: Optional[LocalFeature] = None, fast_matcher: Optional[nn.Module] = None, ransac: Optional[nn.Module] = None, minimum_inliers_num: int = 30) -> None: super().__init__() self.initial_matcher = initial_matcher or (LocalFeatureMatcher( GFTTAffNetHardNet(3000), DescriptorMatcher('smnn', 0.95))) self.fast_matcher = fast_matcher or LoFTR('outdoor') self.ransac = ransac or RANSAC('homography', inl_th=5.0, batch_size=4096, max_iter=10, max_lo_iters=10) self.minimum_inliers_num = minimum_inliers_num # placeholders self.target: torch.Tensor self.target_initial_representation: Dict[str, torch.Tensor] = {} self.target_fast_representation: Dict[str, torch.Tensor] = {} self.previous_homography: Optional[torch.Tensor] = None self.reset_tracking()
def test_smoke(self, device): matcher = LocalFeatureMatcher(SIFTFeature(5), DescriptorMatcher('snn', 0.8)).to(device) assert matcher is not None