def test_smoke(self, padding, device, dtype): kernel = torch.rand(1, 3, 3, device=device, dtype=dtype) _, height, width = kernel.shape input = torch.ones(1, 1, 7, 8, device=device, dtype=dtype) b, c, h, w = input.shape if padding == 'same': out = kornia.filter2d(input, kernel, padding=padding) assert out.shape == (b, c, h, w) else: out = kornia.filter2d(input, kernel, padding=padding) assert out.shape == (b, c, h - height + 1, w - width + 1)
def gaussian_blur2d( input: torch.Tensor, kernel_size: Tuple[int, int], sigma: Tuple[float, float], border_type: str = 'reflect' ) -> torch.Tensor: r"""Create an operator that blurs a tensor using a Gaussian filter. .. image:: _static/img/gaussian_blur2d.png The operator smooths the given tensor with a gaussian kernel by convolving it to each channel. It supports batched operation. Arguments: input: the input tensor with shape :math:`(B,C,H,W)`. kernel_size: the size of the kernel. sigma: the standard deviation of the kernel. border_type: the padding mode to be applied before convolving. The expected modes are: ``'constant'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Default: ``'reflect'``. Returns: the blurred tensor with shape :math:`(B, C, H, W)`. .. note:: See a working example `here <https://kornia-tutorials.readthedocs.io/en/latest/ gaussian_blur.html>`__. Examples: >>> input = torch.rand(2, 4, 5, 5) >>> output = gaussian_blur2d(input, (3, 3), (1.5, 1.5)) >>> output.shape torch.Size([2, 4, 5, 5]) """ kernel: torch.Tensor = torch.unsqueeze(get_gaussian_kernel2d(kernel_size, sigma), dim=0) return kornia.filter2d(input, kernel, border_type)
def laplacian(input: torch.Tensor, kernel_size: int, border_type: str = 'reflect', normalized: bool = True) -> torch.Tensor: r"""Creates an operator that returns a tensor using a Laplacian filter. The operator smooths the given tensor with a laplacian kernel by convolving it to each channel. It supports batched operation. Arguments: input (torch.Tensor): the input image tensor with shape :math:`(B, C, H, W)`. kernel_size (int): the size of the kernel. border_type (str): the padding mode to be applied before convolving. The expected modes are: ``'constant'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Default: ``'reflect'``. normalized (bool): if True, L1 norm of the kernel is set to 1. Return: torch.Tensor: the blurred image with shape :math:`(B, C, H, W)`. Examples: >>> input = torch.rand(2, 4, 5, 5) >>> output = laplacian(input, 3) >>> output.shape torch.Size([2, 4, 5, 5]) """ kernel: torch.Tensor = torch.unsqueeze(get_laplacian_kernel2d(kernel_size), dim=0) if normalized: kernel = normalize_kernel2d(kernel) return kornia.filter2d(input, kernel, border_type)
def test_normalized_mean_filter(self, device, dtype): kernel = torch.ones(1, 3, 3).to(device) input = torch.tensor( [[[ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 5.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ]]], device=device, dtype=dtype, ).expand(2, 2, -1, -1) nv: float = 5.0 / 9 # normalization value expected = torch.tensor( [[[ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, nv, nv, nv, 0.0], [0.0, nv, nv, nv, 0.0], [0.0, nv, nv, nv, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ]]], device=device, dtype=dtype, ).expand(2, 2, -1, -1) actual = kornia.filter2d(input, kernel, normalized=True) tol_val: float = utils._get_precision_by_name(device, 'xla', 1e-1, 1e-4) assert_allclose(actual, expected, rtol=tol_val, atol=tol_val)
def test_mean_filter_2batch_2ch(self, device, dtype): kernel = torch.ones(1, 3, 3, device=device, dtype=dtype) input = torch.tensor( [[[ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 5.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ]]], device=device, dtype=dtype, ).expand(2, 2, -1, -1) expected = torch.tensor( [[[ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 5.0, 5.0, 0.0], [0.0, 5.0, 5.0, 5.0, 0.0], [0.0, 5.0, 5.0, 5.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ]]], device=device, dtype=dtype, ).expand(2, 2, -1, -1) actual = kornia.filter2d(input, kernel) assert_allclose(actual, expected)
def test_even_sized_filter(self, device, dtype): kernel = torch.ones(1, 2, 2, device=device, dtype=dtype) input = torch.tensor( [[[ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 5.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ]]], device=device, dtype=dtype, ) expected = torch.tensor( [[[ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 5.0, 0.0, 0.0], [0.0, 5.0, 5.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ]]], device=device, dtype=dtype, ) actual = kornia.filter2d(input, kernel) assert_allclose(actual, expected)
def test_noncontiguous(self, padding, device, dtype): batch_size = 3 inp = torch.rand(3, 5, 5, device=device, dtype=dtype).expand(batch_size, -1, -1, -1) kernel = torch.ones(1, 2, 2, device=device, dtype=dtype) actual = kornia.filter2d(inp, kernel, padding=padding) assert_close(actual, actual)
def test_even_sized_filter(self, padding, device, dtype): kernel = torch.ones(1, 2, 2, device=device, dtype=dtype) input = torch.tensor( [ [ [ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 5.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ] ] ], device=device, dtype=dtype, ) expected_same = torch.tensor( [ [ [ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 5.0, 0.0, 0.0], [0.0, 5.0, 5.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ] ] ], device=device, dtype=dtype, ) expected_valid = torch.tensor( [ [ [ [0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 5.0, 0.0], [0.0, 5.0, 5.0, 0.0], [0.0, 0.0, 0.0, 0.0], ] ] ], device=device, dtype=dtype, ) actual = kornia.filter2d(input, kernel, padding=padding) if padding == 'same': assert_close(actual, expected_same) else: assert_close(actual, expected_valid)
def test_mean_filter_2batch_2ch(self, padding, device, dtype): kernel = torch.ones(1, 3, 3, device=device, dtype=dtype) input = torch.tensor( [ [ [ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 5.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ] ] ], device=device, dtype=dtype, ).expand(2, 2, -1, -1) expected_same = torch.tensor( [ [ [ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 5.0, 5.0, 0.0], [0.0, 5.0, 5.0, 5.0, 0.0], [0.0, 5.0, 5.0, 5.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ] ] ], device=device, dtype=dtype, ).expand(2, 2, -1, -1) expected_valid = torch.tensor( [ [ [ [5.0, 5.0, 5.0], [5.0, 5.0, 5.0], [5.0, 5.0, 5.0], ] ] ], device=device, dtype=dtype, ).expand(2, 2, -1, -1) actual = kornia.filter2d(input, kernel, padding=padding) if padding == 'same': assert_close(actual, expected_same) else: assert_close(actual, expected_valid)
def motion_blur( input: torch.Tensor, kernel_size: int, angle: Union[float, torch.Tensor], direction: Union[float, torch.Tensor], border_type: str = 'constant', mode: str = 'nearest', ) -> torch.Tensor: r"""Perform motion blur on tensor images. .. image:: _static/img/motion_blur.png Args: input: the input tensor with shape :math:`(B, C, H, W)`. kernel_size: motion kernel width and height. It should be odd and positive. angle (Union[torch.Tensor, float]): angle of the motion blur in degrees (anti-clockwise rotation). If tensor, it must be :math:`(B,)`. direction : forward/backward direction of the motion blur. Lower values towards -1.0 will point the motion blur towards the back (with angle provided via angle), while higher values towards 1.0 will point the motion blur forward. A value of 0.0 leads to a uniformly (but still angled) motion blur. If tensor, it must be :math:`(B,)`. border_type: the padding mode to be applied before convolving. The expected modes are: ``'constant'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Default: ``'constant'``. mode: interpolation mode for rotating the kernel. ``'bilinear'`` or ``'nearest'``. Return: the blurred image with shape :math:`(B, C, H, W)`. Example: >>> input = torch.randn(1, 3, 80, 90).repeat(2, 1, 1, 1) >>> # perform exact motion blur across the batch >>> out_1 = motion_blur(input, 5, 90., 1) >>> torch.allclose(out_1[0], out_1[1]) True >>> # perform element-wise motion blur across the batch >>> out_1 = motion_blur(input, 5, torch.tensor([90., 180,]), torch.tensor([1., -1.])) >>> torch.allclose(out_1[0], out_1[1]) False """ if border_type not in ["constant", "reflect", "replicate", "circular"]: raise AssertionError kernel: torch.Tensor = get_motion_kernel2d(kernel_size, angle, direction, mode) return kornia.filter2d(input, kernel, border_type)
def box_blur( input: torch.Tensor, kernel_size: Tuple[int, int], border_type: str = 'reflect', normalized: bool = True ) -> torch.Tensor: r"""Blur an image using the box filter. .. image:: _static/img/box_blur.png The function smooths an image using the kernel: .. math:: K = \frac{1}{\text{kernel_size}_x * \text{kernel_size}_y} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \end{bmatrix} Args: image: the image to blur with shape :math:`(B,C,H,W)`. kernel_size: the blurring kernel size. border_type: the padding mode to be applied before convolving. The expected modes are: ``'constant'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. normalized: if True, L1 norm of the kernel is set to 1. Returns: the blurred tensor with shape :math:`(B,C,H,W)`. .. note:: See a working example `here <https://kornia-tutorials.readthedocs.io/en/latest/ filtering_operators.html>`__. Example: >>> input = torch.rand(2, 4, 5, 7) >>> output = box_blur(input, (3, 3)) # 2x4x5x7 >>> output.shape torch.Size([2, 4, 5, 7]) """ kernel: torch.Tensor = get_box_kernel2d(kernel_size) if normalized: kernel = normalize_kernel2d(kernel) return kornia.filter2d(input, kernel, border_type)
def box_blur(input: torch.Tensor, kernel_size: Tuple[int, int], border_type: str = 'reflect', normalized: bool = True) -> torch.Tensor: r"""Blurs an image using the box filter. The function smooths an image using the kernel: .. math:: K = \frac{1}{\text{kernel_size}_x * \text{kernel_size}_y} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \end{bmatrix} Args: image (torch.Tensor): the image to blur with shape :math:`(B,C,H,W)`. kernel_size (Tuple[int, int]): the blurring kernel size. border_type (str): the padding mode to be applied before convolving. The expected modes are: ``'constant'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Default: ``'reflect'``. normalized (bool): if True, L1 norm of the kernel is set to 1. Returns: torch.Tensor: the blurred tensor with shape :math:`(B,C,H,W)`. Example: >>> input = torch.rand(2, 4, 5, 7) >>> output = box_blur(input, (3, 3)) # 2x4x5x7 >>> output.shape torch.Size([2, 4, 5, 7]) """ kernel: torch.Tensor = get_box_kernel2d(kernel_size) if normalized: kernel = normalize_kernel2d(kernel) return kornia.filter2d(input, kernel, border_type)
def laplacian( input: torch.Tensor, kernel_size: int, border_type: str = 'reflect', normalized: bool = True ) -> torch.Tensor: r"""Create an operator that returns a tensor using a Laplacian filter. .. image:: _static/img/laplacian.png The operator smooths the given tensor with a laplacian kernel by convolving it to each channel. It supports batched operation. Args: input: the input image tensor with shape :math:`(B, C, H, W)`. kernel_size: the size of the kernel. border_type: the padding mode to be applied before convolving. The expected modes are: ``'constant'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. normalized: if True, L1 norm of the kernel is set to 1. Return: the blurred image with shape :math:`(B, C, H, W)`. .. note:: See a working example `here <https://kornia-tutorials.readthedocs.io/en/latest/ filtering_edges.html>`__. Examples: >>> input = torch.rand(2, 4, 5, 5) >>> output = laplacian(input, 3) >>> output.shape torch.Size([2, 4, 5, 5]) """ kernel: torch.Tensor = torch.unsqueeze(get_laplacian_kernel2d(kernel_size), dim=0) if normalized: kernel = normalize_kernel2d(kernel) return kornia.filter2d(input, kernel, border_type)
def test_batch(self, batch_size, device, dtype): B: int = batch_size kernel = torch.rand(1, 3, 3, device=device, dtype=dtype) input = torch.ones(B, 3, 7, 8, device=device, dtype=dtype) assert kornia.filter2d(input, kernel).shape == input.shape
def test_smoke(self, device, dtype): kernel = torch.rand(1, 3, 3, device=device, dtype=dtype) input = torch.ones(1, 1, 7, 8, device=device, dtype=dtype) assert kornia.filter2d(input, kernel).shape == input.shape
def forward(self, x): f = self.f f = f[None, None, :] * f [None, :, None] return filter2d(x, f, normalized=True)