Repository: kornia/kornia

Issue:
`filter2d` gives wrong output shape with even width and odd height
### Describe the bug

As we know, `filter2d` with `padding='same'` should give a same output shape as `input`. However:

```py
import torch
import numpy as np
from kornia.filters import filter2d

img = np.array([
    [0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0],
    [0, 0, 1, 0, 0, 0],
    [0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
], dtype=np.float32)
img = torch.tensor(img).unsqueeze_(0).unsqueeze_(0)
print(img.shape) # torch.Size([1, 1, 5, 6])

kern = np.array([
    [0, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0, 0],
    [0, 1, 1, 1, 0, 0],
    [0, 1, 1, 1, 0, 0],
    [0, 0, 0, 0, 0, 0],
], dtype=np.float32)
kern = torch.tensor(kern).unsqueeze_(0)
print(kern.shape) # torch.Size([1, 5, 6])

res = filter2d(img, kern, padding='same')
'''
  File "/.../site-packages/kornia/filters/filter.py", line 124, in filter2d
    out = output.view(b, c, h, w)
RuntimeError: shape '[1, 1, 5, 6]' is invalid for input of size 28
'''
print(res.shape)
```

We can't obtain the filtered result.

### Reproduction steps

```bash
Please refer to the code above.
```


### Expected behavior

Like scipy:

```py
import numpy as np
from scipy.signal import convolve2d

img = np.array([
    [0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0],
    [0, 0, 1, 0, 0, 0],
    [0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
], dtype=np.float32)
print(img.shape) # (5, 6)

kern = np.array([
    [0, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0, 0],
    [0, 1, 1, 1, 0, 0],
    [0, 1, 1, 1, 0, 0],
    [0, 0, 0, 0, 0, 0],
], dtype=np.float32)
print(kern.shape) # (5, 6)

res = convolve2d(img, kern, mode='same')
print(res.shape) # (5, 6)
```

### Environment

- PyTorch Version (e.g., 1.0): 1.10.2
- OS (e.g., Linux): Linux (Ubuntu 18.04)
- How you installed PyTorch (`conda`, `pip`, source): `conda`
- Python version: 3.7.11



Discussion:

Resolving patch:
diff --git a/kornia/filters/filter.py b/kornia/filters/filter.py
--- a/kornia/filters/filter.py
+++ b/kornia/filters/filter.py
@@ -13,20 +13,20 @@ def _compute_padding(kernel_size: List[int]) -> List[int]:
     # https://pytorch.org/docs/stable/nn.html#torch.nn.functional.pad
     if len(kernel_size) < 2:
         raise AssertionError(kernel_size)
-    computed = [k // 2 for k in kernel_size]
+    computed = [k - 1 for k in kernel_size]
 
     # for even kernels we need to do asymmetric padding :(
-
     out_padding = 2 * len(kernel_size) * [0]
 
     for i in range(len(kernel_size)):
         computed_tmp = computed[-(i + 1)]
-        if kernel_size[i] % 2 == 0:
-            padding = computed_tmp - 1
-        else:
-            padding = computed_tmp
-        out_padding[2 * i + 0] = padding
-        out_padding[2 * i + 1] = computed_tmp
+
+        pad_front = computed_tmp // 2
+        pad_rear = computed_tmp - pad_front
+
+        out_padding[2 * i + 0] = pad_front
+        out_padding[2 * i + 1] = pad_rear
+
     return out_padding
 
 


Test patch:
diff --git a/test/filters/test_filters.py b/test/filters/test_filters.py
--- a/test/filters/test_filters.py
+++ b/test/filters/test_filters.py
@@ -220,6 +220,44 @@ def test_even_sized_filter(self, padding, device, dtype):
         else:
             assert_close(actual, expected_valid)
 
+    @pytest.mark.parametrize("padding", ["same", "valid"])
+    def test_mix_sized_filter_padding_same(self, padding, device, dtype):
+        kernel = torch.ones(1, 5, 6, device=device, dtype=dtype)
+        input_ = torch.tensor(
+            [
+                [
+                    [
+                        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+                        [0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
+                        [0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
+                        [0.0, 0.0, 1.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(
+            [
+                [
+                    [
+                        [2.0, 2.0, 2.0, 2.0, 2.0, 0.0],
+                        [3.0, 3.0, 3.0, 3.0, 3.0, 0.0],
+                        [3.0, 3.0, 3.0, 3.0, 3.0, 0.0],
+                        [3.0, 3.0, 3.0, 3.0, 3.0, 0.0],
+                        [2.0, 2.0, 2.0, 2.0, 2.0, 0.0]
+                    ]
+                ]
+            ],
+            device=device,
+            dtype=dtype,
+        )
+
+        actual = kornia.filters.filter2d(input_, kernel, padding='same', border_type='constant')
+        assert_close(actual, expected_same)
+
     @pytest.mark.parametrize("padding", ["same", "valid"])
     def test_noncontiguous(self, padding, device, dtype):
         batch_size = 3