def normalize_homography(dst_pix_trans_src_pix: torch.Tensor, dsize_src: Tuple[int, int], dsize_dst: Tuple[int, int]) -> torch.Tensor: __doc__ = HMW.normalize_homography.__doc__ warnings.warn( "`normalize_homography` is deprecated and will be removed > 0.6.0. " "Please use `kornia.geometry.transform.normalize_homography instead.`", DeprecationWarning, stacklevel=2) return HMW.normalize_homography(dst_pix_trans_src_pix, dsize_src, dsize_dst)
def transform_warp_impl(src: torch.Tensor, dst_pix_trans_src_pix: torch.Tensor, dsize_src: Tuple[int, int], dsize_dst: Tuple[int, int], grid_mode: str, padding_mode: str, align_corners: bool) -> torch.Tensor: """Compute the transform in normalized coordinates and perform the warping. """ dst_norm_trans_src_norm: torch.Tensor = normalize_homography( dst_pix_trans_src_pix, dsize_src, dsize_dst) src_norm_trans_dst_norm = torch.inverse(dst_norm_trans_src_norm) return homography_warp(src, src_norm_trans_dst_norm, dsize_dst, grid_mode, padding_mode, align_corners, True)
def warp_perspective( src: torch.Tensor, M: torch.Tensor, dsize: Tuple[int, int], mode: str = 'bilinear', padding_mode: str = 'zeros', align_corners: Optional[bool] = None, ) -> torch.Tensor: r"""Applies a perspective transformation to an image. .. image:: https://kornia-tutorials.readthedocs.io/en/latest/_images/warp_perspective_10_2.png The function warp_perspective transforms the source image using the specified matrix: .. math:: \text{dst} (x, y) = \text{src} \left( \frac{M^{-1}_{11} x + M^{-1}_{12} y + M^{-1}_{13}}{M^{-1}_{31} x + M^{-1}_{32} y + M^{-1}_{33}} , \frac{M^{-1}_{21} x + M^{-1}_{22} y + M^{-1}_{23}}{M^{-1}_{31} x + M^{-1}_{32} y + M^{-1}_{33}} \right ) Args: src: input image with shape :math:`(B, C, H, W)`. M: transformation matrix with shape :math:`(B, 3, 3)`. dsize: size of the output image (height, width). mode: interpolation mode to calculate output values ``'bilinear'`` | ``'nearest'``. padding_mode: padding mode for outside grid values ``'zeros'`` | ``'border'`` | ``'reflection'``. align_corners(bool, optional): interpolation flag. Returns: the warped input image :math:`(B, C, H, W)`. Example: >>> img = torch.rand(1, 4, 5, 6) >>> H = torch.eye(3)[None] >>> out = warp_perspective(img, H, (4, 2), align_corners=True) >>> print(out.shape) torch.Size([1, 4, 4, 2]) .. note:: This function is often used in conjuntion with :func:`get_perspective_transform`. .. note:: See a working example `here <https://kornia-tutorials.readthedocs.io/en/ latest/warp_perspective.html>`_. """ if not isinstance(src, torch.Tensor): raise TypeError("Input src type is not a torch.Tensor. Got {}".format( type(src))) if not isinstance(M, torch.Tensor): raise TypeError("Input M type is not a torch.Tensor. Got {}".format( type(M))) if not len(src.shape) == 4: raise ValueError("Input src must be a BxCxHxW tensor. Got {}".format( src.shape)) if not (len(M.shape) == 3 and M.shape[-2:] == (3, 3)): raise ValueError("Input M must be a Bx3x3 tensor. Got {}".format( M.shape)) # TODO: remove the statement below in kornia v0.6 if align_corners is None: message: str = ( "The align_corners default value has been changed. By default now is set True " "in order to match cv2.warpPerspective. In case you want to keep your previous " "behaviour set it to False. This warning will disappear in kornia > v0.6." ) warnings.warn(message) # set default value for align corners align_corners = True B, C, H, W = src.size() h_out, w_out = dsize # we normalize the 3x3 transformation matrix and convert to 3x4 dst_norm_trans_src_norm: torch.Tensor = normalize_homography( M, (H, W), (h_out, w_out)) # Bx3x3 src_norm_trans_dst_norm = _torch_inverse_cast( dst_norm_trans_src_norm) # Bx3x3 # this piece of code substitutes F.affine_grid since it does not support 3x3 grid = (create_meshgrid(h_out, w_out, normalized_coordinates=True, device=src.device).to(src.dtype).repeat( B, 1, 1, 1)) grid = transform_points(src_norm_trans_dst_norm[:, None, None], grid) return F.grid_sample(src, grid, align_corners=align_corners, mode=mode, padding_mode=padding_mode)
def warp_affine( src: torch.Tensor, M: torch.Tensor, dsize: Tuple[int, int], mode: str = 'bilinear', padding_mode: str = 'zeros', align_corners: Optional[bool] = None, ) -> torch.Tensor: r"""Applies an affine transformation to a tensor. .. image:: _static/img/warp_affine.png The function warp_affine transforms the source tensor using the specified matrix: .. math:: \text{dst}(x, y) = \text{src} \left( M_{11} x + M_{12} y + M_{13} , M_{21} x + M_{22} y + M_{23} \right ) Args: src: input tensor of shape :math:`(B, C, H, W)`. M: affine transformation of shape :math:`(B, 2, 3)`. dsize: size of the output image (height, width). mode: interpolation mode to calculate output values ``'bilinear'`` | ``'nearest'``. padding_mode (str): padding mode for outside grid values ``'zeros'`` | ``'border'`` | ``'reflection'``. align_corners : mode for grid_generation. Returns: the warped tensor with shape :math:`(B, C, H, W)`. Example: >>> img = torch.rand(1, 4, 5, 6) >>> A = torch.eye(2, 3)[None] >>> out = warp_affine(img, A, (4, 2), align_corners=True) >>> print(out.shape) torch.Size([1, 4, 4, 2]) .. note:: This function is often used in conjuntion with :func:`get_rotation_matrix2d`, :func:`get_shear_matrix2d`, :func:`get_affine_matrix2d`, :func:`invert_affine_transform`. .. note:: See a working example `here <https://kornia.readthedocs.io/en/latest/ tutorials/warp_affine.html>`__. """ if not isinstance(src, torch.Tensor): raise TypeError("Input src type is not a torch.Tensor. Got {}".format( type(src))) if not isinstance(M, torch.Tensor): raise TypeError("Input M type is not a torch.Tensor. Got {}".format( type(M))) if not len(src.shape) == 4: raise ValueError("Input src must be a BxCxHxW tensor. Got {}".format( src.shape)) if not (len(M.shape) == 3 or M.shape[-2:] == (2, 3)): raise ValueError("Input M must be a Bx2x3 tensor. Got {}".format( M.shape)) # TODO: remove the statement below in kornia v0.6 if align_corners is None: message: str = ( "The align_corners default value has been changed. By default now is set True " "in order to match cv2.warpAffine. In case you want to keep your previous " "behaviour set it to False. This warning will disappear in kornia > v0.6." ) warnings.warn(message) # set default value for align corners align_corners = True B, C, H, W = src.size() # we generate a 3x3 transformation matrix from 2x3 affine M_3x3: torch.Tensor = convert_affinematrix_to_homography(M) dst_norm_trans_src_norm: torch.Tensor = normalize_homography( M_3x3, (H, W), dsize) # src_norm_trans_dst_norm = torch.inverse(dst_norm_trans_src_norm) src_norm_trans_dst_norm = _torch_inverse_cast(dst_norm_trans_src_norm) grid = F.affine_grid(src_norm_trans_dst_norm[:, :2, :], [B, C, dsize[0], dsize[1]], align_corners=align_corners) return F.grid_sample(src, grid, align_corners=align_corners, mode=mode, padding_mode=padding_mode)
def warp_affine( src: torch.Tensor, M: torch.Tensor, dsize: Tuple[int, int], mode: str = 'bilinear', padding_mode: str = 'zeros', align_corners: bool = True, ) -> torch.Tensor: r"""Apply an affine transformation to a tensor. .. image:: _static/img/warp_affine.png The function warp_affine transforms the source tensor using the specified matrix: .. math:: \text{dst}(x, y) = \text{src} \left( M_{11} x + M_{12} y + M_{13} , M_{21} x + M_{22} y + M_{23} \right ) Args: src: input tensor of shape :math:`(B, C, H, W)`. M: affine transformation of shape :math:`(B, 2, 3)`. dsize: size of the output image (height, width). mode: interpolation mode to calculate output values ``'bilinear'`` | ``'nearest'``. padding_mode (str): padding mode for outside grid values ``'zeros'`` | ``'border'`` | ``'reflection'``. align_corners : mode for grid_generation. Returns: the warped tensor with shape :math:`(B, C, H, W)`. .. note:: This function is often used in conjunction with :func:`get_rotation_matrix2d`, :func:`get_shear_matrix2d`, :func:`get_affine_matrix2d`, :func:`invert_affine_transform`. .. note:: See a working example `here <https://kornia-tutorials.readthedocs.io/en/latest/ rotate_affine.html>`__. Example: >>> img = torch.rand(1, 4, 5, 6) >>> A = torch.eye(2, 3)[None] >>> out = warp_affine(img, A, (4, 2), align_corners=True) >>> print(out.shape) torch.Size([1, 4, 4, 2]) """ if not isinstance(src, torch.Tensor): raise TypeError(f"Input src type is not a torch.Tensor. Got {type(src)}") if not isinstance(M, torch.Tensor): raise TypeError(f"Input M type is not a torch.Tensor. Got {type(M)}") if not len(src.shape) == 4: raise ValueError(f"Input src must be a BxCxHxW tensor. Got {src.shape}") if not (len(M.shape) == 3 or M.shape[-2:] == (2, 3)): raise ValueError(f"Input M must be a Bx2x3 tensor. Got {M.shape}") B, C, H, W = src.size() # we generate a 3x3 transformation matrix from 2x3 affine M_3x3: torch.Tensor = convert_affinematrix_to_homography(M) dst_norm_trans_src_norm: torch.Tensor = normalize_homography(M_3x3, (H, W), dsize) # src_norm_trans_dst_norm = torch.inverse(dst_norm_trans_src_norm) src_norm_trans_dst_norm = _torch_inverse_cast(dst_norm_trans_src_norm) grid = F.affine_grid(src_norm_trans_dst_norm[:, :2, :], [B, C, dsize[0], dsize[1]], align_corners=align_corners) return F.grid_sample(src, grid, align_corners=align_corners, mode=mode, padding_mode=padding_mode)
def warp_affine(src: torch.Tensor, M: torch.Tensor, dsize: Tuple[int, int], flags: str = 'bilinear', padding_mode: str = 'zeros', align_corners: bool = False) -> torch.Tensor: r"""Applies an affine transformation to a tensor. The function warp_affine transforms the source tensor using the specified matrix: .. math:: \text{dst}(x, y) = \text{src} \left( M_{11} x + M_{12} y + M_{13} , M_{21} x + M_{22} y + M_{23} \right ) Args: src (torch.Tensor): input tensor of shape :math:`(B, C, H, W)`. M (torch.Tensor): affine transformation of shape :math:`(B, 2, 3)`. dsize (Tuple[int, int]): size of the output image (height, width). mode (str): interpolation mode to calculate output values 'bilinear' | 'nearest'. Default: 'bilinear'. padding_mode (str): padding mode for outside grid values 'zeros' | 'border' | 'reflection'. Default: 'zeros'. align_corners (bool): mode for grid_generation. Default: False. Returns: torch.Tensor: the warped tensor with shape :math:`(B, C, H, W)`. .. note:: See a working example `here <https://kornia.readthedocs.io/en/latest/ tutorials/warp_affine.html>`__. """ if not isinstance(src, torch.Tensor): raise TypeError("Input src type is not a torch.Tensor. Got {}".format( type(src))) if not isinstance(M, torch.Tensor): raise TypeError("Input M type is not a torch.Tensor. Got {}".format( type(M))) if not len(src.shape) == 4: raise ValueError("Input src must be a BxCxHxW tensor. Got {}".format( src.shape)) if not (len(M.shape) == 3 or M.shape[-2:] == (2, 3)): raise ValueError("Input M must be a Bx2x3 tensor. Got {}".format( M.shape)) B, C, H, W = src.size() dsize_src = (H, W) out_size = dsize # we generate a 3x3 transformation matrix from 2x3 affine M_3x3: torch.Tensor = convert_affinematrix_to_homography(M) dst_norm_trans_src_norm: torch.Tensor = normalize_homography( M_3x3, dsize_src, out_size) src_norm_trans_dst_norm = torch.inverse(dst_norm_trans_src_norm) grid = F.affine_grid(src_norm_trans_dst_norm[:, :2, :], [B, C, out_size[0], out_size[1]], align_corners=align_corners) return F.grid_sample(src, grid, align_corners=align_corners, mode=flags, padding_mode=padding_mode)