def test_normalize_homography_identity(self, batch_size, device, dtype): # create input data input_shape = (4, 8, 5) dst_homo_src = utils.create_eye_batch(batch_size=batch_size, eye_size=4).to(device=device, dtype=dtype) res = torch.tensor( [[[0.5000, 0.0, 0.0, -1.0], [0.0, 0.2857, 0.0, -1.0], [0.0, 0.0, 0.6667, -1.0], [0.0, 0.0, 0.0, 1.0]]], device=device, dtype=dtype, ) norm = kornia.normal_transform_pixel3d(input_shape[0], input_shape[1], input_shape[2]).to( device=device, dtype=dtype ) assert_close(norm, res, rtol=1e-4, atol=1e-4) norm_homo = kornia.normalize_homography3d(dst_homo_src, input_shape, input_shape).to(device=device, dtype=dtype) assert_close(norm_homo, dst_homo_src, rtol=1e-4, atol=1e-4) norm_homo = kornia.normalize_homography3d(dst_homo_src, input_shape, input_shape).to(device=device, dtype=dtype) assert_close(norm_homo, dst_homo_src, rtol=1e-4, atol=1e-4) # change output scale norm_homo = kornia.normalize_homography3d( dst_homo_src, input_shape, (input_shape[0] // 2, input_shape[1] * 2, input_shape[2] // 2) ).to(device=device, dtype=dtype) res = torch.tensor( [[[4.0, 0.0, 0.0, 3.0], [0.0, 0.4667, 0.0, -0.5333], [0.0, 0.0, 3.0, 2.0], [0.0, 0.0, 0.0, 1.0]]], device=device, dtype=dtype, ).repeat(batch_size, 1, 1) assert_close(norm_homo, res, rtol=1e-4, atol=1e-4)
def test_jit_warp_homography(self, batch_size, align_corners, normalized_coordinates, device, dtype): # generate input data height, width = 128, 64 eye_size = 3 # identity 3x3 patch_src = torch.rand(batch_size, 1, height, width, device=device, dtype=dtype) # create base homography dst_homo_src = utils.create_eye_batch(batch_size, eye_size, device=device, dtype=dtype) for _ in range(self.num_tests): # generate homography noise homo_delta = torch.rand_like(dst_homo_src) * 0.3 dst_homo_src_i = dst_homo_src + homo_delta # transform the points with and without jit patch_dst = kornia.homography_warp( patch_src, dst_homo_src_i, (height, width), align_corners=align_corners, normalized_coordinates=normalized_coordinates, ) patch_dst_jit = torch.jit.script(kornia.homography_warp)( patch_src, dst_homo_src_i, (height, width), align_corners=align_corners, normalized_coordinates=normalized_coordinates, ) assert_close(patch_dst, patch_dst_jit, atol=1e-4, rtol=1e-4)
def test_warp_grid_translation(self, shape, offset, device, dtype): # create input data depth, height, width = shape dst_homo_src = utils.create_eye_batch(batch_size=1, eye_size=4, device=device, dtype=dtype) dst_homo_src[..., 0, 3] = offset # apply offset in x grid = kornia.create_meshgrid3d(depth, height, width, normalized_coordinates=False) flow = kornia.warp_grid3d(grid, dst_homo_src) # the grid the src plus the offset should be equal to the flow # on the x-axis, y-axis remains the same. assert_allclose(grid[..., 0].to(device=device, dtype=dtype) + offset, flow[..., 0], atol=1e-4, rtol=1e-4) assert_allclose(grid[..., 1].to(device=device, dtype=dtype), flow[..., 1], atol=1e-4, rtol=1e-4) assert_allclose(grid[..., 2].to(device=device, dtype=dtype), flow[..., 2], atol=1e-4, rtol=1e-4)
def test_jit_warp_homography(self, device, batch_size, align_corners, normalized_coordinates): # generate input data height, width = 128, 64 eye_size = 3 # identity 3x3 # create checkerboard board = utils.create_checkerboard(height, width, 4) patch_src = torch.from_numpy(board).view(1, 1, height, width).expand( batch_size, 1, height, width).to(device) # create base homography dst_homo_src = utils.create_eye_batch(batch_size, eye_size).to(device) for i in range(self.num_tests): # generate homography noise homo_delta = torch.rand_like(dst_homo_src) * 0.3 dst_homo_src_i = dst_homo_src + homo_delta # transform the points with and without jit patch_dst = kornia.homography_warp( patch_src, dst_homo_src_i, (height, width), align_corners=align_corners, normalized_coordinates=normalized_coordinates) patch_dst_jit = torch.jit.script(kornia.homography_warp)( patch_src, dst_homo_src_i, (height, width), align_corners=align_corners, normalized_coordinates=normalized_coordinates) assert_allclose(patch_dst, patch_dst_jit)
def test_gradcheck(self, batch_shape, device, dtype): # generate input data eye_size = 3 # identity 3x3 # create checkerboard patch_src = torch.rand(batch_shape, device=device, dtype=dtype) patch_src = utils.tensor_to_gradcheck_var(patch_src) # to var # create base homography batch_size, _, height, width = patch_src.shape dst_homo_src = utils.create_eye_batch(batch_size, eye_size, device=device, dtype=dtype) dst_homo_src = utils.tensor_to_gradcheck_var( dst_homo_src, requires_grad=False) # to var # instantiate warper warper = kornia.HomographyWarper(height, width, align_corners=True) # evaluate function gradient assert gradcheck(warper, ( patch_src, dst_homo_src, ), raise_exception=True)
def test_normalize_homography_identity(self, batch_size, device, dtype): # create input data height, width = 2, 5 dst_homo_src = utils.create_eye_batch(batch_size=batch_size, eye_size=3, device=device, dtype=dtype) res = torch.tensor( [[[0.5, 0.0, -1.0], [0.0, 2.0, -1.0], [0.0, 0.0, 1.0]]], device=device, dtype=dtype) assert (kornia.normal_transform_pixel(height, width, device=device, dtype=dtype) == res).all() norm_homo = kornia.normalize_homography(dst_homo_src, (height, width), (height, width)) assert (norm_homo == dst_homo_src).all() norm_homo = kornia.normalize_homography(dst_homo_src, (height, width), (height, width)) assert (norm_homo == dst_homo_src).all() # change output scale norm_homo = kornia.normalize_homography(dst_homo_src, (height, width), (height * 2, width // 2)) res = torch.tensor( [[[4.0, 0.0, 3.0], [0.0, 1 / 3, -2 / 3], [0.0, 0.0, 1.0]]], device=device, dtype=dtype).repeat(batch_size, 1, 1) assert_allclose(norm_homo, res, atol=1e-4, rtol=1e-4)
def test_homography_warper(self, batch_size, device, dtype): # generate input data height, width = 128, 64 eye_size = 3 # identity 3x3 patch_src = torch.ones(batch_size, 1, height, width, device=device, dtype=dtype) # create base homography dst_homo_src = utils.create_eye_batch(batch_size, eye_size, device=device, dtype=dtype) # instantiate warper warper = kornia.geometry.transform.HomographyWarper(height, width, align_corners=True) for _ in range(self.num_tests): # generate homography noise homo_delta = torch.rand_like(dst_homo_src) * 0.3 dst_homo_src_i = dst_homo_src + homo_delta # transform the points from dst to ref patch_dst = warper(patch_src, dst_homo_src_i) patch_dst_to_src = warper(patch_dst, _torch_inverse_cast(dst_homo_src_i)) # same transform precomputing the grid warper.precompute_warp_grid(_torch_inverse_cast(dst_homo_src_i)) patch_dst_to_src_precomputed = warper(patch_dst) assert_close(patch_dst_to_src_precomputed, patch_dst_to_src, atol=1e-4, rtol=1e-4) # projected should be equal as initial error = utils.compute_patch_error(patch_src, patch_dst_to_src, height, width) assert error.item() < self.threshold # check functional api patch_dst_to_src_functional = kornia.geometry.transform.homography_warp( patch_dst, _torch_inverse_cast(dst_homo_src_i), (height, width), align_corners=True) assert_close(patch_dst_to_src, patch_dst_to_src_functional, atol=1e-4, rtol=1e-4)
def test_identity(self, device, dtype): # create input data height, width = 2, 5 patch_src = torch.rand(1, 1, height, width, device=device, dtype=dtype) dst_homo_src = utils.create_eye_batch(batch_size=1, eye_size=3, device=device, dtype=dtype) # instantiate warper warper = kornia.HomographyWarper(height, width, align_corners=True) # warp from source to destination patch_dst = warper(patch_src, dst_homo_src) assert_close(patch_src, patch_dst)
def test_translation(self, shape): # create input data offset = 2. # in pixel height, width = shape patch_src = torch.rand(1, 1, height, width) dst_homo_src = utils.create_eye_batch(batch_size=1, eye_size=3) dst_homo_src[..., 0, 2] = offset / (width - 1) # apply offset in x # instantiate warper and from source to destination warper = kornia.HomographyWarper(height, width) patch_dst = warper(patch_src, dst_homo_src) assert_allclose(patch_src[..., 1:], patch_dst[..., :-1])
def test_identity(self): # create input data height, width = 2, 5 patch_src = torch.rand(1, 1, height, width) dst_homo_src = utils.create_eye_batch(batch_size=1, eye_size=3) # instantiate warper warper = kornia.HomographyWarper(height, width) # warp from source to destination patch_dst = warper(patch_src, dst_homo_src) assert_allclose(patch_src, patch_dst)
def test_translation(self, shape, device, dtype): # create input data offset = 2.0 # in pixel height, width = shape patch_src = torch.rand(1, 1, height, width, device=device, dtype=dtype) dst_homo_src = utils.create_eye_batch(batch_size=1, eye_size=3, device=device, dtype=dtype) dst_homo_src[..., 0, 2] = offset / (width - 1) # apply offset in x # instantiate warper and from source to destination warper = kornia.HomographyWarper(height, width, align_corners=True) patch_dst = warper(patch_src, dst_homo_src) assert_close(patch_src[..., 1:], patch_dst[..., :-1], atol=1e-4, rtol=1e-4)
def test_homography_warper(self, batch_size, device, dtype): # generate input data height, width = 128, 64 eye_size = 3 # identity 3x3 # create checkerboard board = utils.create_checkerboard(height, width, 4) patch_src = torch.from_numpy(board).to( device=device, dtype=dtype).view(1, 1, height, width).expand(batch_size, 1, height, width) # create base homography dst_homo_src = utils.create_eye_batch(batch_size, eye_size, device=device, dtype=dtype) # instantiate warper warper = kornia.HomographyWarper(height, width, align_corners=True) for i in range(self.num_tests): # generate homography noise homo_delta = torch.rand_like(dst_homo_src) * 0.3 dst_homo_src_i = dst_homo_src + homo_delta # transform the points from dst to ref patch_dst = warper(patch_src, dst_homo_src_i) patch_dst_to_src = warper(patch_dst, torch.inverse(dst_homo_src_i)) # same transform precomputing the grid warper.precompute_warp_grid(torch.inverse(dst_homo_src_i)) patch_dst_to_src_precomputed = warper(patch_dst) assert (patch_dst_to_src_precomputed == patch_dst_to_src).all() # projected should be equal as initial error = utils.compute_patch_error(patch_src, patch_dst_to_src, height, width) assert error.item() < self.threshold # check functional api patch_dst_to_src_functional = kornia.homography_warp( patch_dst, torch.inverse(dst_homo_src_i), (height, width), align_corners=True) assert_allclose(patch_dst_to_src, patch_dst_to_src_functional, atol=1e-4, rtol=1e-4)
def test_identity_resize(self, batch_shape): # create input data batch_size, channels, height, width = batch_shape patch_src = torch.rand(batch_size, channels, height, width) dst_homo_src = utils.create_eye_batch(batch_size, eye_size=3) # instantiate warper warp from source to destination warper = kornia.HomographyWarper(height // 2, width // 2) patch_dst = warper(patch_src, dst_homo_src) # check the corners assert_allclose(patch_src[..., 0, 0], patch_dst[..., 0, 0]) assert_allclose(patch_src[..., 0, -1], patch_dst[..., 0, -1]) assert_allclose(patch_src[..., -1, 0], patch_dst[..., -1, 0]) assert_allclose(patch_src[..., -1, -1], patch_dst[..., -1, -1])
def test_identity_resize(self, batch_shape, device, dtype): # create input data batch_size, channels, height, width = batch_shape patch_src = torch.rand(batch_size, channels, height, width, device=device, dtype=dtype) dst_homo_src = utils.create_eye_batch(batch_size, eye_size=3, device=device, dtype=dtype) # instantiate warper warp from source to destination warper = kornia.HomographyWarper(height // 2, width // 2, align_corners=True) patch_dst = warper(patch_src, dst_homo_src) # check the corners assert_close(patch_src[..., 0, 0], patch_dst[..., 0, 0], atol=1e-4, rtol=1e-4) assert_close(patch_src[..., 0, -1], patch_dst[..., 0, -1], atol=1e-4, rtol=1e-4) assert_close(patch_src[..., -1, 0], patch_dst[..., -1, 0], atol=1e-4, rtol=1e-4) assert_close(patch_src[..., -1, -1], patch_dst[..., -1, -1], atol=1e-4, rtol=1e-4)
def test_angle_axis_to_rotation_matrix(batch_size, device, dtype): # generate input data angle_axis = torch.rand(batch_size, 3, device=device, dtype=dtype) eye_batch = create_eye_batch(batch_size, 3, device=device, dtype=dtype) # apply transform rotation_matrix = kornia.angle_axis_to_rotation_matrix(angle_axis) rotation_matrix_eye = torch.matmul(rotation_matrix, rotation_matrix.transpose(1, 2)) assert_allclose(rotation_matrix_eye, eye_batch, atol=1e-4, rtol=1e-4) # evaluate function gradient angle_axis = tensor_to_gradcheck_var(angle_axis) # to var assert gradcheck(kornia.angle_axis_to_rotation_matrix, (angle_axis, ), raise_exception=True)
def test_warp_grid_translation(self, shape, offset, device): # create input data height, width = shape dst_homo_src = utils.create_eye_batch(batch_size=1, eye_size=3).to(device) dst_homo_src[..., 0, 2] = offset # apply offset in x # instantiate warper warper = kornia.HomographyWarper(height, width, normalized_coordinates=False) flow = warper.warp_grid(dst_homo_src) # the grid the src plus the offset should be equal to the flow # on the x-axis, y-axis remains the same. assert_allclose(warper.grid[..., 0].to(device) + offset, flow[..., 0]) assert_allclose(warper.grid[..., 1].to(device), flow[..., 1])
def test_rotation(self, batch_shape): # create input data batch_size, channels, height, width = batch_shape patch_src = torch.rand(batch_size, channels, height, width) # rotation of 90deg dst_homo_src = utils.create_eye_batch(batch_size, 3) dst_homo_src[..., 0, 0] = 0.0 dst_homo_src[..., 0, 1] = 1.0 dst_homo_src[..., 1, 0] = -1.0 dst_homo_src[..., 1, 1] = 0.0 # instantiate warper and warp from source to destination warper = kornia.HomographyWarper(height, width) patch_dst = warper(patch_src, dst_homo_src) # check the corners assert_allclose(patch_src[..., 0, 0], patch_dst[..., 0, -1]) assert_allclose(patch_src[..., 0, -1], patch_dst[..., -1, -1]) assert_allclose(patch_src[..., -1, 0], patch_dst[..., 0, 0]) assert_allclose(patch_src[..., -1, -1], patch_dst[..., -1, 0])
def test_homography_warper(self, batch_size, device_type): # generate input data height, width = 128, 64 eye_size = 3 # identity 3x3 device = torch.device(device_type) # create checkerboard board = utils.create_checkerboard(height, width, 4) patch_src = torch.from_numpy(board).view(1, 1, height, width).expand( batch_size, 1, height, width) patch_src = patch_src.to(device) # create base homography dst_homo_src = utils.create_eye_batch(batch_size, eye_size).to(device) # instantiate warper warper = kornia.HomographyWarper(height, width) for i in range(self.num_tests): # generate homography noise homo_delta = torch.zeros_like(dst_homo_src) homo_delta[:, -1, -1] = 0.0 dst_homo_src_i = dst_homo_src + homo_delta # transform the points from dst to ref patch_dst = warper(patch_src, dst_homo_src_i) patch_dst_to_src = warper(patch_dst, torch.inverse(dst_homo_src_i)) # projected should be equal as initial error = utils.compute_patch_error(patch_dst, patch_dst_to_src, height, width) assert error.item() < self.threshold # check functional api patch_dst_to_src_functional = kornia.homography_warp( patch_dst, torch.inverse(dst_homo_src_i), (height, width)) assert utils.check_equal_torch(patch_dst_to_src, patch_dst_to_src_functional)