We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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.

--- 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/geometry/transform/crop.py`
Content:
```
1 from typing import Tuple
2 
3 import torch
4 
5 from kornia.geometry.transform.imgwarp import (
6     warp_perspective, get_perspective_transform
7 )
8 
9 __all__ = [
10     "crop_and_resize",
11     "center_crop",
12 ]
13 
14 
15 def crop_and_resize(tensor: torch.Tensor, boxes: torch.Tensor,
16                     size: Tuple[int, int]) -> torch.Tensor:
17     r"""Extracts crops from the input tensor and resizes them.
18 
19     Args:
20         tensor (torch.Tensor): the reference tensor of shape BxCxHxW.
21         boxes (torch.Tensor): a tensor containing the coordinates of the
22           bounding boxes to be extracted. The tensor must have the shape
23           of Bx4x2, where each box is defined in the following order: top-left,
24           top-right, bottom-left and bottom-right. The coordinates order must
25           be in y, x respectively.
26         size (Tuple[int, int]): a tuple with the height and width that will be
27           used to resize the extracted patches.
28 
29     Returns:
30         torch.Tensor: tensor containing the patches with shape BxN1xN2
31 
32     Example:
33         >>> input = torch.tensor([[
34                 [1., 2., 3., 4.],
35                 [5., 6., 7., 8.],
36                 [9., 10., 11., 12.],
37                 [13., 14., 15., 16.],
38             ]])
39         >>> boxes = torch.tensor([[
40                 [1., 1.],
41                 [1., 2.],
42                 [2., 1.],
43                 [2., 2.],
44             ]])  # 1x4x2
45         >>> kornia.crop_and_resize(input, boxes, (2, 2))
46         tensor([[[ 6.0000,  7.0000],
47                  [ 10.0000, 11.0000]]])
48     """
49     if not torch.is_tensor(tensor):
50         raise TypeError("Input tensor type is not a torch.Tensor. Got {}"
51                         .format(type(tensor)))
52     if not torch.is_tensor(boxes):
53         raise TypeError("Input boxes type is not a torch.Tensor. Got {}"
54                         .format(type(boxes)))
55     if not len(tensor.shape) in (3, 4,):
56         raise ValueError("Input tensor must be in the shape of CxHxW or "
57                          "BxCxHxW. Got {}".format(tensor.shape))
58     if not isinstance(size, (tuple, list,)) and len(size) == 2:
59         raise ValueError("Input size must be a tuple/list of length 2. Got {}"
60                          .format(size))
61     # unpack input data
62     dst_h: torch.Tensor = torch.tensor(size[0])
63     dst_w: torch.Tensor = torch.tensor(size[1])
64 
65     # [y, x] origin
66     # top-left, top-right, bottom-left, bottom-right
67     points_src: torch.Tensor = boxes.to(
68         tensor.device).to(tensor.dtype)
69 
70     # [y, x] destination
71     # top-left, top-right, bottom-left, bottom-right
72     points_dst: torch.Tensor = torch.tensor([[
73         [0, 0],
74         [0, dst_w - 1],
75         [dst_h - 1, 0],
76         [dst_h - 1, dst_w - 1],
77     ]]).repeat(points_src.shape[0], 1, 1).to(
78         tensor.device).to(tensor.dtype)
79 
80     # warping needs data in the shape of BCHW
81     is_unbatched: bool = tensor.ndimension() == 3
82     if is_unbatched:
83         tensor = torch.unsqueeze(tensor, dim=0)
84 
85     # compute transformation between points and warp
86     dst_trans_src: torch.Tensor = get_perspective_transform(
87         points_src, points_dst)
88 
89     # simulate broadcasting
90     dst_trans_src = dst_trans_src.expand(tensor.shape[0], -1, -1)
91 
92     patches: torch.Tensor = warp_perspective(
93         tensor, dst_trans_src, (dst_h, dst_w))
94 
95     # return in the original shape
96     if is_unbatched:
97         patches = torch.squeeze(patches, dim=0)
98 
99     return patches
100 
101 
102 def center_crop(tensor: torch.Tensor, size: Tuple[int, int]) -> torch.Tensor:
103     r"""Crops the given tensor at the center.
104 
105     Args:
106         tensor (torch.Tensor): the input tensor with shape (C, H, W) or
107           (B, C, H, W).
108         size (Tuple[int, int]): a tuple with the expected height and width
109           of the output patch.
110 
111     Returns:
112         torch.Tensor: the output tensor with patches.
113 
114     Examples:
115         >>> input = torch.tensor([[
116                 [1., 2., 3., 4.],
117                 [5., 6., 7., 8.],
118                 [9., 10., 11., 12.],
119                 [13., 14., 15., 16.],
120              ]])
121         >>> kornia.center_crop(input, (2, 4))
122         tensor([[[ 5.0000,  6.0000,  7.0000,  8.0000],
123                  [ 9.0000, 10.0000, 11.0000, 12.0000]]])
124     """
125     if not torch.is_tensor(tensor):
126         raise TypeError("Input tensor type is not a torch.Tensor. Got {}"
127                         .format(type(tensor)))
128     if not len(tensor.shape) in (3, 4,):
129         raise ValueError("Input tensor must be in the shape of CxHxW or "
130                          "BxCxHxW. Got {}".format(tensor.shape))
131     if not isinstance(size, (tuple, list,)) and len(size) == 2:
132         raise ValueError("Input size must be a tuple/list of length 2. Got {}"
133                          .format(size))
134     # unpack input sizes
135     dst_h: torch.Tensor = torch.tensor(size[0])
136     dst_w: torch.Tensor = torch.tensor(size[1])
137     src_h: torch.Tensor = torch.tensor(tensor.shape[-2])
138     src_w: torch.Tensor = torch.tensor(tensor.shape[-1])
139 
140     # compute start/end offsets
141     dst_h_half: torch.Tensor = dst_h / 2
142     dst_w_half: torch.Tensor = dst_w / 2
143     src_h_half: torch.Tensor = src_h / 2
144     src_w_half: torch.Tensor = src_w / 2
145 
146     start_x: torch.Tensor = src_h_half - dst_h_half
147     start_y: torch.Tensor = src_w_half - dst_w_half
148 
149     end_x: torch.Tensor = start_x + dst_w - 1
150     end_y: torch.Tensor = start_y + dst_h - 1
151 
152     # [y, x] origin
153     # top-left, top-right, bottom-left, bottom-right
154     points_src: torch.Tensor = torch.tensor([[
155         [start_y, start_x],
156         [start_y, end_x],
157         [end_y, start_x],
158         [end_y, end_x],
159     ]]).to(tensor.device).to(tensor.dtype)
160 
161     # [y, x] destination
162     # top-left, top-right, bottom-left, bottom-right
163     points_dst: torch.Tensor = torch.tensor([[
164         [0, 0],
165         [0, dst_w - 1],
166         [dst_h - 1, 0],
167         [dst_h - 1, dst_w - 1],
168     ]]).to(tensor.device).to(tensor.dtype)
169 
170     # warping needs data in the shape of BCHW
171     is_unbatched: bool = tensor.ndimension() == 3
172     if is_unbatched:
173         tensor = torch.unsqueeze(tensor, dim=0)
174 
175     # compute transformation between points and warp
176     dst_trans_src: torch.Tensor = get_perspective_transform(
177         points_src, points_dst)
178     dst_trans_src = dst_trans_src.repeat(tensor.shape[0], 1, 1)
179 
180     patches: torch.Tensor = warp_perspective(
181         tensor, dst_trans_src, (dst_h, dst_w))
182 
183     # return in the original shape
184     if is_unbatched:
185         patches = torch.squeeze(patches, dim=0)
186 
187     return patches
188
```
--- 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/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 @@
         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 @@
     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)

{"golden_diff": "diff --git a/kornia/geometry/transform/crop.py b/kornia/geometry/transform/crop.py\n--- a/kornia/geometry/transform/crop.py\n+++ b/kornia/geometry/transform/crop.py\n@@ -20,9 +20,9 @@\n         tensor (torch.Tensor): the reference tensor of shape BxCxHxW.\n         boxes (torch.Tensor): a tensor containing the coordinates of the\n           bounding boxes to be extracted. The tensor must have the shape\n-          of Bx4x2, where each box is defined in the following order: top-left,\n-          top-right, bottom-left and bottom-right. The coordinates order must\n-          be in y, x respectively.\n+          of Bx4x2, where each box is defined in the following (clockwise)\n+          order: top-left, top-right, bottom-right and bottom-left. The\n+          coordinates must be in the x, y order.\n         size (Tuple[int, int]): a tuple with the height and width that will be\n           used to resize the extracted patches.\n \n@@ -62,18 +62,18 @@\n     dst_h: torch.Tensor = torch.tensor(size[0])\n     dst_w: torch.Tensor = torch.tensor(size[1])\n \n-    # [y, x] origin\n-    # top-left, top-right, bottom-left, bottom-right\n+    # [x, y] origin\n+    # top-left, top-right, bottom-right, bottom-left\n     points_src: torch.Tensor = boxes.to(\n         tensor.device).to(tensor.dtype)\n \n-    # [y, x] destination\n-    # top-left, top-right, bottom-left, bottom-right\n+    # [x, y] destination\n+    # top-left, top-right, bottom-right, bottom-left\n     points_dst: torch.Tensor = torch.tensor([[\n         [0, 0],\n-        [0, dst_w - 1],\n-        [dst_h - 1, 0],\n-        [dst_h - 1, dst_w - 1],\n+        [dst_w - 1, 0],\n+        [dst_w - 1, dst_h - 1],\n+        [0, dst_h - 1],\n     ]]).repeat(points_src.shape[0], 1, 1).to(\n         tensor.device).to(tensor.dtype)\n", "issue": "[BUG] crop_and_resize doesn't work when it changes image aspect ratio\nHere 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:\r\n```python3\r\n>>> inp = torch.tensor([[\r\n            [1., 2., 3., 4.],\r\n            [5., 6., 7., 8.],\r\n            [9., 10., 11., 12.],\r\n            [13., 14., 15., 16.],\r\n        ]])\r\n>>> height, width = 2, 3\r\n>>> boxes = torch.tensor([[\r\n            [1., 1.],\r\n            [1., 2.],\r\n            [2., 1.],\r\n            [2., 2.],\r\n        ]])\r\n>>> kornia.crop_and_resize(inp, boxes, (height, width))\r\ntensor([[[ 6.0000,  7.0000,  8.0000],\r\n         [ 8.0000,  9.0000, 10.0000]]])\r\n```\r\nBut the expected result, as per [documentation](https://torchgeometry.readthedocs.io/en/latest/geometry.transform.html#kornia.geometry.transform.crop_and_resize), is:\r\n```python\r\ntorch.tensor([[[6., 6.5, 7.],\r\n               [10., 10.5, 11.]]])\r\n```\r\n\r\nThe 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).\r\n\r\nThe existing tests for `crop_and_resize` are written in such an unfortunate way that they work both ways.\n", "before_files": [{"content": "from typing import Tuple\n\nimport torch\n\nfrom kornia.geometry.transform.imgwarp import (\n    warp_perspective, get_perspective_transform\n)\n\n__all__ = [\n    \"crop_and_resize\",\n    \"center_crop\",\n]\n\n\ndef crop_and_resize(tensor: torch.Tensor, boxes: torch.Tensor,\n                    size: Tuple[int, int]) -> torch.Tensor:\n    r\"\"\"Extracts crops from the input tensor and resizes them.\n\n    Args:\n        tensor (torch.Tensor): the reference tensor of shape BxCxHxW.\n        boxes (torch.Tensor): a tensor containing the coordinates of the\n          bounding boxes to be extracted. The tensor must have the shape\n          of Bx4x2, where each box is defined in the following order: top-left,\n          top-right, bottom-left and bottom-right. The coordinates order must\n          be in y, x respectively.\n        size (Tuple[int, int]): a tuple with the height and width that will be\n          used to resize the extracted patches.\n\n    Returns:\n        torch.Tensor: tensor containing the patches with shape BxN1xN2\n\n    Example:\n        >>> input = torch.tensor([[\n                [1., 2., 3., 4.],\n                [5., 6., 7., 8.],\n                [9., 10., 11., 12.],\n                [13., 14., 15., 16.],\n            ]])\n        >>> boxes = torch.tensor([[\n                [1., 1.],\n                [1., 2.],\n                [2., 1.],\n                [2., 2.],\n            ]])  # 1x4x2\n        >>> kornia.crop_and_resize(input, boxes, (2, 2))\n        tensor([[[ 6.0000,  7.0000],\n                 [ 10.0000, 11.0000]]])\n    \"\"\"\n    if not torch.is_tensor(tensor):\n        raise TypeError(\"Input tensor type is not a torch.Tensor. Got {}\"\n                        .format(type(tensor)))\n    if not torch.is_tensor(boxes):\n        raise TypeError(\"Input boxes type is not a torch.Tensor. Got {}\"\n                        .format(type(boxes)))\n    if not len(tensor.shape) in (3, 4,):\n        raise ValueError(\"Input tensor must be in the shape of CxHxW or \"\n                         \"BxCxHxW. Got {}\".format(tensor.shape))\n    if not isinstance(size, (tuple, list,)) and len(size) == 2:\n        raise ValueError(\"Input size must be a tuple/list of length 2. Got {}\"\n                         .format(size))\n    # unpack input data\n    dst_h: torch.Tensor = torch.tensor(size[0])\n    dst_w: torch.Tensor = torch.tensor(size[1])\n\n    # [y, x] origin\n    # top-left, top-right, bottom-left, bottom-right\n    points_src: torch.Tensor = boxes.to(\n        tensor.device).to(tensor.dtype)\n\n    # [y, x] destination\n    # top-left, top-right, bottom-left, bottom-right\n    points_dst: torch.Tensor = torch.tensor([[\n        [0, 0],\n        [0, dst_w - 1],\n        [dst_h - 1, 0],\n        [dst_h - 1, dst_w - 1],\n    ]]).repeat(points_src.shape[0], 1, 1).to(\n        tensor.device).to(tensor.dtype)\n\n    # warping needs data in the shape of BCHW\n    is_unbatched: bool = tensor.ndimension() == 3\n    if is_unbatched:\n        tensor = torch.unsqueeze(tensor, dim=0)\n\n    # compute transformation between points and warp\n    dst_trans_src: torch.Tensor = get_perspective_transform(\n        points_src, points_dst)\n\n    # simulate broadcasting\n    dst_trans_src = dst_trans_src.expand(tensor.shape[0], -1, -1)\n\n    patches: torch.Tensor = warp_perspective(\n        tensor, dst_trans_src, (dst_h, dst_w))\n\n    # return in the original shape\n    if is_unbatched:\n        patches = torch.squeeze(patches, dim=0)\n\n    return patches\n\n\ndef center_crop(tensor: torch.Tensor, size: Tuple[int, int]) -> torch.Tensor:\n    r\"\"\"Crops the given tensor at the center.\n\n    Args:\n        tensor (torch.Tensor): the input tensor with shape (C, H, W) or\n          (B, C, H, W).\n        size (Tuple[int, int]): a tuple with the expected height and width\n          of the output patch.\n\n    Returns:\n        torch.Tensor: the output tensor with patches.\n\n    Examples:\n        >>> input = torch.tensor([[\n                [1., 2., 3., 4.],\n                [5., 6., 7., 8.],\n                [9., 10., 11., 12.],\n                [13., 14., 15., 16.],\n             ]])\n        >>> kornia.center_crop(input, (2, 4))\n        tensor([[[ 5.0000,  6.0000,  7.0000,  8.0000],\n                 [ 9.0000, 10.0000, 11.0000, 12.0000]]])\n    \"\"\"\n    if not torch.is_tensor(tensor):\n        raise TypeError(\"Input tensor type is not a torch.Tensor. Got {}\"\n                        .format(type(tensor)))\n    if not len(tensor.shape) in (3, 4,):\n        raise ValueError(\"Input tensor must be in the shape of CxHxW or \"\n                         \"BxCxHxW. Got {}\".format(tensor.shape))\n    if not isinstance(size, (tuple, list,)) and len(size) == 2:\n        raise ValueError(\"Input size must be a tuple/list of length 2. Got {}\"\n                         .format(size))\n    # unpack input sizes\n    dst_h: torch.Tensor = torch.tensor(size[0])\n    dst_w: torch.Tensor = torch.tensor(size[1])\n    src_h: torch.Tensor = torch.tensor(tensor.shape[-2])\n    src_w: torch.Tensor = torch.tensor(tensor.shape[-1])\n\n    # compute start/end offsets\n    dst_h_half: torch.Tensor = dst_h / 2\n    dst_w_half: torch.Tensor = dst_w / 2\n    src_h_half: torch.Tensor = src_h / 2\n    src_w_half: torch.Tensor = src_w / 2\n\n    start_x: torch.Tensor = src_h_half - dst_h_half\n    start_y: torch.Tensor = src_w_half - dst_w_half\n\n    end_x: torch.Tensor = start_x + dst_w - 1\n    end_y: torch.Tensor = start_y + dst_h - 1\n\n    # [y, x] origin\n    # top-left, top-right, bottom-left, bottom-right\n    points_src: torch.Tensor = torch.tensor([[\n        [start_y, start_x],\n        [start_y, end_x],\n        [end_y, start_x],\n        [end_y, end_x],\n    ]]).to(tensor.device).to(tensor.dtype)\n\n    # [y, x] destination\n    # top-left, top-right, bottom-left, bottom-right\n    points_dst: torch.Tensor = torch.tensor([[\n        [0, 0],\n        [0, dst_w - 1],\n        [dst_h - 1, 0],\n        [dst_h - 1, dst_w - 1],\n    ]]).to(tensor.device).to(tensor.dtype)\n\n    # warping needs data in the shape of BCHW\n    is_unbatched: bool = tensor.ndimension() == 3\n    if is_unbatched:\n        tensor = torch.unsqueeze(tensor, dim=0)\n\n    # compute transformation between points and warp\n    dst_trans_src: torch.Tensor = get_perspective_transform(\n        points_src, points_dst)\n    dst_trans_src = dst_trans_src.repeat(tensor.shape[0], 1, 1)\n\n    patches: torch.Tensor = warp_perspective(\n        tensor, dst_trans_src, (dst_h, dst_w))\n\n    # return in the original shape\n    if is_unbatched:\n        patches = torch.squeeze(patches, dim=0)\n\n    return patches\n", "path": "kornia/geometry/transform/crop.py"}], "after_files": [{"content": "from typing import Tuple\n\nimport torch\n\nfrom kornia.geometry.transform.imgwarp import (\n    warp_perspective, get_perspective_transform\n)\n\n__all__ = [\n    \"crop_and_resize\",\n    \"center_crop\",\n]\n\n\ndef crop_and_resize(tensor: torch.Tensor, boxes: torch.Tensor,\n                    size: Tuple[int, int]) -> torch.Tensor:\n    r\"\"\"Extracts crops from the input tensor and resizes them.\n\n    Args:\n        tensor (torch.Tensor): the reference tensor of shape BxCxHxW.\n        boxes (torch.Tensor): a tensor containing the coordinates of the\n          bounding boxes to be extracted. The tensor must have the shape\n          of Bx4x2, where each box is defined in the following (clockwise)\n          order: top-left, top-right, bottom-right and bottom-left. The\n          coordinates must be in the x, y order.\n        size (Tuple[int, int]): a tuple with the height and width that will be\n          used to resize the extracted patches.\n\n    Returns:\n        torch.Tensor: tensor containing the patches with shape BxN1xN2\n\n    Example:\n        >>> input = torch.tensor([[\n                [1., 2., 3., 4.],\n                [5., 6., 7., 8.],\n                [9., 10., 11., 12.],\n                [13., 14., 15., 16.],\n            ]])\n        >>> boxes = torch.tensor([[\n                [1., 1.],\n                [1., 2.],\n                [2., 1.],\n                [2., 2.],\n            ]])  # 1x4x2\n        >>> kornia.crop_and_resize(input, boxes, (2, 2))\n        tensor([[[ 6.0000,  7.0000],\n                 [ 10.0000, 11.0000]]])\n    \"\"\"\n    if not torch.is_tensor(tensor):\n        raise TypeError(\"Input tensor type is not a torch.Tensor. Got {}\"\n                        .format(type(tensor)))\n    if not torch.is_tensor(boxes):\n        raise TypeError(\"Input boxes type is not a torch.Tensor. Got {}\"\n                        .format(type(boxes)))\n    if not len(tensor.shape) in (3, 4,):\n        raise ValueError(\"Input tensor must be in the shape of CxHxW or \"\n                         \"BxCxHxW. Got {}\".format(tensor.shape))\n    if not isinstance(size, (tuple, list,)) and len(size) == 2:\n        raise ValueError(\"Input size must be a tuple/list of length 2. Got {}\"\n                         .format(size))\n    # unpack input data\n    dst_h: torch.Tensor = torch.tensor(size[0])\n    dst_w: torch.Tensor = torch.tensor(size[1])\n\n    # [x, y] origin\n    # top-left, top-right, bottom-right, bottom-left\n    points_src: torch.Tensor = boxes.to(\n        tensor.device).to(tensor.dtype)\n\n    # [x, y] destination\n    # top-left, top-right, bottom-right, bottom-left\n    points_dst: torch.Tensor = torch.tensor([[\n        [0, 0],\n        [dst_w - 1, 0],\n        [dst_w - 1, dst_h - 1],\n        [0, dst_h - 1],\n    ]]).repeat(points_src.shape[0], 1, 1).to(\n        tensor.device).to(tensor.dtype)\n\n    # warping needs data in the shape of BCHW\n    is_unbatched: bool = tensor.ndimension() == 3\n    if is_unbatched:\n        tensor = torch.unsqueeze(tensor, dim=0)\n\n    # compute transformation between points and warp\n    dst_trans_src: torch.Tensor = get_perspective_transform(\n        points_src, points_dst)\n\n    # simulate broadcasting\n    dst_trans_src = dst_trans_src.expand(tensor.shape[0], -1, -1)\n\n    patches: torch.Tensor = warp_perspective(\n        tensor, dst_trans_src, (dst_h, dst_w))\n\n    # return in the original shape\n    if is_unbatched:\n        patches = torch.squeeze(patches, dim=0)\n\n    return patches\n\n\ndef center_crop(tensor: torch.Tensor, size: Tuple[int, int]) -> torch.Tensor:\n    r\"\"\"Crops the given tensor at the center.\n\n    Args:\n        tensor (torch.Tensor): the input tensor with shape (C, H, W) or\n          (B, C, H, W).\n        size (Tuple[int, int]): a tuple with the expected height and width\n          of the output patch.\n\n    Returns:\n        torch.Tensor: the output tensor with patches.\n\n    Examples:\n        >>> input = torch.tensor([[\n                [1., 2., 3., 4.],\n                [5., 6., 7., 8.],\n                [9., 10., 11., 12.],\n                [13., 14., 15., 16.],\n             ]])\n        >>> kornia.center_crop(input, (2, 4))\n        tensor([[[ 5.0000,  6.0000,  7.0000,  8.0000],\n                 [ 9.0000, 10.0000, 11.0000, 12.0000]]])\n    \"\"\"\n    if not torch.is_tensor(tensor):\n        raise TypeError(\"Input tensor type is not a torch.Tensor. Got {}\"\n                        .format(type(tensor)))\n    if not len(tensor.shape) in (3, 4,):\n        raise ValueError(\"Input tensor must be in the shape of CxHxW or \"\n                         \"BxCxHxW. Got {}\".format(tensor.shape))\n    if not isinstance(size, (tuple, list,)) and len(size) == 2:\n        raise ValueError(\"Input size must be a tuple/list of length 2. Got {}\"\n                         .format(size))\n    # unpack input sizes\n    dst_h: torch.Tensor = torch.tensor(size[0])\n    dst_w: torch.Tensor = torch.tensor(size[1])\n    src_h: torch.Tensor = torch.tensor(tensor.shape[-2])\n    src_w: torch.Tensor = torch.tensor(tensor.shape[-1])\n\n    # compute start/end offsets\n    dst_h_half: torch.Tensor = dst_h / 2\n    dst_w_half: torch.Tensor = dst_w / 2\n    src_h_half: torch.Tensor = src_h / 2\n    src_w_half: torch.Tensor = src_w / 2\n\n    start_x: torch.Tensor = src_h_half - dst_h_half\n    start_y: torch.Tensor = src_w_half - dst_w_half\n\n    end_x: torch.Tensor = start_x + dst_w - 1\n    end_y: torch.Tensor = start_y + dst_h - 1\n\n    # [y, x] origin\n    # top-left, top-right, bottom-left, bottom-right\n    points_src: torch.Tensor = torch.tensor([[\n        [start_y, start_x],\n        [start_y, end_x],\n        [end_y, start_x],\n        [end_y, end_x],\n    ]]).to(tensor.device).to(tensor.dtype)\n\n    # [y, x] destination\n    # top-left, top-right, bottom-left, bottom-right\n    points_dst: torch.Tensor = torch.tensor([[\n        [0, 0],\n        [0, dst_w - 1],\n        [dst_h - 1, 0],\n        [dst_h - 1, dst_w - 1],\n    ]]).to(tensor.device).to(tensor.dtype)\n\n    # warping needs data in the shape of BCHW\n    is_unbatched: bool = tensor.ndimension() == 3\n    if is_unbatched:\n        tensor = torch.unsqueeze(tensor, dim=0)\n\n    # compute transformation between points and warp\n    dst_trans_src: torch.Tensor = get_perspective_transform(\n        points_src, points_dst)\n    dst_trans_src = dst_trans_src.repeat(tensor.shape[0], 1, 1)\n\n    patches: torch.Tensor = warp_perspective(\n        tensor, dst_trans_src, (dst_h, dst_w))\n\n    # return in the original shape\n    if is_unbatched:\n        patches = torch.squeeze(patches, dim=0)\n\n    return patches\n", "path": "kornia/geometry/transform/crop.py"}]}