def compute_transformation(self, input: Tensor, params: Dict[str, Tensor]) -> Tensor: return get_affine_matrix2d( torch.as_tensor(params["translations"], device=input.device, dtype=input.dtype), torch.as_tensor(params["center"], device=input.device, dtype=input.dtype), torch.as_tensor(params["scale"], device=input.device, dtype=input.dtype), torch.as_tensor(params["angle"], device=input.device, dtype=input.dtype), deg2rad( torch.as_tensor(params["sx"], device=input.device, dtype=input.dtype)), deg2rad( torch.as_tensor(params["sy"], device=input.device, dtype=input.dtype)), )
def angle_to_rotation_matrix(angle: torch.Tensor) -> torch.Tensor: r"""Create 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 = 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)
def get_rotation_matrix2d(center: torch.Tensor, angle: torch.Tensor, scale: torch.Tensor) -> torch.Tensor: r"""Calculates an affine matrix of 2D rotation. The function calculates the following matrix: .. math:: \begin{bmatrix} \alpha & \beta & (1 - \alpha) \cdot \text{x} - \beta \cdot \text{y} \\ -\beta & \alpha & \beta \cdot \text{x} + (1 - \alpha) \cdot \text{y} \end{bmatrix} where .. math:: \alpha = \text{scale} \cdot cos(\text{angle}) \\ \beta = \text{scale} \cdot sin(\text{angle}) The transformation maps the rotation center to itself If this is not the target, adjust the shift. Args: center (Tensor): center of the rotation in the source image. angle (Tensor): rotation angle in degrees. Positive values mean counter-clockwise rotation (the coordinate origin is assumed to be the top-left corner). scale (Tensor): isotropic scale factor. Returns: Tensor: the affine matrix of 2D rotation. Shape: - Input: :math:`(B, 2)`, :math:`(B)` and :math:`(B)` - Output: :math:`(B, 2, 3)` Example: >>> center = torch.zeros(1, 2) >>> scale = torch.ones(1) >>> angle = 45. * torch.ones(1) >>> M = kornia.get_rotation_matrix2d(center, angle, scale) tensor([[[ 0.7071, 0.7071, 0.0000], [-0.7071, 0.7071, 0.0000]]]) """ if not torch.is_tensor(center): raise TypeError( "Input center type is not a torch.Tensor. Got {}".format( type(center))) if not torch.is_tensor(angle): raise TypeError( "Input angle type is not a torch.Tensor. Got {}".format( type(angle))) if not torch.is_tensor(scale): raise TypeError( "Input scale type is not a torch.Tensor. Got {}".format( type(scale))) if not (len(center.shape) == 2 and center.shape[1] == 2): raise ValueError("Input center must be a Bx2 tensor. Got {}".format( center.shape)) if not len(angle.shape) == 1: raise ValueError("Input angle must be a B tensor. Got {}".format( angle.shape)) if not len(scale.shape) == 1: raise ValueError("Input scale must be a B tensor. Got {}".format( scale.shape)) if not (center.shape[0] == angle.shape[0] == scale.shape[0]): raise ValueError( "Inputs must have same batch size dimension. Got {}".format( center.shape, angle.shape, scale.shape)) # convert angle and apply scale angle_rad: torch.Tensor = deg2rad(angle) alpha: torch.Tensor = torch.cos(angle_rad) * scale beta: torch.Tensor = torch.sin(angle_rad) * scale # unpack the center to x, y coordinates x: torch.Tensor = center[..., 0] y: torch.Tensor = center[..., 1] # create output tensor batch_size: int = center.shape[0] M: torch.Tensor = torch.zeros(batch_size, 2, 3, device=center.device, dtype=center.dtype) M[..., 0, 0] = alpha M[..., 0, 1] = beta M[..., 0, 2] = (torch.tensor(1.) - alpha) * x - beta * y M[..., 1, 0] = -beta M[..., 1, 1] = alpha M[..., 1, 2] = beta * x + (torch.tensor(1.) - alpha) * y return M