We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add more border_type options for filter2D
## 🚀 Feature
1. For filter2D, add border_types that are provided by **filter2** of **Matlab**.
    For example, border_type of 'valid':
      ```
      %     'valid' - returns only those parts of the correlation
      %               that are computed without the zero-padded
      %               edges, size(Y) < size(X).
      ```
2. If possible, add a border_type option for some loss functions (e.g. ssim_loss). This option is used to control the behavior of filter2D in ssim_loss.

## Motivation
In my field, some metrics were written by Matlab, and I have to migrate these codes into PyTorch. The issue is, the Matlab code used a border_type(i.e., "valid") that is not supported by Kornia, resulting in different scores between Matlab-version and PyTorch-version.

## Pitch
filter2D function will support "valid" border type.

## Alternatives
Don't think of any alternative solutions.

## Additional context




--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kornia/filters/filter.py`
Content:
```
1 from typing import List
2 
3 import torch
4 import torch.nn.functional as F
5 
6 from kornia.filters.__tmp__ import _deprecation_wrapper
7 from kornia.filters.kernels import normalize_kernel2d
8 
9 
10 def _compute_padding(kernel_size: List[int]) -> List[int]:
11     """Compute padding tuple."""
12     # 4 or 6 ints:  (padding_left, padding_right,padding_top,padding_bottom)
13     # https://pytorch.org/docs/stable/nn.html#torch.nn.functional.pad
14     if len(kernel_size) < 2:
15         raise AssertionError(kernel_size)
16     computed = [k // 2 for k in kernel_size]
17 
18     # for even kernels we need to do asymmetric padding :(
19 
20     out_padding = 2 * len(kernel_size) * [0]
21 
22     for i in range(len(kernel_size)):
23         computed_tmp = computed[-(i + 1)]
24         if kernel_size[i] % 2 == 0:
25             padding = computed_tmp - 1
26         else:
27             padding = computed_tmp
28         out_padding[2 * i + 0] = padding
29         out_padding[2 * i + 1] = computed_tmp
30     return out_padding
31 
32 
33 def filter2d(
34     input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'reflect', normalized: bool = False
35 ) -> torch.Tensor:
36     r"""Convolve a tensor with a 2d kernel.
37 
38     The function applies a given kernel to a tensor. The kernel is applied
39     independently at each depth channel of the tensor. Before applying the
40     kernel, the function applies padding according to the specified mode so
41     that the output remains in the same shape.
42 
43     Args:
44         input: the input tensor with shape of
45           :math:`(B, C, H, W)`.
46         kernel: the kernel to be convolved with the input
47           tensor. The kernel shape must be :math:`(1, kH, kW)` or :math:`(B, kH, kW)`.
48         border_type: the padding mode to be applied before convolving.
49           The expected modes are: ``'constant'``, ``'reflect'``,
50           ``'replicate'`` or ``'circular'``.
51         normalized: If True, kernel will be L1 normalized.
52 
53     Return:
54         torch.Tensor: the convolved tensor of same size and numbers of channels
55         as the input with shape :math:`(B, C, H, W)`.
56 
57     Example:
58         >>> input = torch.tensor([[[
59         ...    [0., 0., 0., 0., 0.],
60         ...    [0., 0., 0., 0., 0.],
61         ...    [0., 0., 5., 0., 0.],
62         ...    [0., 0., 0., 0., 0.],
63         ...    [0., 0., 0., 0., 0.],]]])
64         >>> kernel = torch.ones(1, 3, 3)
65         >>> filter2d(input, kernel)
66         tensor([[[[0., 0., 0., 0., 0.],
67                   [0., 5., 5., 5., 0.],
68                   [0., 5., 5., 5., 0.],
69                   [0., 5., 5., 5., 0.],
70                   [0., 0., 0., 0., 0.]]]])
71     """
72     if not isinstance(input, torch.Tensor):
73         raise TypeError(f"Input border_type is not torch.Tensor. Got {type(input)}")
74 
75     if not isinstance(kernel, torch.Tensor):
76         raise TypeError(f"Input border_type is not torch.Tensor. Got {type(kernel)}")
77 
78     if not isinstance(border_type, str):
79         raise TypeError(f"Input border_type is not string. Got {type(kernel)}")
80 
81     if not len(input.shape) == 4:
82         raise ValueError(f"Invalid input shape, we expect BxCxHxW. Got: {input.shape}")
83 
84     if not len(kernel.shape) == 3 and kernel.shape[0] != 1:
85         raise ValueError(f"Invalid kernel shape, we expect 1xHxW. Got: {kernel.shape}")
86 
87     # prepare kernel
88     b, c, h, w = input.shape
89     tmp_kernel: torch.Tensor = kernel.unsqueeze(1).to(input)
90 
91     if normalized:
92         tmp_kernel = normalize_kernel2d(tmp_kernel)
93 
94     tmp_kernel = tmp_kernel.expand(-1, c, -1, -1)
95 
96     # pad the input tensor
97     height, width = tmp_kernel.shape[-2:]
98     padding_shape: List[int] = _compute_padding([height, width])
99     input_pad: torch.Tensor = F.pad(input, padding_shape, mode=border_type)
100 
101     # kernel and input tensor reshape to align element-wise or batch-wise params
102     tmp_kernel = tmp_kernel.reshape(-1, 1, height, width)
103     input_pad = input_pad.view(-1, tmp_kernel.size(0), input_pad.size(-2), input_pad.size(-1))
104 
105     # convolve the tensor with the kernel.
106     output = F.conv2d(input_pad, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)
107 
108     return output.view(b, c, h, w)
109 
110 
111 def filter3d(
112     input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'replicate', normalized: bool = False
113 ) -> torch.Tensor:
114     r"""Convolve a tensor with a 3d kernel.
115 
116     The function applies a given kernel to a tensor. The kernel is applied
117     independently at each depth channel of the tensor. Before applying the
118     kernel, the function applies padding according to the specified mode so
119     that the output remains in the same shape.
120 
121     Args:
122         input: the input tensor with shape of
123           :math:`(B, C, D, H, W)`.
124         kernel: the kernel to be convolved with the input
125           tensor. The kernel shape must be :math:`(1, kD, kH, kW)`  or :math:`(B, kD, kH, kW)`.
126         border_type: the padding mode to be applied before convolving.
127           The expected modes are: ``'constant'``,
128           ``'replicate'`` or ``'circular'``.
129         normalized: If True, kernel will be L1 normalized.
130 
131     Return:
132         the convolved tensor of same size and numbers of channels
133         as the input with shape :math:`(B, C, D, H, W)`.
134 
135     Example:
136         >>> input = torch.tensor([[[
137         ...    [[0., 0., 0., 0., 0.],
138         ...     [0., 0., 0., 0., 0.],
139         ...     [0., 0., 0., 0., 0.],
140         ...     [0., 0., 0., 0., 0.],
141         ...     [0., 0., 0., 0., 0.]],
142         ...    [[0., 0., 0., 0., 0.],
143         ...     [0., 0., 0., 0., 0.],
144         ...     [0., 0., 5., 0., 0.],
145         ...     [0., 0., 0., 0., 0.],
146         ...     [0., 0., 0., 0., 0.]],
147         ...    [[0., 0., 0., 0., 0.],
148         ...     [0., 0., 0., 0., 0.],
149         ...     [0., 0., 0., 0., 0.],
150         ...     [0., 0., 0., 0., 0.],
151         ...     [0., 0., 0., 0., 0.]]
152         ... ]]])
153         >>> kernel = torch.ones(1, 3, 3, 3)
154         >>> filter3d(input, kernel)
155         tensor([[[[[0., 0., 0., 0., 0.],
156                    [0., 5., 5., 5., 0.],
157                    [0., 5., 5., 5., 0.],
158                    [0., 5., 5., 5., 0.],
159                    [0., 0., 0., 0., 0.]],
160         <BLANKLINE>
161                   [[0., 0., 0., 0., 0.],
162                    [0., 5., 5., 5., 0.],
163                    [0., 5., 5., 5., 0.],
164                    [0., 5., 5., 5., 0.],
165                    [0., 0., 0., 0., 0.]],
166         <BLANKLINE>
167                   [[0., 0., 0., 0., 0.],
168                    [0., 5., 5., 5., 0.],
169                    [0., 5., 5., 5., 0.],
170                    [0., 5., 5., 5., 0.],
171                    [0., 0., 0., 0., 0.]]]]])
172     """
173     if not isinstance(input, torch.Tensor):
174         raise TypeError(f"Input border_type is not torch.Tensor. Got {type(input)}")
175 
176     if not isinstance(kernel, torch.Tensor):
177         raise TypeError(f"Input border_type is not torch.Tensor. Got {type(kernel)}")
178 
179     if not isinstance(border_type, str):
180         raise TypeError(f"Input border_type is not string. Got {type(kernel)}")
181 
182     if not len(input.shape) == 5:
183         raise ValueError(f"Invalid input shape, we expect BxCxDxHxW. Got: {input.shape}")
184 
185     if not len(kernel.shape) == 4 and kernel.shape[0] != 1:
186         raise ValueError(f"Invalid kernel shape, we expect 1xDxHxW. Got: {kernel.shape}")
187 
188     # prepare kernel
189     b, c, d, h, w = input.shape
190     tmp_kernel: torch.Tensor = kernel.unsqueeze(1).to(input)
191 
192     if normalized:
193         bk, dk, hk, wk = kernel.shape
194         tmp_kernel = normalize_kernel2d(tmp_kernel.view(bk, dk, hk * wk)).view_as(tmp_kernel)
195 
196     tmp_kernel = tmp_kernel.expand(-1, c, -1, -1, -1)
197 
198     # pad the input tensor
199     depth, height, width = tmp_kernel.shape[-3:]
200     padding_shape: List[int] = _compute_padding([depth, height, width])
201     input_pad: torch.Tensor = F.pad(input, padding_shape, mode=border_type)
202 
203     # kernel and input tensor reshape to align element-wise or batch-wise params
204     tmp_kernel = tmp_kernel.reshape(-1, 1, depth, height, width)
205     input_pad = input_pad.view(-1, tmp_kernel.size(0), input_pad.size(-3), input_pad.size(-2), input_pad.size(-1))
206 
207     # convolve the tensor with the kernel.
208     output = F.conv3d(input_pad, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)
209 
210     return output.view(b, c, d, h, w)
211 
212 
213 # for backward compatibility.
214 filter2D = _deprecation_wrapper(filter2d, 'filter2D')
215 filter3D = _deprecation_wrapper(filter3d, 'filter3D')
216
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kornia/filters/filter.py b/kornia/filters/filter.py
--- a/kornia/filters/filter.py
+++ b/kornia/filters/filter.py
@@ -31,7 +31,8 @@
 
 
 def filter2d(
-    input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'reflect', normalized: bool = False
+    input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'reflect', normalized: bool = False,
+    padding: str = 'same'
 ) -> torch.Tensor:
     r"""Convolve a tensor with a 2d kernel.
 
@@ -49,6 +50,8 @@
           The expected modes are: ``'constant'``, ``'reflect'``,
           ``'replicate'`` or ``'circular'``.
         normalized: If True, kernel will be L1 normalized.
+        padding: This defines the type of padding.
+          2 modes available ``'same'`` or ``'valid'``.
 
     Return:
         torch.Tensor: the convolved tensor of same size and numbers of channels
@@ -62,7 +65,7 @@
         ...    [0., 0., 0., 0., 0.],
         ...    [0., 0., 0., 0., 0.],]]])
         >>> kernel = torch.ones(1, 3, 3)
-        >>> filter2d(input, kernel)
+        >>> filter2d(input, kernel, padding='same')
         tensor([[[[0., 0., 0., 0., 0.],
                   [0., 5., 5., 5., 0.],
                   [0., 5., 5., 5., 0.],
@@ -78,6 +81,12 @@
     if not isinstance(border_type, str):
         raise TypeError(f"Input border_type is not string. Got {type(kernel)}")
 
+    if not isinstance(padding, str):
+        raise TypeError(f"Input padding is not string. Got {type(padding)}")
+
+    if padding not in ['valid', 'same']:
+        raise ValueError(f"Invalid padding mode, we expect 'valid' or 'same'. Got: {padding}")
+
     if not len(input.shape) == 4:
         raise ValueError(f"Invalid input shape, we expect BxCxHxW. Got: {input.shape}")
 
@@ -93,19 +102,26 @@
 
     tmp_kernel = tmp_kernel.expand(-1, c, -1, -1)
 
-    # pad the input tensor
     height, width = tmp_kernel.shape[-2:]
-    padding_shape: List[int] = _compute_padding([height, width])
-    input_pad: torch.Tensor = F.pad(input, padding_shape, mode=border_type)
+
+    # pad the input tensor
+    if padding == 'same':
+        padding_shape: List[int] = _compute_padding([height, width])
+        input = F.pad(input, padding_shape, mode=border_type)
 
     # kernel and input tensor reshape to align element-wise or batch-wise params
     tmp_kernel = tmp_kernel.reshape(-1, 1, height, width)
-    input_pad = input_pad.view(-1, tmp_kernel.size(0), input_pad.size(-2), input_pad.size(-1))
+    input = input.view(-1, tmp_kernel.size(0), input.size(-2), input.size(-1))
 
     # convolve the tensor with the kernel.
-    output = F.conv2d(input_pad, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)
+    output = F.conv2d(input, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)
+
+    if padding == 'same':
+        out = output.view(b, c, h, w)
+    else:
+        out = output.view(b, c, h - height + 1, w - width + 1)
 
-    return output.view(b, c, h, w)
+    return out
 
 
 def filter3d(

{"golden_diff": "diff --git a/kornia/filters/filter.py b/kornia/filters/filter.py\n--- a/kornia/filters/filter.py\n+++ b/kornia/filters/filter.py\n@@ -31,7 +31,8 @@\n \n \n def filter2d(\n-    input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'reflect', normalized: bool = False\n+    input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'reflect', normalized: bool = False,\n+    padding: str = 'same'\n ) -> torch.Tensor:\n     r\"\"\"Convolve a tensor with a 2d kernel.\n \n@@ -49,6 +50,8 @@\n           The expected modes are: ``'constant'``, ``'reflect'``,\n           ``'replicate'`` or ``'circular'``.\n         normalized: If True, kernel will be L1 normalized.\n+        padding: This defines the type of padding.\n+          2 modes available ``'same'`` or ``'valid'``.\n \n     Return:\n         torch.Tensor: the convolved tensor of same size and numbers of channels\n@@ -62,7 +65,7 @@\n         ...    [0., 0., 0., 0., 0.],\n         ...    [0., 0., 0., 0., 0.],]]])\n         >>> kernel = torch.ones(1, 3, 3)\n-        >>> filter2d(input, kernel)\n+        >>> filter2d(input, kernel, padding='same')\n         tensor([[[[0., 0., 0., 0., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n@@ -78,6 +81,12 @@\n     if not isinstance(border_type, str):\n         raise TypeError(f\"Input border_type is not string. Got {type(kernel)}\")\n \n+    if not isinstance(padding, str):\n+        raise TypeError(f\"Input padding is not string. Got {type(padding)}\")\n+\n+    if padding not in ['valid', 'same']:\n+        raise ValueError(f\"Invalid padding mode, we expect 'valid' or 'same'. Got: {padding}\")\n+\n     if not len(input.shape) == 4:\n         raise ValueError(f\"Invalid input shape, we expect BxCxHxW. Got: {input.shape}\")\n \n@@ -93,19 +102,26 @@\n \n     tmp_kernel = tmp_kernel.expand(-1, c, -1, -1)\n \n-    # pad the input tensor\n     height, width = tmp_kernel.shape[-2:]\n-    padding_shape: List[int] = _compute_padding([height, width])\n-    input_pad: torch.Tensor = F.pad(input, padding_shape, mode=border_type)\n+\n+    # pad the input tensor\n+    if padding == 'same':\n+        padding_shape: List[int] = _compute_padding([height, width])\n+        input = F.pad(input, padding_shape, mode=border_type)\n \n     # kernel and input tensor reshape to align element-wise or batch-wise params\n     tmp_kernel = tmp_kernel.reshape(-1, 1, height, width)\n-    input_pad = input_pad.view(-1, tmp_kernel.size(0), input_pad.size(-2), input_pad.size(-1))\n+    input = input.view(-1, tmp_kernel.size(0), input.size(-2), input.size(-1))\n \n     # convolve the tensor with the kernel.\n-    output = F.conv2d(input_pad, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)\n+    output = F.conv2d(input, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)\n+\n+    if padding == 'same':\n+        out = output.view(b, c, h, w)\n+    else:\n+        out = output.view(b, c, h - height + 1, w - width + 1)\n \n-    return output.view(b, c, h, w)\n+    return out\n \n \n def filter3d(\n", "issue": "Add more border_type options for filter2D\n## \ud83d\ude80 Feature\r\n1. For filter2D, add border_types that are provided by **filter2** of **Matlab**.\r\n    For example, border_type of 'valid':\r\n      ```\r\n      %     'valid' - returns only those parts of the correlation\r\n      %               that are computed without the zero-padded\r\n      %               edges, size(Y) < size(X).\r\n      ```\r\n2. If possible, add a border_type option for some loss functions (e.g. ssim_loss). This option is used to control the behavior of filter2D in ssim_loss.\r\n\r\n## Motivation\r\nIn my field, some metrics were written by Matlab, and I have to migrate these codes into PyTorch. The issue is, the Matlab code used a border_type(i.e., \"valid\") that is not supported by Kornia, resulting in different scores between Matlab-version and PyTorch-version.\r\n\r\n## Pitch\r\nfilter2D function will support \"valid\" border type.\r\n\r\n## Alternatives\r\nDon't think of any alternative solutions.\r\n\r\n## Additional context\r\n\r\n\r\n\n", "before_files": [{"content": "from typing import List\n\nimport torch\nimport torch.nn.functional as F\n\nfrom kornia.filters.__tmp__ import _deprecation_wrapper\nfrom kornia.filters.kernels import normalize_kernel2d\n\n\ndef _compute_padding(kernel_size: List[int]) -> List[int]:\n    \"\"\"Compute padding tuple.\"\"\"\n    # 4 or 6 ints:  (padding_left, padding_right,padding_top,padding_bottom)\n    # https://pytorch.org/docs/stable/nn.html#torch.nn.functional.pad\n    if len(kernel_size) < 2:\n        raise AssertionError(kernel_size)\n    computed = [k // 2 for k in kernel_size]\n\n    # for even kernels we need to do asymmetric padding :(\n\n    out_padding = 2 * len(kernel_size) * [0]\n\n    for i in range(len(kernel_size)):\n        computed_tmp = computed[-(i + 1)]\n        if kernel_size[i] % 2 == 0:\n            padding = computed_tmp - 1\n        else:\n            padding = computed_tmp\n        out_padding[2 * i + 0] = padding\n        out_padding[2 * i + 1] = computed_tmp\n    return out_padding\n\n\ndef filter2d(\n    input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'reflect', normalized: bool = False\n) -> torch.Tensor:\n    r\"\"\"Convolve a tensor with a 2d kernel.\n\n    The function applies a given kernel to a tensor. The kernel is applied\n    independently at each depth channel of the tensor. Before applying the\n    kernel, the function applies padding according to the specified mode so\n    that the output remains in the same shape.\n\n    Args:\n        input: the input tensor with shape of\n          :math:`(B, C, H, W)`.\n        kernel: the kernel to be convolved with the input\n          tensor. The kernel shape must be :math:`(1, kH, kW)` or :math:`(B, kH, kW)`.\n        border_type: the padding mode to be applied before convolving.\n          The expected modes are: ``'constant'``, ``'reflect'``,\n          ``'replicate'`` or ``'circular'``.\n        normalized: If True, kernel will be L1 normalized.\n\n    Return:\n        torch.Tensor: the convolved tensor of same size and numbers of channels\n        as the input with shape :math:`(B, C, H, W)`.\n\n    Example:\n        >>> input = torch.tensor([[[\n        ...    [0., 0., 0., 0., 0.],\n        ...    [0., 0., 0., 0., 0.],\n        ...    [0., 0., 5., 0., 0.],\n        ...    [0., 0., 0., 0., 0.],\n        ...    [0., 0., 0., 0., 0.],]]])\n        >>> kernel = torch.ones(1, 3, 3)\n        >>> filter2d(input, kernel)\n        tensor([[[[0., 0., 0., 0., 0.],\n                  [0., 5., 5., 5., 0.],\n                  [0., 5., 5., 5., 0.],\n                  [0., 5., 5., 5., 0.],\n                  [0., 0., 0., 0., 0.]]]])\n    \"\"\"\n    if not isinstance(input, torch.Tensor):\n        raise TypeError(f\"Input border_type is not torch.Tensor. Got {type(input)}\")\n\n    if not isinstance(kernel, torch.Tensor):\n        raise TypeError(f\"Input border_type is not torch.Tensor. Got {type(kernel)}\")\n\n    if not isinstance(border_type, str):\n        raise TypeError(f\"Input border_type is not string. Got {type(kernel)}\")\n\n    if not len(input.shape) == 4:\n        raise ValueError(f\"Invalid input shape, we expect BxCxHxW. Got: {input.shape}\")\n\n    if not len(kernel.shape) == 3 and kernel.shape[0] != 1:\n        raise ValueError(f\"Invalid kernel shape, we expect 1xHxW. Got: {kernel.shape}\")\n\n    # prepare kernel\n    b, c, h, w = input.shape\n    tmp_kernel: torch.Tensor = kernel.unsqueeze(1).to(input)\n\n    if normalized:\n        tmp_kernel = normalize_kernel2d(tmp_kernel)\n\n    tmp_kernel = tmp_kernel.expand(-1, c, -1, -1)\n\n    # pad the input tensor\n    height, width = tmp_kernel.shape[-2:]\n    padding_shape: List[int] = _compute_padding([height, width])\n    input_pad: torch.Tensor = F.pad(input, padding_shape, mode=border_type)\n\n    # kernel and input tensor reshape to align element-wise or batch-wise params\n    tmp_kernel = tmp_kernel.reshape(-1, 1, height, width)\n    input_pad = input_pad.view(-1, tmp_kernel.size(0), input_pad.size(-2), input_pad.size(-1))\n\n    # convolve the tensor with the kernel.\n    output = F.conv2d(input_pad, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)\n\n    return output.view(b, c, h, w)\n\n\ndef filter3d(\n    input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'replicate', normalized: bool = False\n) -> torch.Tensor:\n    r\"\"\"Convolve a tensor with a 3d kernel.\n\n    The function applies a given kernel to a tensor. The kernel is applied\n    independently at each depth channel of the tensor. Before applying the\n    kernel, the function applies padding according to the specified mode so\n    that the output remains in the same shape.\n\n    Args:\n        input: the input tensor with shape of\n          :math:`(B, C, D, H, W)`.\n        kernel: the kernel to be convolved with the input\n          tensor. The kernel shape must be :math:`(1, kD, kH, kW)`  or :math:`(B, kD, kH, kW)`.\n        border_type: the padding mode to be applied before convolving.\n          The expected modes are: ``'constant'``,\n          ``'replicate'`` or ``'circular'``.\n        normalized: If True, kernel will be L1 normalized.\n\n    Return:\n        the convolved tensor of same size and numbers of channels\n        as the input with shape :math:`(B, C, D, H, W)`.\n\n    Example:\n        >>> input = torch.tensor([[[\n        ...    [[0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.]],\n        ...    [[0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 5., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.]],\n        ...    [[0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.]]\n        ... ]]])\n        >>> kernel = torch.ones(1, 3, 3, 3)\n        >>> filter3d(input, kernel)\n        tensor([[[[[0., 0., 0., 0., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 0., 0., 0., 0.]],\n        <BLANKLINE>\n                  [[0., 0., 0., 0., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 0., 0., 0., 0.]],\n        <BLANKLINE>\n                  [[0., 0., 0., 0., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 0., 0., 0., 0.]]]]])\n    \"\"\"\n    if not isinstance(input, torch.Tensor):\n        raise TypeError(f\"Input border_type is not torch.Tensor. Got {type(input)}\")\n\n    if not isinstance(kernel, torch.Tensor):\n        raise TypeError(f\"Input border_type is not torch.Tensor. Got {type(kernel)}\")\n\n    if not isinstance(border_type, str):\n        raise TypeError(f\"Input border_type is not string. Got {type(kernel)}\")\n\n    if not len(input.shape) == 5:\n        raise ValueError(f\"Invalid input shape, we expect BxCxDxHxW. Got: {input.shape}\")\n\n    if not len(kernel.shape) == 4 and kernel.shape[0] != 1:\n        raise ValueError(f\"Invalid kernel shape, we expect 1xDxHxW. Got: {kernel.shape}\")\n\n    # prepare kernel\n    b, c, d, h, w = input.shape\n    tmp_kernel: torch.Tensor = kernel.unsqueeze(1).to(input)\n\n    if normalized:\n        bk, dk, hk, wk = kernel.shape\n        tmp_kernel = normalize_kernel2d(tmp_kernel.view(bk, dk, hk * wk)).view_as(tmp_kernel)\n\n    tmp_kernel = tmp_kernel.expand(-1, c, -1, -1, -1)\n\n    # pad the input tensor\n    depth, height, width = tmp_kernel.shape[-3:]\n    padding_shape: List[int] = _compute_padding([depth, height, width])\n    input_pad: torch.Tensor = F.pad(input, padding_shape, mode=border_type)\n\n    # kernel and input tensor reshape to align element-wise or batch-wise params\n    tmp_kernel = tmp_kernel.reshape(-1, 1, depth, height, width)\n    input_pad = input_pad.view(-1, tmp_kernel.size(0), input_pad.size(-3), input_pad.size(-2), input_pad.size(-1))\n\n    # convolve the tensor with the kernel.\n    output = F.conv3d(input_pad, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)\n\n    return output.view(b, c, d, h, w)\n\n\n# for backward compatibility.\nfilter2D = _deprecation_wrapper(filter2d, 'filter2D')\nfilter3D = _deprecation_wrapper(filter3d, 'filter3D')\n", "path": "kornia/filters/filter.py"}], "after_files": [{"content": "from typing import List\n\nimport torch\nimport torch.nn.functional as F\n\nfrom kornia.filters.__tmp__ import _deprecation_wrapper\nfrom kornia.filters.kernels import normalize_kernel2d\n\n\ndef _compute_padding(kernel_size: List[int]) -> List[int]:\n    \"\"\"Compute padding tuple.\"\"\"\n    # 4 or 6 ints:  (padding_left, padding_right,padding_top,padding_bottom)\n    # https://pytorch.org/docs/stable/nn.html#torch.nn.functional.pad\n    if len(kernel_size) < 2:\n        raise AssertionError(kernel_size)\n    computed = [k // 2 for k in kernel_size]\n\n    # for even kernels we need to do asymmetric padding :(\n\n    out_padding = 2 * len(kernel_size) * [0]\n\n    for i in range(len(kernel_size)):\n        computed_tmp = computed[-(i + 1)]\n        if kernel_size[i] % 2 == 0:\n            padding = computed_tmp - 1\n        else:\n            padding = computed_tmp\n        out_padding[2 * i + 0] = padding\n        out_padding[2 * i + 1] = computed_tmp\n    return out_padding\n\n\ndef filter2d(\n    input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'reflect', normalized: bool = False,\n    padding: str = 'same'\n) -> torch.Tensor:\n    r\"\"\"Convolve a tensor with a 2d kernel.\n\n    The function applies a given kernel to a tensor. The kernel is applied\n    independently at each depth channel of the tensor. Before applying the\n    kernel, the function applies padding according to the specified mode so\n    that the output remains in the same shape.\n\n    Args:\n        input: the input tensor with shape of\n          :math:`(B, C, H, W)`.\n        kernel: the kernel to be convolved with the input\n          tensor. The kernel shape must be :math:`(1, kH, kW)` or :math:`(B, kH, kW)`.\n        border_type: the padding mode to be applied before convolving.\n          The expected modes are: ``'constant'``, ``'reflect'``,\n          ``'replicate'`` or ``'circular'``.\n        normalized: If True, kernel will be L1 normalized.\n        padding: This defines the type of padding.\n          2 modes available ``'same'`` or ``'valid'``.\n\n    Return:\n        torch.Tensor: the convolved tensor of same size and numbers of channels\n        as the input with shape :math:`(B, C, H, W)`.\n\n    Example:\n        >>> input = torch.tensor([[[\n        ...    [0., 0., 0., 0., 0.],\n        ...    [0., 0., 0., 0., 0.],\n        ...    [0., 0., 5., 0., 0.],\n        ...    [0., 0., 0., 0., 0.],\n        ...    [0., 0., 0., 0., 0.],]]])\n        >>> kernel = torch.ones(1, 3, 3)\n        >>> filter2d(input, kernel, padding='same')\n        tensor([[[[0., 0., 0., 0., 0.],\n                  [0., 5., 5., 5., 0.],\n                  [0., 5., 5., 5., 0.],\n                  [0., 5., 5., 5., 0.],\n                  [0., 0., 0., 0., 0.]]]])\n    \"\"\"\n    if not isinstance(input, torch.Tensor):\n        raise TypeError(f\"Input border_type is not torch.Tensor. Got {type(input)}\")\n\n    if not isinstance(kernel, torch.Tensor):\n        raise TypeError(f\"Input border_type is not torch.Tensor. Got {type(kernel)}\")\n\n    if not isinstance(border_type, str):\n        raise TypeError(f\"Input border_type is not string. Got {type(kernel)}\")\n\n    if not isinstance(padding, str):\n        raise TypeError(f\"Input padding is not string. Got {type(padding)}\")\n\n    if padding not in ['valid', 'same']:\n        raise ValueError(f\"Invalid padding mode, we expect 'valid' or 'same'. Got: {padding}\")\n\n    if not len(input.shape) == 4:\n        raise ValueError(f\"Invalid input shape, we expect BxCxHxW. Got: {input.shape}\")\n\n    if not len(kernel.shape) == 3 and kernel.shape[0] != 1:\n        raise ValueError(f\"Invalid kernel shape, we expect 1xHxW. Got: {kernel.shape}\")\n\n    # prepare kernel\n    b, c, h, w = input.shape\n    tmp_kernel: torch.Tensor = kernel.unsqueeze(1).to(input)\n\n    if normalized:\n        tmp_kernel = normalize_kernel2d(tmp_kernel)\n\n    tmp_kernel = tmp_kernel.expand(-1, c, -1, -1)\n\n    height, width = tmp_kernel.shape[-2:]\n\n    # pad the input tensor\n    if padding == 'same':\n        padding_shape: List[int] = _compute_padding([height, width])\n        input = F.pad(input, padding_shape, mode=border_type)\n\n    # kernel and input tensor reshape to align element-wise or batch-wise params\n    tmp_kernel = tmp_kernel.reshape(-1, 1, height, width)\n    input = input.view(-1, tmp_kernel.size(0), input.size(-2), input.size(-1))\n\n    # convolve the tensor with the kernel.\n    output = F.conv2d(input, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)\n\n    if padding == 'same':\n        out = output.view(b, c, h, w)\n    else:\n        out = output.view(b, c, h - height + 1, w - width + 1)\n\n    return out\n\n\ndef filter3d(\n    input: torch.Tensor, kernel: torch.Tensor, border_type: str = 'replicate', normalized: bool = False\n) -> torch.Tensor:\n    r\"\"\"Convolve a tensor with a 3d kernel.\n\n    The function applies a given kernel to a tensor. The kernel is applied\n    independently at each depth channel of the tensor. Before applying the\n    kernel, the function applies padding according to the specified mode so\n    that the output remains in the same shape.\n\n    Args:\n        input: the input tensor with shape of\n          :math:`(B, C, D, H, W)`.\n        kernel: the kernel to be convolved with the input\n          tensor. The kernel shape must be :math:`(1, kD, kH, kW)`  or :math:`(B, kD, kH, kW)`.\n        border_type: the padding mode to be applied before convolving.\n          The expected modes are: ``'constant'``,\n          ``'replicate'`` or ``'circular'``.\n        normalized: If True, kernel will be L1 normalized.\n\n    Return:\n        the convolved tensor of same size and numbers of channels\n        as the input with shape :math:`(B, C, D, H, W)`.\n\n    Example:\n        >>> input = torch.tensor([[[\n        ...    [[0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.]],\n        ...    [[0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 5., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.]],\n        ...    [[0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.],\n        ...     [0., 0., 0., 0., 0.]]\n        ... ]]])\n        >>> kernel = torch.ones(1, 3, 3, 3)\n        >>> filter3d(input, kernel)\n        tensor([[[[[0., 0., 0., 0., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 0., 0., 0., 0.]],\n        <BLANKLINE>\n                  [[0., 0., 0., 0., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 0., 0., 0., 0.]],\n        <BLANKLINE>\n                  [[0., 0., 0., 0., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 5., 5., 5., 0.],\n                   [0., 0., 0., 0., 0.]]]]])\n    \"\"\"\n    if not isinstance(input, torch.Tensor):\n        raise TypeError(f\"Input border_type is not torch.Tensor. Got {type(input)}\")\n\n    if not isinstance(kernel, torch.Tensor):\n        raise TypeError(f\"Input border_type is not torch.Tensor. Got {type(kernel)}\")\n\n    if not isinstance(border_type, str):\n        raise TypeError(f\"Input border_type is not string. Got {type(kernel)}\")\n\n    if not len(input.shape) == 5:\n        raise ValueError(f\"Invalid input shape, we expect BxCxDxHxW. Got: {input.shape}\")\n\n    if not len(kernel.shape) == 4 and kernel.shape[0] != 1:\n        raise ValueError(f\"Invalid kernel shape, we expect 1xDxHxW. Got: {kernel.shape}\")\n\n    # prepare kernel\n    b, c, d, h, w = input.shape\n    tmp_kernel: torch.Tensor = kernel.unsqueeze(1).to(input)\n\n    if normalized:\n        bk, dk, hk, wk = kernel.shape\n        tmp_kernel = normalize_kernel2d(tmp_kernel.view(bk, dk, hk * wk)).view_as(tmp_kernel)\n\n    tmp_kernel = tmp_kernel.expand(-1, c, -1, -1, -1)\n\n    # pad the input tensor\n    depth, height, width = tmp_kernel.shape[-3:]\n    padding_shape: List[int] = _compute_padding([depth, height, width])\n    input_pad: torch.Tensor = F.pad(input, padding_shape, mode=border_type)\n\n    # kernel and input tensor reshape to align element-wise or batch-wise params\n    tmp_kernel = tmp_kernel.reshape(-1, 1, depth, height, width)\n    input_pad = input_pad.view(-1, tmp_kernel.size(0), input_pad.size(-3), input_pad.size(-2), input_pad.size(-1))\n\n    # convolve the tensor with the kernel.\n    output = F.conv3d(input_pad, tmp_kernel, groups=tmp_kernel.size(0), padding=0, stride=1)\n\n    return output.view(b, c, d, h, w)\n\n\n# for backward compatibility.\nfilter2D = _deprecation_wrapper(filter2d, 'filter2D')\nfilter3D = _deprecation_wrapper(filter3d, 'filter3D')\n", "path": "kornia/filters/filter.py"}]}