Repository: kornia/kornia

Issue:
[BUG] crop_and_resize doesn't work when it changes image aspect ratio
Here is a failing test-case, adapted from [this test](https://github.com/arraiyopensource/kornia/blob/a48164b1274827773f3da36dcbe2879c69f4471c/test/geometry/transform/test_crop.py#L14) but with some aspect-ratio distortion:
```python3
>>> inp = torch.tensor([[
            [1., 2., 3., 4.],
            [5., 6., 7., 8.],
            [9., 10., 11., 12.],
            [13., 14., 15., 16.],
        ]])
>>> height, width = 2, 3
>>> boxes = torch.tensor([[
            [1., 1.],
            [1., 2.],
            [2., 1.],
            [2., 2.],
        ]])
>>> kornia.crop_and_resize(inp, boxes, (height, width))
tensor([[[ 6.0000,  7.0000,  8.0000],
         [ 8.0000,  9.0000, 10.0000]]])
```
But the expected result, as per [documentation](https://torchgeometry.readthedocs.io/en/latest/geometry.transform.html#kornia.geometry.transform.crop_and_resize), is:
```python
torch.tensor([[[6., 6.5, 7.],
               [10., 10.5, 11.]]])
```

The issue seems to be caused by a mis-use of the `get_perspective_transform` function by `crop_and_resize`. The arguments to [`get_perspective_transform`](https://torchgeometry.readthedocs.io/en/latest/geometry.transform.html#kornia.geometry.transform.get_perspective_transform) expect points to be written in [x,y] format (not documented), but `crop_and_resize` passes them in [y,x]. The [x,y] ordering in `get_perspective_transform` is [used in this example](https://kornia.readthedocs.io/en/latest/tutorials/warp_perspective.html).

The existing tests for `crop_and_resize` are written in such an unfortunate way that they work both ways.


Discussion:

Resolving patch:
diff --git a/kornia/geometry/transform/crop.py b/kornia/geometry/transform/crop.py
--- a/kornia/geometry/transform/crop.py
+++ b/kornia/geometry/transform/crop.py
@@ -20,9 +20,9 @@ def crop_and_resize(tensor: torch.Tensor, boxes: torch.Tensor,
         tensor (torch.Tensor): the reference tensor of shape BxCxHxW.
         boxes (torch.Tensor): a tensor containing the coordinates of the
           bounding boxes to be extracted. The tensor must have the shape
-          of Bx4x2, where each box is defined in the following order: top-left,
-          top-right, bottom-left and bottom-right. The coordinates order must
-          be in y, x respectively.
+          of Bx4x2, where each box is defined in the following (clockwise)
+          order: top-left, top-right, bottom-right and bottom-left. The
+          coordinates must be in the x, y order.
         size (Tuple[int, int]): a tuple with the height and width that will be
           used to resize the extracted patches.
 
@@ -62,18 +62,18 @@ def crop_and_resize(tensor: torch.Tensor, boxes: torch.Tensor,
     dst_h: torch.Tensor = torch.tensor(size[0])
     dst_w: torch.Tensor = torch.tensor(size[1])
 
-    # [y, x] origin
-    # top-left, top-right, bottom-left, bottom-right
+    # [x, y] origin
+    # top-left, top-right, bottom-right, bottom-left
     points_src: torch.Tensor = boxes.to(
         tensor.device).to(tensor.dtype)
 
-    # [y, x] destination
-    # top-left, top-right, bottom-left, bottom-right
+    # [x, y] destination
+    # top-left, top-right, bottom-right, bottom-left
     points_dst: torch.Tensor = torch.tensor([[
         [0, 0],
-        [0, dst_w - 1],
-        [dst_h - 1, 0],
-        [dst_h - 1, dst_w - 1],
+        [dst_w - 1, 0],
+        [dst_w - 1, dst_h - 1],
+        [0, dst_h - 1],
     ]]).repeat(points_src.shape[0], 1, 1).to(
         tensor.device).to(tensor.dtype)
 


Test patch:
diff --git a/test/geometry/transform/test_crop.py b/test/geometry/transform/test_crop.py
--- a/test/geometry/transform/test_crop.py
+++ b/test/geometry/transform/test_crop.py
@@ -19,17 +19,17 @@ def test_crop(self):
             [13., 14., 15., 16.],
         ]])
 
-        height, width = 2, 2
+        height, width = 2, 3
         expected = torch.tensor([[
-            [6., 7.],
-            [10., 11.],
+            [6., 6.5, 7.],
+            [10., 10.5, 11.],
         ]])
 
         boxes = torch.tensor([[
             [1., 1.],
-            [1., 2.],
             [2., 1.],
             [2., 2.],
+            [1., 2.],
         ]])  # 1x4x2
 
         patches = kornia.crop_and_resize(inp, boxes, (height, width))
@@ -53,20 +53,20 @@ def test_crop_batch(self):
             [6., 7.],
             [10., 11.],
         ]], [[
-            [11., 15.],
-            [12., 16.],
+            [7., 15.],
+            [8., 16.],
         ]]])
 
         boxes = torch.tensor([[
             [1., 1.],
-            [1., 2.],
             [2., 1.],
             [2., 2.],
+            [1., 2.],
         ], [
-            [2., 2.],
-            [2., 3.],
+            [1., 2.],
             [3., 2.],
             [3., 3.],
+            [1., 3.],
         ]])  # 2x4x2
 
         patches = kornia.crop_and_resize(inp, boxes, (height, width))
@@ -96,9 +96,9 @@ def test_crop_batch_broadcast(self):
 
         boxes = torch.tensor([[
             [1., 1.],
-            [1., 2.],
             [2., 1.],
             [2., 2.],
+            [1., 2.],
         ]])  # 1x4x2
 
         patches = kornia.crop_and_resize(inp, boxes, (height, width))
@@ -111,9 +111,9 @@ def test_gradcheck(self):
 
         boxes = torch.tensor([[
             [1., 1.],
-            [1., 2.],
             [2., 1.],
             [2., 2.],
+            [1., 2.],
         ]])  # 1x4x2
         boxes = utils.tensor_to_gradcheck_var(
             boxes, requires_grad=False)  # to var
@@ -138,9 +138,9 @@ def op_script(input: torch.Tensor,
         ]])
         boxes = torch.tensor([[
             [1., 1.],
-            [1., 2.],
             [2., 1.],
             [2., 2.],
+            [1., 2.],
         ]])  # 1x4x2
 
         crop_height, crop_width = 4, 2