Repository: kornia/kornia

Issue:
RandomCrop issue
RandomCrop works fine with padding_mode = 'consant'.
But with 'reflect' I got error:    
```
 assert len(pad) == 2, '3D tensors expect 2 values for padding'
AssertionError: 3D tensors expect 2 values for padding

```

```
crop_width=2014
crop_height= 758
random_crop = kornia.augmentation.RandomCrop(
        size=(crop_height, crop_width),
        pad_if_needed=1,
        padding_mode='constant', # 'reflect'
        p=1
)
kornia_transform = nn.Sequential(
    random_crop
)

    korn_img = kornia_transform(torch_arr)

```
torch_arr.shape is [1, 720, 1280]

Is there mirror-like pad function? So I want to pad it first ant then crop


Discussion:
@shijianjian is it a known issue ?
if think @anguelos implemented a pad_if_needed in torchvision 
It is a partial bug here that the input shall be transformed into BCHW. It is not about the padding mode. Will fix that soon.

Resolving patch:
diff --git a/kornia/augmentation/augmentation.py b/kornia/augmentation/augmentation.py
--- a/kornia/augmentation/augmentation.py
+++ b/kornia/augmentation/augmentation.py
@@ -15,6 +15,7 @@
 from . import random_generator as rg
 from .utils import (
     _range_bound,
+    _transform_input
 )
 
 
@@ -755,6 +756,7 @@ def generate_parameters(self, batch_shape: torch.Size) -> Dict[str, torch.Tensor
                                         same_on_batch=self.same_on_batch, device=self.device, dtype=self.dtype)
 
     def precrop_padding(self, input: torch.Tensor) -> torch.Tensor:
+        assert len(input.shape) == 4, f"Expected BCHW. Got {input.shape}"
         if self.padding is not None:
             if isinstance(self.padding, int):
                 self.padding = cast(int, self.padding)
@@ -787,9 +789,11 @@ def forward(self, input: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]],
                 params: Optional[Dict[str, torch.Tensor]] = None, return_transform: Optional[bool] = None
                 ) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
         if isinstance(input, (tuple, list)):
-            _input = (self.precrop_padding(input[0]), input[1])
+            input_temp = _transform_input(input[0])
+            _input = (self.precrop_padding(input_temp), input[1])
         else:
             input = cast(torch.Tensor, input)  # TODO: weird that cast is not working under this context.
+            input = _transform_input(input)
             _input = self.precrop_padding(input)  # type: ignore
         out = super().forward(_input, params, return_transform)
         if not self._params['batch_prob'].all():


Test patch:
diff --git a/test/augmentation/test_augmentation.py b/test/augmentation/test_augmentation.py
--- a/test/augmentation/test_augmentation.py
+++ b/test/augmentation/test_augmentation.py
@@ -1970,7 +1970,11 @@ def test_no_padding(self, device, dtype):
         rc = RandomCrop(size=(2, 3), padding=None, align_corners=True, p=1.)
         out = rc(inp)
 
+        torch.manual_seed(0)
+        out2 = rc(inp.squeeze())
+
         assert_allclose(out, expected, atol=1e-4, rtol=1e-4)
+        assert_allclose(out2, expected, atol=1e-4, rtol=1e-4)
 
     def test_no_padding_batch(self, device, dtype):
         torch.manual_seed(42)
@@ -1996,6 +2000,26 @@ def test_same_on_batch(self, device, dtype):
         res = f(input)
         assert (res[0] == res[1]).all()
 
+    def test_padding(self, device, dtype):
+        torch.manual_seed(42)
+        inp = torch.tensor([[[
+            [0., 1., 2.],
+            [3., 4., 5.],
+            [6., 7., 8.]
+        ]]], device=device, dtype=dtype)
+        expected = torch.tensor([[[
+            [7., 8., 7.],
+            [4., 5., 4.]
+        ]]], device=device, dtype=dtype)
+        rc = RandomCrop(size=(2, 3), padding=1, padding_mode='reflect', align_corners=True, p=1.)
+        out = rc(inp)
+
+        torch.manual_seed(42)
+        out2 = rc(inp.squeeze())
+
+        assert_allclose(out, expected, atol=1e-4, rtol=1e-4)
+        assert_allclose(out2, expected, atol=1e-4, rtol=1e-4)
+
     def test_padding_batch_1(self, device, dtype):
         torch.manual_seed(42)
         batch_size = 2