def test_jit(self, device, dtype): points1 = torch.rand(4, 2, device=device, dtype=dtype) points2 = torch.rand(4, 2, device=device, dtype=dtype) model = RANSAC('homography').to(device=device, dtype=dtype) model_jit = torch.jit.script( RANSAC('homography').to(device=device, dtype=dtype)) assert_close(model(points1, points2)[0], model_jit(points1, points2)[0], rtol=1e-4, atol=1e-4)
def test_jit(self, device, dtype): points1 = torch.rand(8, 2, device=device, dtype=dtype) points2 = torch.rand(8, 2, device=device, dtype=dtype) model = RANSAC('fundamental').to(device=device, dtype=dtype) model_jit = torch.jit.script( RANSAC('fundamental').to(device=device, dtype=dtype)) assert_close(model(points1, points2)[0], model_jit(points1, points2)[0], rtol=1e-3, atol=1e-3)
def test_smoke(self, device, dtype): torch.random.manual_seed(0) points1 = torch.rand(8, 2, device=device, dtype=dtype) points2 = torch.rand(8, 2, device=device, dtype=dtype) ransac = RANSAC('fundamental').to(device=device, dtype=dtype) Fm, _ = ransac(points1, points2) assert Fm.shape == (3, 3)
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_dirty_points(self, device, dtype): points1 = torch.tensor( [[[0.8569, 0.5982], [0.0059, 0.9649], [0.1968, 0.8846], [0.6084, 0.3467], [0.9633, 0.5274], [0.8941, 0.8939], [0.0863, 0.5133], [0.2645, 0.8882]]], device=device, dtype=dtype, ) points2 = torch.tensor( [[[0.0928, 0.3013], [0.0989, 0.9649], [0.0341, 0.4827], [0.8294, 0.4469], [0.2230, 0.2998], [0.1722, 0.8182], [0.5264, 0.8869], [0.8908, 0.1233]]], device=device, dtype=dtype, ) # generated with OpenCV using above points # import cv2 # Fm_expected, _ = cv2.findFundamentalMat( # points1.detach().numpy().reshape(-1, 1, 2), # points2.detach().numpy().reshape(-1, 1, 2), cv2.FM_8POINT) Fm_expected = torch.tensor( [[[0.2019, 0.6860, -0.6610], [0.5520, 0.8154, -0.8044], [-0.5002, -1.0254, 1.]]], device=device, dtype=dtype, ) ransac = RANSAC('fundamental', max_iter=1, inl_th=1.0).to(device=device, dtype=dtype) F_mat, inliers = ransac(points1[0], points2[0]) assert_close(F_mat, Fm_expected[0], rtol=1e-3, atol=1e-3)
def test_smoke(self, device, dtype): torch.random.manual_seed(0) points1 = torch.rand(4, 2, device=device, dtype=dtype) points2 = torch.rand(4, 2, device=device, dtype=dtype) ransac = RANSAC('homography').to(device=device, dtype=dtype) torch.random.manual_seed(0) H, _ = ransac(points1, points2) assert H.shape == (3, 3)
def test_gradcheck(self, device): points1 = torch.rand(8, 2, device=device, dtype=torch.float64, requires_grad=True) points2 = torch.rand(8, 2, device=device, dtype=torch.float64) model = RANSAC('fundamental').to(device=device, dtype=torch.float64) def gradfun(p1, p2): return model(p1, p2)[0] assert gradcheck(gradfun, (points1, points2), raise_exception=True)
def test_real_clean(self, device, dtype, data): # generate input data torch.random.manual_seed(0) data_dev = utils.dict_to(data, device, dtype) homography_gt = torch.inverse(data_dev['H_gt']) homography_gt = homography_gt / homography_gt[2, 2] pts_src = data_dev['pts0'] pts_dst = data_dev['pts1'] ransac = RANSAC('homography', inl_th=0.5, max_iter=20).to(device=device, dtype=dtype) # compute transform from source to target dst_homo_src, _ = ransac(pts_src, pts_dst) assert_close(transform_points(dst_homo_src[None], pts_src[None]), pts_dst[None], rtol=1e-3, atol=1e-3)
def test_real_clean(self, device, dtype, data): torch.random.manual_seed(0) # generate input data data_dev = utils.dict_to(data, device, dtype) pts_src = data_dev['pts0'] pts_dst = data_dev['pts1'] # compute transform from source to target ransac = RANSAC('fundamental', inl_th=0.5, max_iter=20, max_lo_iters=10).to(device=device, dtype=dtype) fundamental_matrix, _ = ransac(pts_src, pts_dst) gross_errors = (sampson_epipolar_distance(pts_src[None], pts_dst[None], fundamental_matrix[None], squared=False) > 1.0) assert gross_errors.sum().item() == 0
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 test_real_dirty(self, device, dtype, data): torch.random.manual_seed(0) # generate input data data_dev = utils.dict_to(data, device, dtype) pts_src = data_dev['pts0'] pts_dst = data_dev['pts1'] kp1 = data_dev['loftr_indoor_tentatives0'] kp2 = data_dev['loftr_indoor_tentatives1'] ransac = RANSAC('fundamental', inl_th=1.0, max_iter=20, max_lo_iters=10).to(device=device, dtype=dtype) # compute transform from source to target fundamental_matrix, _ = ransac(kp1, kp2) gross_errors = (sampson_epipolar_distance(pts_src[None], pts_dst[None], fundamental_matrix[None], squared=False) > 10.0) assert gross_errors.sum().item() < 2
def test_real_dirty(self, device, dtype, data): # generate input data torch.random.manual_seed(0) data_dev = utils.dict_to(data, device, dtype) homography_gt = torch.inverse(data_dev['H_gt']) homography_gt = homography_gt / homography_gt[2, 2] pts_src = data_dev['pts0'] pts_dst = data_dev['pts1'] kp1 = data_dev['loftr_outdoor_tentatives0'] kp2 = data_dev['loftr_outdoor_tentatives1'] ransac = RANSAC('homography', inl_th=3.0, max_iter=30, max_lo_iters=10).to(device=device, dtype=dtype) # compute transform from source to target dst_homo_src, _ = ransac(kp1, kp2) # Reprojection error of 5px is OK assert_close(transform_points(dst_homo_src[None], pts_src[None]), pts_dst[None], rtol=5, atol=0.15)
def test_dirty_points(self, device, dtype): # generate input data torch.random.manual_seed(0) H = torch.eye(3, dtype=dtype, device=device) H[:2] = H[:2] + 0.1 * torch.rand_like(H[:2]) H[2:, :2] = H[2:, :2] + 0.001 * torch.rand_like(H[2:, :2]) points_src = 100.0 * torch.rand(1, 20, 2, device=device, dtype=dtype) points_dst = transform_points(H[None], points_src) # making last point an outlier points_dst[:, -1, :] += 800 ransac = RANSAC('homography', inl_th=0.5, max_iter=20).to(device=device, dtype=dtype) # compute transform from source to target dst_homo_src, _ = ransac(points_src[0], points_dst[0]) assert_close(transform_points(dst_homo_src[None], points_src[:, :-1]), points_dst[:, :-1], rtol=1e-3, atol=1e-3)
def test_smoke(self, device, dtype): points1 = torch.rand(8, 2, device=device, dtype=dtype) points2 = torch.rand(8, 2, device=device, dtype=dtype) ransac = RANSAC('fundamental').to(device=device, dtype=dtype) Fm, inliers = ransac(points1, points2) assert Fm.shape == (3, 3)
def test_smoke(self, device, dtype): points1 = torch.rand(4, 2, device=device, dtype=dtype) points2 = torch.rand(4, 2, device=device, dtype=dtype) ransac = RANSAC('homography').to(device=device, dtype=dtype) H, inliers = ransac(points1, points2) assert H.shape == (3, 3)