def get_projective_transform(center: torch.Tensor, angles: torch.Tensor, scales: torch.Tensor) -> torch.Tensor: r"""Calculate the projection matrix for a 3D rotation. .. warning:: This API signature it is experimental and might suffer some changes in the future. The function computes the projection matrix given the center and angles per axis. Args: center: center of the rotation (x,y,z) in the source with shape :math:`(B, 3)`. angles: angle axis vector containing the rotation angles in degrees in the form of (rx, ry, rz) with shape :math:`(B, 3)`. Internally it calls Rodrigues to compute the rotation matrix from axis-angle. scales: scale factor for x-y-z-directions with shape :math:`(B, 3)`. Returns: the projection matrix of 3D rotation with shape :math:`(B, 3, 4)`. .. note:: This function is often used in conjunction with :func:`warp_affine3d`. """ if not (len(center.shape) == 2 and center.shape[-1] == 3): raise AssertionError(center.shape) if not (len(angles.shape) == 2 and angles.shape[-1] == 3): raise AssertionError(angles.shape) if center.device != angles.device: raise AssertionError(center.device, angles.device) if center.dtype != angles.dtype: raise AssertionError(center.dtype, angles.dtype) # create rotation matrix angle_axis_rad: torch.Tensor = K.deg2rad(angles) rmat: torch.Tensor = K.angle_axis_to_rotation_matrix( angle_axis_rad) # Bx3x3 scaling_matrix: torch.Tensor = K.eye_like(3, rmat) scaling_matrix = scaling_matrix * scales.unsqueeze(dim=1) rmat = rmat @ scaling_matrix.to(rmat) # define matrix to move forth and back to origin from_origin_mat = torch.eye(4)[None].repeat(rmat.shape[0], 1, 1).type_as(center) # Bx4x4 from_origin_mat[..., :3, -1] += center to_origin_mat = from_origin_mat.clone() to_origin_mat = _torch_inverse_cast(from_origin_mat) # append translation with zeros proj_mat = projection_from_Rt(rmat, torch.zeros_like(center)[..., None]) # Bx3x4 # chain 4x4 transforms proj_mat = convert_affinematrix_to_homography3d(proj_mat) # Bx4x4 proj_mat = from_origin_mat @ proj_mat @ to_origin_mat return proj_mat[..., :3, :] # Bx3x4
def test_deg2rad(batch_shape, device, dtype): # generate input data x_deg = 180. * torch.rand(batch_shape, device=device, dtype=dtype) # convert radians/degrees x_rad = kornia.deg2rad(x_deg) x_rad_to_deg = kornia.rad2deg(x_rad) assert_allclose(x_deg, x_rad_to_deg, atol=1e-4, rtol=1e-4) assert gradcheck(kornia.deg2rad, (tensor_to_gradcheck_var(x_deg), ), raise_exception=True)
def test_rad2deg(batch_shape, device, dtype): # generate input data x_rad = kornia.pi * torch.rand(batch_shape, device=device, dtype=dtype) # convert radians/degrees x_deg = kornia.rad2deg(x_rad) x_deg_to_rad = kornia.deg2rad(x_deg) # compute error assert_allclose(x_rad, x_deg_to_rad) # evaluate function gradient assert gradcheck(kornia.rad2deg, (tensor_to_gradcheck_var(x_rad), ), raise_exception=True)
def __init__(self, D, H, W, angleIncrement=10.0): self.D = D self.H = H self.W = W self.centerD = self.D // 2 self.centerW = self.W // 2 self.EPS = 1e-5 self.device = torch.device("cuda") self.angleIncrement = angleIncrement # with torch.no_grad(): self.anglesDeg = -1 * torch.arange(0, 360, angleIncrement).to( self.device) self.anglesRad = kornia.deg2rad(self.anglesDeg).to(self.device) self.precomputeMeshGrids()
def test_deg2rad(batch_shape, device_type): # generate input data x_deg = 180. * torch.rand(batch_shape) x_deg = x_deg.to(torch.device(device_type)) # convert radians/degrees x_rad = kornia.deg2rad(x_deg) x_rad_to_deg = kornia.rad2deg(x_rad) # compute error error = utils.compute_mse(x_deg, x_rad_to_deg) assert pytest.approx(error.item(), 0.0) assert gradcheck(kornia.deg2rad, (utils.tensor_to_gradcheck_var(x_deg),), raise_exception=True)
def test_rad2deg(batch_shape, device_type): # generate input data x_rad = kornia.pi * torch.rand(batch_shape) x_rad = x_rad.to(torch.device(device_type)) # convert radians/degrees x_deg = kornia.rad2deg(x_rad) x_deg_to_rad = kornia.deg2rad(x_deg) # compute error error = utils.compute_mse(x_rad, x_deg_to_rad) # evaluate function gradient assert gradcheck(kornia.rad2deg, (utils.tensor_to_gradcheck_var(x_rad),), raise_exception=True)
def get_projective_transform(center: torch.Tensor, angles: torch.Tensor) -> torch.Tensor: r"""Calculates the projection matrix for a 3D rotation. The function computes the projection matrix given the center and angles per axis. Args: center (torch.Tensor): center of the rotation in the source with shape :math:`(B, 3)`. angles (torch.Tensor): angle axis vector containing the rotation angles in degrees in the form of (rx, ry, rz) with shape :math:`(B, 3)`. Internally it calls Rodrigues to compute the rotation matrix from axis-angle. Returns: torch.Tensor: the projection matrix of 3D rotation with shape :math:`(B, 3, 4)`. """ assert len(center.shape) == 2 and center.shape[-1] == 3, center.shape assert len(angles.shape) == 2 and angles.shape[-1] == 3, angles.shape assert center.device == angles.device, (center.device, angles.device) assert center.dtype == angles.dtype, (center.dtype, angles.dtype) # create rotation matrix angle_axis_rad: torch.Tensor = K.deg2rad(angles) rmat: torch.Tensor = K.angle_axis_to_rotation_matrix( angle_axis_rad) # Bx3x3 # define matrix to move forth and back to origin from_origin_mat = torch.eye(4)[None].repeat(rmat.shape[0], 1, 1).type_as(center) # Bx4x4 from_origin_mat[..., :3, -1] += center to_origin_mat = from_origin_mat.clone() to_origin_mat = from_origin_mat.inverse() # append tranlation with zeros proj_mat = projection_from_Rt(rmat, torch.zeros_like(center)[..., None]) # Bx3x4 # chain 4x4 transforms proj_mat = matrix_to_homogeneous(proj_mat) # Bx4x4 proj_mat = (from_origin_mat @ proj_mat @ to_origin_mat) return proj_mat[..., :3, :] # Bx3x4
def angle_to_rotation_matrix(angle: torch.Tensor) -> torch.Tensor: """ Creates a rotation matrix out of angles in degrees Args: angle: (torch.Tensor): tensor of angles in degrees, any shape. Returns: torch.Tensor: tensor of *x2x2 rotation matrices. Shape: - Input: :math:`(*)` - Output: :math:`(*, 2, 2)` Example: >>> input = torch.rand(1, 3) # Nx3 >>> output = kornia.angle_to_rotation_matrix(input) # Nx3x2x2 """ ang_rad = kornia.deg2rad(angle) cos_a: torch.Tensor = torch.cos(ang_rad) sin_a: torch.Tensor = torch.sin(ang_rad) return torch.stack([cos_a, sin_a, -sin_a, cos_a], dim=-1).view(*angle.shape, 2, 2)