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 utils.check_equal_torch(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 utils.check_equal_torch(patch_src, patch_dst)
def test_pinhole_camera_scale_inplace(self): batch_size = 2 height, width = 4, 6 fx, fy, cx, cy = 1, 2, width / 2, height / 2 tx, ty, tz = 1, 2, 3 scale_val = 2.0 intrinsics = self._create_intrinsics(batch_size, fx, fy, cx, cy) extrinsics = self._create_extrinsics(batch_size, tx, ty, tz) height = torch.ones(batch_size) * height width = torch.ones(batch_size) * width scale_factor = torch.ones(batch_size) * scale_val pinhole = kornia.PinholeCamera(intrinsics, extrinsics, height, width) pinhole_scale = pinhole.clone() pinhole_scale.scale_(scale_factor) assert utils.check_equal_torch( pinhole_scale.intrinsics[..., 0, 0], pinhole.intrinsics[..., 0, 0] * scale_val) # fx assert utils.check_equal_torch( pinhole_scale.intrinsics[..., 1, 1], pinhole.intrinsics[..., 1, 1] * scale_val) # fy assert utils.check_equal_torch( pinhole_scale.intrinsics[..., 0, 2], pinhole.intrinsics[..., 0, 2] * scale_val) # cx assert utils.check_equal_torch( pinhole_scale.intrinsics[..., 1, 2], pinhole.intrinsics[..., 1, 2] * scale_val) # cy assert utils.check_equal_torch( pinhole_scale.height, pinhole.height * scale_val) assert utils.check_equal_torch( pinhole_scale.width, pinhole.width * scale_val)
def test_two_classes_perfect(self): batch_size = 1 num_classes = 2 actual = torch.tensor( [[1, 1, 1, 1, 0, 0, 0, 0]]) predicted = torch.tensor( [[1, 1, 1, 1, 0, 0, 0, 0]]) mean_iou = kornia.utils.metrics.mean_iou(predicted, actual, num_classes) mean_iou_real = torch.tensor( [[1.0, 1.0]], dtype=torch.float32) assert mean_iou.shape == (batch_size, num_classes) assert utils.check_equal_torch(mean_iou, mean_iou_real)
def test_rotation_translation_Bx4x4(self, batch_size): offset = 10 x, y, z = 0, 0, kornia.pi ones = torch.ones(batch_size) rmat_01 = euler_angles_to_rotation_matrix(x * ones, y * ones, z * ones) trans_01 = identity_matrix(batch_size) trans_01[..., :3, -1] += offset # add offset to translation vector trans_01[..., :3, :3] = rmat_01[..., :3, :3] trans_10 = kornia.inverse_transformation(trans_01) trans_01_hat = kornia.inverse_transformation(trans_10) assert utils.check_equal_torch(trans_01, trans_01_hat)
def test_two_classes(self): num_classes = 2 actual = torch.tensor( [[1, 1, 1, 1, 0, 0, 0, 0]]) predicted = torch.tensor( [[1, 1, 1, 1, 0, 0, 0, 1]]) conf_mat = kornia.utils.metrics.confusion_matrix( predicted, actual, num_classes) conf_mat_real = torch.tensor( [[[3, 1], [0, 4]]], dtype=torch.float32) assert utils.check_equal_torch(conf_mat, conf_mat_real)
def test_normalize_pixel_grid(): # generate input data batch_size = 1 height, width = 2, 4 # create points grid grid_norm = kornia.utils.create_meshgrid(height, width, normalized_coordinates=True) grid_norm = torch.unsqueeze(grid_norm, dim=0) grid_pix = kornia.utils.create_meshgrid(height, width, normalized_coordinates=False) grid_pix = torch.unsqueeze(grid_pix, dim=0) # grid from pixel space to normalized norm_trans_pix = kornia.normal_transform_pixel(height, width) # 1x3x3 pix_trans_norm = torch.inverse(norm_trans_pix) # 1x3x3 # transform grids grid_pix_to_norm = kornia.transform_points(norm_trans_pix, grid_pix) grid_norm_to_pix = kornia.transform_points(pix_trans_norm, grid_norm) assert utils.check_equal_torch(grid_pix, grid_norm_to_pix) assert utils.check_equal_torch(grid_norm, grid_pix_to_norm)
def test_rotation_translation_Bx4x4(self, batch_size): offset = 10. x, y, z = 0., 0., kornia.pi ones = torch.ones(batch_size) rmat_02 = euler_angles_to_rotation_matrix(x * ones, y * ones, z * ones) trans_01 = identity_matrix(batch_size) trans_02 = identity_matrix(batch_size) trans_02[..., :3, -1] += offset # add offset to translation vector trans_02[..., :3, :3] = rmat_02[..., :3, :3] trans_12 = kornia.relative_transformation(trans_01, trans_02) trans_02_hat = kornia.compose_transformations(trans_01, trans_12) assert utils.check_equal_torch(trans_02_hat, trans_02)
def test_four_classes_one_missing(self): num_classes = 4 actual = torch.tensor( [[3, 3, 1, 1, 2, 1, 1, 3, 2, 2, 1, 1, 2, 3, 2, 1]]) predicted = torch.tensor( [[3, 2, 1, 1, 1, 1, 1, 2, 1, 3, 3, 2, 1, 1, 3, 3]]) conf_mat = kornia.utils.metrics.confusion_matrix( predicted, actual, num_classes) conf_mat_real = torch.tensor( [[[0, 0, 0, 0], [0, 4, 1, 2], [0, 3, 0, 2], [0, 1, 2, 1]]], dtype=torch.float32) assert utils.check_equal_torch(conf_mat, conf_mat_real)
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 utils.check_equal_torch(patch_src[..., 0, 0], patch_dst[..., 0, -1]) assert utils.check_equal_torch(patch_src[..., 0, -1], patch_dst[..., -1, -1]) assert utils.check_equal_torch(patch_src[..., -1, 0], patch_dst[..., 0, 0]) assert utils.check_equal_torch(patch_src[..., -1, -1], patch_dst[..., -1, 0])
def test_three_classes_normalized(self): num_classes = 3 normalized = True actual = torch.tensor( [[2, 2, 0, 0, 1, 0, 0, 2, 1, 1, 0, 0, 1, 2, 1, 0]]) predicted = torch.tensor( [[2, 1, 0, 0, 0, 0, 0, 1, 0, 2, 2, 1, 0, 0, 2, 2]]) conf_mat = kornia.utils.metrics.confusion_matrix( predicted, actual, num_classes, normalized) conf_mat_real = torch.tensor( [[[0.5000, 0.3333, 0.4000], [0.3750, 0.0000, 0.4000], [0.1250, 0.6667, 0.2000]]], dtype=torch.float32) assert utils.check_equal_torch(conf_mat, conf_mat_real)
def test_four_classes_one_missing(self): batch_size = 1 num_classes = 4 actual = torch.tensor( [[[0, 0, 0, 0], [0, 0, 0, 0], [2, 2, 3, 3], [2, 2, 3, 3]]]) predicted = torch.tensor( [[[3, 3, 2, 2], [3, 3, 2, 2], [2, 2, 3, 3], [2, 2, 3, 3]]]) mean_iou = kornia.utils.metrics.mean_iou(predicted, actual, num_classes) mean_iou_real = torch.tensor( [[0.0, 1.0, 0.5, 0.5]], dtype=torch.float32) assert mean_iou.shape == (batch_size, num_classes) assert utils.check_equal_torch(mean_iou, mean_iou_real)
def test_warp_perspective_rotation(batch_shape, device_type): # generate input data batch_size, channels, height, width = batch_shape alpha = 0.5 * kornia.pi * torch.ones(batch_size) # 90 deg rotation # create data patch device = torch.device(device_type) patch = torch.rand(batch_shape).to(device) # create transformation (rotation) M = torch.eye(3, device=device).repeat(batch_size, 1, 1) # Bx3x3 M[:, 0, 0] = torch.cos(alpha) M[:, 0, 1] = -torch.sin(alpha) M[:, 1, 0] = torch.sin(alpha) M[:, 1, 1] = torch.cos(alpha) # apply transformation and inverse _, _, h, w = patch.shape patch_warped = kornia.warp_perspective(patch, M, dsize=(height, width)) patch_warped_inv = kornia.warp_perspective(patch_warped, torch.inverse(M), dsize=(height, width)) # generate mask to compute error mask = torch.ones_like(patch) mask_warped_inv = kornia.warp_perspective(kornia.warp_perspective( patch, M, dsize=(height, width)), torch.inverse(M), dsize=(height, width)) assert utils.check_equal_torch(mask_warped_inv * patch, mask_warped_inv * patch_warped_inv) # evaluate function gradient patch = utils.tensor_to_gradcheck_var(patch) # to var M = utils.tensor_to_gradcheck_var(M, requires_grad=False) # to var assert gradcheck(kornia.warp_perspective, (patch, M, ( height, width, )), raise_exception=True)
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)
def test_compute_projection_matrix(self, batch_size): height, width = 3, 5 # output shape pinhole_src, pinhole_dst = self._create_pinhole_pair(batch_size) pinhole_dst.tx += 1. # apply offset to tx # create warper warper = kornia.DepthWarper(pinhole_dst, height, width) assert warper._dst_proj_src is None # initialize projection matrices warper.compute_projection_matrix(pinhole_src) assert warper._dst_proj_src is not None # retreive computed projection matrix and compare to expected dst_proj_src = warper._dst_proj_src dst_proj_src_expected = torch.eye(4)[None].repeat(batch_size, 1, 1) # Bx4x4 dst_proj_src_expected[..., 0, -2] += pinhole_src.cx dst_proj_src_expected[..., 1, -2] += pinhole_src.cy dst_proj_src_expected[..., 0, -1] += 1. # offset to x-axis assert utils.check_equal_torch(dst_proj_src, dst_proj_src_expected)
def test_four_classes_2d_perfect(self): num_classes = 4 actual = torch.tensor( [[[0, 0, 1, 1], [0, 0, 1, 1], [2, 2, 3, 3], [2, 2, 3, 3]]]) predicted = torch.tensor( [[[0, 0, 1, 1], [0, 0, 1, 1], [2, 2, 3, 3], [2, 2, 3, 3]]]) conf_mat = kornia.utils.metrics.confusion_matrix( predicted, actual, num_classes) conf_mat_real = torch.tensor( [[[4, 0, 0, 0], [0, 4, 0, 0], [0, 0, 4, 0], [0, 0, 0, 4]]], dtype=torch.float32) assert utils.check_equal_torch(conf_mat, conf_mat_real)
def test_warp_tensor_offset_x1y1(self, batch_size): channels, height, width = 3, 3, 5 # output shape pinhole_src, pinhole_dst = self._create_pinhole_pair(batch_size) pinhole_dst.tx += 1. # apply offset to tx pinhole_dst.ty += 1. # apply offset to ty # initialize depth to one depth_src = torch.ones(batch_size, 1, height, width) # create warper, initialize projection matrices and warp grid warper = kornia.DepthWarper(pinhole_dst, height, width) warper.compute_projection_matrix(pinhole_src) # create patch to warp patch_dst = torch.arange(float(height * width)).view( 1, 1, height, width).expand(batch_size, channels, -1, -1) # warpd source patch by depth patch_src = warper(depth_src, patch_dst) # compare patches assert utils.check_equal_torch(patch_dst[..., 1:, 1:], patch_src[..., :2, :4])