We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
This may be  has extra "as"
https://github.com/pytorch/vision/blob/631ff9123edeedf044c4355ef99dc42a396feb5b/torchvision/models/detection/transform.py#L87

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `torchvision/models/detection/transform.py`
Content:
```
1 import math
2 import torch
3 from torch import nn, Tensor
4 from torch.nn import functional as F
5 import torchvision
6 from typing import List, Tuple, Dict, Optional
7 
8 from .image_list import ImageList
9 from .roi_heads import paste_masks_in_image
10 
11 
12 @torch.jit.unused
13 def _resize_image_and_masks_onnx(image, self_min_size, self_max_size, target):
14     # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]
15     from torch.onnx import operators
16     im_shape = operators.shape_as_tensor(image)[-2:]
17     min_size = torch.min(im_shape).to(dtype=torch.float32)
18     max_size = torch.max(im_shape).to(dtype=torch.float32)
19     scale_factor = torch.min(self_min_size / min_size, self_max_size / max_size)
20 
21     image = torch.nn.functional.interpolate(
22         image[None], scale_factor=scale_factor, mode='bilinear', recompute_scale_factor=True,
23         align_corners=False)[0]
24 
25     if target is None:
26         return image, target
27 
28     if "masks" in target:
29         mask = target["masks"]
30         mask = F.interpolate(mask[:, None].float(), scale_factor=scale_factor, recompute_scale_factor=True)[:, 0].byte()
31         target["masks"] = mask
32     return image, target
33 
34 
35 def _resize_image_and_masks(image, self_min_size, self_max_size, target):
36     # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]
37     im_shape = torch.tensor(image.shape[-2:])
38     min_size = float(torch.min(im_shape))
39     max_size = float(torch.max(im_shape))
40     scale_factor = self_min_size / min_size
41     if max_size * scale_factor > self_max_size:
42         scale_factor = self_max_size / max_size
43     image = torch.nn.functional.interpolate(
44         image[None], scale_factor=scale_factor, mode='bilinear', recompute_scale_factor=True,
45         align_corners=False)[0]
46 
47     if target is None:
48         return image, target
49 
50     if "masks" in target:
51         mask = target["masks"]
52         mask = F.interpolate(mask[:, None].float(), scale_factor=scale_factor, recompute_scale_factor=True)[:, 0].byte()
53         target["masks"] = mask
54     return image, target
55 
56 
57 class GeneralizedRCNNTransform(nn.Module):
58     """
59     Performs input / target transformation before feeding the data to a GeneralizedRCNN
60     model.
61 
62     The transformations it perform are:
63         - input normalization (mean subtraction and std division)
64         - input / target resizing to match min_size / max_size
65 
66     It returns a ImageList for the inputs, and a List[Dict[Tensor]] for the targets
67     """
68 
69     def __init__(self, min_size, max_size, image_mean, image_std):
70         super(GeneralizedRCNNTransform, self).__init__()
71         if not isinstance(min_size, (list, tuple)):
72             min_size = (min_size,)
73         self.min_size = min_size
74         self.max_size = max_size
75         self.image_mean = image_mean
76         self.image_std = image_std
77 
78     def forward(self,
79                 images,       # type: List[Tensor]
80                 targets=None  # type: Optional[List[Dict[str, Tensor]]]
81                 ):
82         # type: (...) -> Tuple[ImageList, Optional[List[Dict[str, Tensor]]]]
83         images = [img for img in images]
84         if targets is not None:
85             # make a copy of targets to avoid modifying it in-place
86             # once torchscript supports dict comprehension
87             # this can be simplified as as follows
88             # targets = [{k: v for k,v in t.items()} for t in targets]
89             targets_copy: List[Dict[str, Tensor]] = []
90             for t in targets:
91                 data: Dict[str, Tensor] = {}
92                 for k, v in t.items():
93                     data[k] = v
94                 targets_copy.append(data)
95             targets = targets_copy
96         for i in range(len(images)):
97             image = images[i]
98             target_index = targets[i] if targets is not None else None
99 
100             if image.dim() != 3:
101                 raise ValueError("images is expected to be a list of 3d tensors "
102                                  "of shape [C, H, W], got {}".format(image.shape))
103             image = self.normalize(image)
104             image, target_index = self.resize(image, target_index)
105             images[i] = image
106             if targets is not None and target_index is not None:
107                 targets[i] = target_index
108 
109         image_sizes = [img.shape[-2:] for img in images]
110         images = self.batch_images(images)
111         image_sizes_list: List[Tuple[int, int]] = []
112         for image_size in image_sizes:
113             assert len(image_size) == 2
114             image_sizes_list.append((image_size[0], image_size[1]))
115 
116         image_list = ImageList(images, image_sizes_list)
117         return image_list, targets
118 
119     def normalize(self, image):
120         if not image.is_floating_point():
121             raise TypeError(
122                 f"Expected input images to be of floating type (in range [0, 1]), "
123                 f"but found type {image.dtype} instead"
124             )
125         dtype, device = image.dtype, image.device
126         mean = torch.as_tensor(self.image_mean, dtype=dtype, device=device)
127         std = torch.as_tensor(self.image_std, dtype=dtype, device=device)
128         return (image - mean[:, None, None]) / std[:, None, None]
129 
130     def torch_choice(self, k):
131         # type: (List[int]) -> int
132         """
133         Implements `random.choice` via torch ops so it can be compiled with
134         TorchScript. Remove if https://github.com/pytorch/pytorch/issues/25803
135         is fixed.
136         """
137         index = int(torch.empty(1).uniform_(0., float(len(k))).item())
138         return k[index]
139 
140     def resize(self, image, target):
141         # type: (Tensor, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]
142         h, w = image.shape[-2:]
143         if self.training:
144             size = float(self.torch_choice(self.min_size))
145         else:
146             # FIXME assume for now that testing uses the largest scale
147             size = float(self.min_size[-1])
148         if torchvision._is_tracing():
149             image, target = _resize_image_and_masks_onnx(image, size, float(self.max_size), target)
150         else:
151             image, target = _resize_image_and_masks(image, size, float(self.max_size), target)
152 
153         if target is None:
154             return image, target
155 
156         bbox = target["boxes"]
157         bbox = resize_boxes(bbox, (h, w), image.shape[-2:])
158         target["boxes"] = bbox
159 
160         if "keypoints" in target:
161             keypoints = target["keypoints"]
162             keypoints = resize_keypoints(keypoints, (h, w), image.shape[-2:])
163             target["keypoints"] = keypoints
164         return image, target
165 
166     # _onnx_batch_images() is an implementation of
167     # batch_images() that is supported by ONNX tracing.
168     @torch.jit.unused
169     def _onnx_batch_images(self, images, size_divisible=32):
170         # type: (List[Tensor], int) -> Tensor
171         max_size = []
172         for i in range(images[0].dim()):
173             max_size_i = torch.max(torch.stack([img.shape[i] for img in images]).to(torch.float32)).to(torch.int64)
174             max_size.append(max_size_i)
175         stride = size_divisible
176         max_size[1] = (torch.ceil((max_size[1].to(torch.float32)) / stride) * stride).to(torch.int64)
177         max_size[2] = (torch.ceil((max_size[2].to(torch.float32)) / stride) * stride).to(torch.int64)
178         max_size = tuple(max_size)
179 
180         # work around for
181         # pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img)
182         # which is not yet supported in onnx
183         padded_imgs = []
184         for img in images:
185             padding = [(s1 - s2) for s1, s2 in zip(max_size, tuple(img.shape))]
186             padded_img = torch.nn.functional.pad(img, (0, padding[2], 0, padding[1], 0, padding[0]))
187             padded_imgs.append(padded_img)
188 
189         return torch.stack(padded_imgs)
190 
191     def max_by_axis(self, the_list):
192         # type: (List[List[int]]) -> List[int]
193         maxes = the_list[0]
194         for sublist in the_list[1:]:
195             for index, item in enumerate(sublist):
196                 maxes[index] = max(maxes[index], item)
197         return maxes
198 
199     def batch_images(self, images, size_divisible=32):
200         # type: (List[Tensor], int) -> Tensor
201         if torchvision._is_tracing():
202             # batch_images() does not export well to ONNX
203             # call _onnx_batch_images() instead
204             return self._onnx_batch_images(images, size_divisible)
205 
206         max_size = self.max_by_axis([list(img.shape) for img in images])
207         stride = float(size_divisible)
208         max_size = list(max_size)
209         max_size[1] = int(math.ceil(float(max_size[1]) / stride) * stride)
210         max_size[2] = int(math.ceil(float(max_size[2]) / stride) * stride)
211 
212         batch_shape = [len(images)] + max_size
213         batched_imgs = images[0].new_full(batch_shape, 0)
214         for img, pad_img in zip(images, batched_imgs):
215             pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img)
216 
217         return batched_imgs
218 
219     def postprocess(self,
220                     result,               # type: List[Dict[str, Tensor]]
221                     image_shapes,         # type: List[Tuple[int, int]]
222                     original_image_sizes  # type: List[Tuple[int, int]]
223                     ):
224         # type: (...) -> List[Dict[str, Tensor]]
225         if self.training:
226             return result
227         for i, (pred, im_s, o_im_s) in enumerate(zip(result, image_shapes, original_image_sizes)):
228             boxes = pred["boxes"]
229             boxes = resize_boxes(boxes, im_s, o_im_s)
230             result[i]["boxes"] = boxes
231             if "masks" in pred:
232                 masks = pred["masks"]
233                 masks = paste_masks_in_image(masks, boxes, o_im_s)
234                 result[i]["masks"] = masks
235             if "keypoints" in pred:
236                 keypoints = pred["keypoints"]
237                 keypoints = resize_keypoints(keypoints, im_s, o_im_s)
238                 result[i]["keypoints"] = keypoints
239         return result
240 
241     def __repr__(self):
242         format_string = self.__class__.__name__ + '('
243         _indent = '\n    '
244         format_string += "{0}Normalize(mean={1}, std={2})".format(_indent, self.image_mean, self.image_std)
245         format_string += "{0}Resize(min_size={1}, max_size={2}, mode='bilinear')".format(_indent, self.min_size,
246                                                                                          self.max_size)
247         format_string += '\n)'
248         return format_string
249 
250 
251 def resize_keypoints(keypoints, original_size, new_size):
252     # type: (Tensor, List[int], List[int]) -> Tensor
253     ratios = [
254         torch.tensor(s, dtype=torch.float32, device=keypoints.device) /
255         torch.tensor(s_orig, dtype=torch.float32, device=keypoints.device)
256         for s, s_orig in zip(new_size, original_size)
257     ]
258     ratio_h, ratio_w = ratios
259     resized_data = keypoints.clone()
260     if torch._C._get_tracing_state():
261         resized_data_0 = resized_data[:, :, 0] * ratio_w
262         resized_data_1 = resized_data[:, :, 1] * ratio_h
263         resized_data = torch.stack((resized_data_0, resized_data_1, resized_data[:, :, 2]), dim=2)
264     else:
265         resized_data[..., 0] *= ratio_w
266         resized_data[..., 1] *= ratio_h
267     return resized_data
268 
269 
270 def resize_boxes(boxes, original_size, new_size):
271     # type: (Tensor, List[int], List[int]) -> Tensor
272     ratios = [
273         torch.tensor(s, dtype=torch.float32, device=boxes.device) /
274         torch.tensor(s_orig, dtype=torch.float32, device=boxes.device)
275         for s, s_orig in zip(new_size, original_size)
276     ]
277     ratio_height, ratio_width = ratios
278     xmin, ymin, xmax, ymax = boxes.unbind(1)
279 
280     xmin = xmin * ratio_width
281     xmax = xmax * ratio_width
282     ymin = ymin * ratio_height
283     ymax = ymax * ratio_height
284     return torch.stack((xmin, ymin, xmax, ymax), dim=1)
285
```
--- 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/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py
--- a/torchvision/models/detection/transform.py
+++ b/torchvision/models/detection/transform.py
@@ -84,7 +84,7 @@
         if targets is not None:
             # make a copy of targets to avoid modifying it in-place
             # once torchscript supports dict comprehension
-            # this can be simplified as as follows
+            # this can be simplified as follows
             # targets = [{k: v for k,v in t.items()} for t in targets]
             targets_copy: List[Dict[str, Tensor]] = []
             for t in targets:

{"golden_diff": "diff --git a/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py\n--- a/torchvision/models/detection/transform.py\n+++ b/torchvision/models/detection/transform.py\n@@ -84,7 +84,7 @@\n         if targets is not None:\n             # make a copy of targets to avoid modifying it in-place\n             # once torchscript supports dict comprehension\n-            # this can be simplified as as follows\n+            # this can be simplified as follows\n             # targets = [{k: v for k,v in t.items()} for t in targets]\n             targets_copy: List[Dict[str, Tensor]] = []\n             for t in targets:\n", "issue": "This may be  has extra \"as\"\nhttps://github.com/pytorch/vision/blob/631ff9123edeedf044c4355ef99dc42a396feb5b/torchvision/models/detection/transform.py#L87\n", "before_files": [{"content": "import math\nimport torch\nfrom torch import nn, Tensor\nfrom torch.nn import functional as F\nimport torchvision\nfrom typing import List, Tuple, Dict, Optional\n\nfrom .image_list import ImageList\nfrom .roi_heads import paste_masks_in_image\n\n\n@torch.jit.unused\ndef _resize_image_and_masks_onnx(image, self_min_size, self_max_size, target):\n    # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]\n    from torch.onnx import operators\n    im_shape = operators.shape_as_tensor(image)[-2:]\n    min_size = torch.min(im_shape).to(dtype=torch.float32)\n    max_size = torch.max(im_shape).to(dtype=torch.float32)\n    scale_factor = torch.min(self_min_size / min_size, self_max_size / max_size)\n\n    image = torch.nn.functional.interpolate(\n        image[None], scale_factor=scale_factor, mode='bilinear', recompute_scale_factor=True,\n        align_corners=False)[0]\n\n    if target is None:\n        return image, target\n\n    if \"masks\" in target:\n        mask = target[\"masks\"]\n        mask = F.interpolate(mask[:, None].float(), scale_factor=scale_factor, recompute_scale_factor=True)[:, 0].byte()\n        target[\"masks\"] = mask\n    return image, target\n\n\ndef _resize_image_and_masks(image, self_min_size, self_max_size, target):\n    # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]\n    im_shape = torch.tensor(image.shape[-2:])\n    min_size = float(torch.min(im_shape))\n    max_size = float(torch.max(im_shape))\n    scale_factor = self_min_size / min_size\n    if max_size * scale_factor > self_max_size:\n        scale_factor = self_max_size / max_size\n    image = torch.nn.functional.interpolate(\n        image[None], scale_factor=scale_factor, mode='bilinear', recompute_scale_factor=True,\n        align_corners=False)[0]\n\n    if target is None:\n        return image, target\n\n    if \"masks\" in target:\n        mask = target[\"masks\"]\n        mask = F.interpolate(mask[:, None].float(), scale_factor=scale_factor, recompute_scale_factor=True)[:, 0].byte()\n        target[\"masks\"] = mask\n    return image, target\n\n\nclass GeneralizedRCNNTransform(nn.Module):\n    \"\"\"\n    Performs input / target transformation before feeding the data to a GeneralizedRCNN\n    model.\n\n    The transformations it perform are:\n        - input normalization (mean subtraction and std division)\n        - input / target resizing to match min_size / max_size\n\n    It returns a ImageList for the inputs, and a List[Dict[Tensor]] for the targets\n    \"\"\"\n\n    def __init__(self, min_size, max_size, image_mean, image_std):\n        super(GeneralizedRCNNTransform, self).__init__()\n        if not isinstance(min_size, (list, tuple)):\n            min_size = (min_size,)\n        self.min_size = min_size\n        self.max_size = max_size\n        self.image_mean = image_mean\n        self.image_std = image_std\n\n    def forward(self,\n                images,       # type: List[Tensor]\n                targets=None  # type: Optional[List[Dict[str, Tensor]]]\n                ):\n        # type: (...) -> Tuple[ImageList, Optional[List[Dict[str, Tensor]]]]\n        images = [img for img in images]\n        if targets is not None:\n            # make a copy of targets to avoid modifying it in-place\n            # once torchscript supports dict comprehension\n            # this can be simplified as as follows\n            # targets = [{k: v for k,v in t.items()} for t in targets]\n            targets_copy: List[Dict[str, Tensor]] = []\n            for t in targets:\n                data: Dict[str, Tensor] = {}\n                for k, v in t.items():\n                    data[k] = v\n                targets_copy.append(data)\n            targets = targets_copy\n        for i in range(len(images)):\n            image = images[i]\n            target_index = targets[i] if targets is not None else None\n\n            if image.dim() != 3:\n                raise ValueError(\"images is expected to be a list of 3d tensors \"\n                                 \"of shape [C, H, W], got {}\".format(image.shape))\n            image = self.normalize(image)\n            image, target_index = self.resize(image, target_index)\n            images[i] = image\n            if targets is not None and target_index is not None:\n                targets[i] = target_index\n\n        image_sizes = [img.shape[-2:] for img in images]\n        images = self.batch_images(images)\n        image_sizes_list: List[Tuple[int, int]] = []\n        for image_size in image_sizes:\n            assert len(image_size) == 2\n            image_sizes_list.append((image_size[0], image_size[1]))\n\n        image_list = ImageList(images, image_sizes_list)\n        return image_list, targets\n\n    def normalize(self, image):\n        if not image.is_floating_point():\n            raise TypeError(\n                f\"Expected input images to be of floating type (in range [0, 1]), \"\n                f\"but found type {image.dtype} instead\"\n            )\n        dtype, device = image.dtype, image.device\n        mean = torch.as_tensor(self.image_mean, dtype=dtype, device=device)\n        std = torch.as_tensor(self.image_std, dtype=dtype, device=device)\n        return (image - mean[:, None, None]) / std[:, None, None]\n\n    def torch_choice(self, k):\n        # type: (List[int]) -> int\n        \"\"\"\n        Implements `random.choice` via torch ops so it can be compiled with\n        TorchScript. Remove if https://github.com/pytorch/pytorch/issues/25803\n        is fixed.\n        \"\"\"\n        index = int(torch.empty(1).uniform_(0., float(len(k))).item())\n        return k[index]\n\n    def resize(self, image, target):\n        # type: (Tensor, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]\n        h, w = image.shape[-2:]\n        if self.training:\n            size = float(self.torch_choice(self.min_size))\n        else:\n            # FIXME assume for now that testing uses the largest scale\n            size = float(self.min_size[-1])\n        if torchvision._is_tracing():\n            image, target = _resize_image_and_masks_onnx(image, size, float(self.max_size), target)\n        else:\n            image, target = _resize_image_and_masks(image, size, float(self.max_size), target)\n\n        if target is None:\n            return image, target\n\n        bbox = target[\"boxes\"]\n        bbox = resize_boxes(bbox, (h, w), image.shape[-2:])\n        target[\"boxes\"] = bbox\n\n        if \"keypoints\" in target:\n            keypoints = target[\"keypoints\"]\n            keypoints = resize_keypoints(keypoints, (h, w), image.shape[-2:])\n            target[\"keypoints\"] = keypoints\n        return image, target\n\n    # _onnx_batch_images() is an implementation of\n    # batch_images() that is supported by ONNX tracing.\n    @torch.jit.unused\n    def _onnx_batch_images(self, images, size_divisible=32):\n        # type: (List[Tensor], int) -> Tensor\n        max_size = []\n        for i in range(images[0].dim()):\n            max_size_i = torch.max(torch.stack([img.shape[i] for img in images]).to(torch.float32)).to(torch.int64)\n            max_size.append(max_size_i)\n        stride = size_divisible\n        max_size[1] = (torch.ceil((max_size[1].to(torch.float32)) / stride) * stride).to(torch.int64)\n        max_size[2] = (torch.ceil((max_size[2].to(torch.float32)) / stride) * stride).to(torch.int64)\n        max_size = tuple(max_size)\n\n        # work around for\n        # pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img)\n        # which is not yet supported in onnx\n        padded_imgs = []\n        for img in images:\n            padding = [(s1 - s2) for s1, s2 in zip(max_size, tuple(img.shape))]\n            padded_img = torch.nn.functional.pad(img, (0, padding[2], 0, padding[1], 0, padding[0]))\n            padded_imgs.append(padded_img)\n\n        return torch.stack(padded_imgs)\n\n    def max_by_axis(self, the_list):\n        # type: (List[List[int]]) -> List[int]\n        maxes = the_list[0]\n        for sublist in the_list[1:]:\n            for index, item in enumerate(sublist):\n                maxes[index] = max(maxes[index], item)\n        return maxes\n\n    def batch_images(self, images, size_divisible=32):\n        # type: (List[Tensor], int) -> Tensor\n        if torchvision._is_tracing():\n            # batch_images() does not export well to ONNX\n            # call _onnx_batch_images() instead\n            return self._onnx_batch_images(images, size_divisible)\n\n        max_size = self.max_by_axis([list(img.shape) for img in images])\n        stride = float(size_divisible)\n        max_size = list(max_size)\n        max_size[1] = int(math.ceil(float(max_size[1]) / stride) * stride)\n        max_size[2] = int(math.ceil(float(max_size[2]) / stride) * stride)\n\n        batch_shape = [len(images)] + max_size\n        batched_imgs = images[0].new_full(batch_shape, 0)\n        for img, pad_img in zip(images, batched_imgs):\n            pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img)\n\n        return batched_imgs\n\n    def postprocess(self,\n                    result,               # type: List[Dict[str, Tensor]]\n                    image_shapes,         # type: List[Tuple[int, int]]\n                    original_image_sizes  # type: List[Tuple[int, int]]\n                    ):\n        # type: (...) -> List[Dict[str, Tensor]]\n        if self.training:\n            return result\n        for i, (pred, im_s, o_im_s) in enumerate(zip(result, image_shapes, original_image_sizes)):\n            boxes = pred[\"boxes\"]\n            boxes = resize_boxes(boxes, im_s, o_im_s)\n            result[i][\"boxes\"] = boxes\n            if \"masks\" in pred:\n                masks = pred[\"masks\"]\n                masks = paste_masks_in_image(masks, boxes, o_im_s)\n                result[i][\"masks\"] = masks\n            if \"keypoints\" in pred:\n                keypoints = pred[\"keypoints\"]\n                keypoints = resize_keypoints(keypoints, im_s, o_im_s)\n                result[i][\"keypoints\"] = keypoints\n        return result\n\n    def __repr__(self):\n        format_string = self.__class__.__name__ + '('\n        _indent = '\\n    '\n        format_string += \"{0}Normalize(mean={1}, std={2})\".format(_indent, self.image_mean, self.image_std)\n        format_string += \"{0}Resize(min_size={1}, max_size={2}, mode='bilinear')\".format(_indent, self.min_size,\n                                                                                         self.max_size)\n        format_string += '\\n)'\n        return format_string\n\n\ndef resize_keypoints(keypoints, original_size, new_size):\n    # type: (Tensor, List[int], List[int]) -> Tensor\n    ratios = [\n        torch.tensor(s, dtype=torch.float32, device=keypoints.device) /\n        torch.tensor(s_orig, dtype=torch.float32, device=keypoints.device)\n        for s, s_orig in zip(new_size, original_size)\n    ]\n    ratio_h, ratio_w = ratios\n    resized_data = keypoints.clone()\n    if torch._C._get_tracing_state():\n        resized_data_0 = resized_data[:, :, 0] * ratio_w\n        resized_data_1 = resized_data[:, :, 1] * ratio_h\n        resized_data = torch.stack((resized_data_0, resized_data_1, resized_data[:, :, 2]), dim=2)\n    else:\n        resized_data[..., 0] *= ratio_w\n        resized_data[..., 1] *= ratio_h\n    return resized_data\n\n\ndef resize_boxes(boxes, original_size, new_size):\n    # type: (Tensor, List[int], List[int]) -> Tensor\n    ratios = [\n        torch.tensor(s, dtype=torch.float32, device=boxes.device) /\n        torch.tensor(s_orig, dtype=torch.float32, device=boxes.device)\n        for s, s_orig in zip(new_size, original_size)\n    ]\n    ratio_height, ratio_width = ratios\n    xmin, ymin, xmax, ymax = boxes.unbind(1)\n\n    xmin = xmin * ratio_width\n    xmax = xmax * ratio_width\n    ymin = ymin * ratio_height\n    ymax = ymax * ratio_height\n    return torch.stack((xmin, ymin, xmax, ymax), dim=1)\n", "path": "torchvision/models/detection/transform.py"}], "after_files": [{"content": "import math\nimport torch\nfrom torch import nn, Tensor\nfrom torch.nn import functional as F\nimport torchvision\nfrom typing import List, Tuple, Dict, Optional\n\nfrom .image_list import ImageList\nfrom .roi_heads import paste_masks_in_image\n\n\n@torch.jit.unused\ndef _resize_image_and_masks_onnx(image, self_min_size, self_max_size, target):\n    # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]\n    from torch.onnx import operators\n    im_shape = operators.shape_as_tensor(image)[-2:]\n    min_size = torch.min(im_shape).to(dtype=torch.float32)\n    max_size = torch.max(im_shape).to(dtype=torch.float32)\n    scale_factor = torch.min(self_min_size / min_size, self_max_size / max_size)\n\n    image = torch.nn.functional.interpolate(\n        image[None], scale_factor=scale_factor, mode='bilinear', recompute_scale_factor=True,\n        align_corners=False)[0]\n\n    if target is None:\n        return image, target\n\n    if \"masks\" in target:\n        mask = target[\"masks\"]\n        mask = F.interpolate(mask[:, None].float(), scale_factor=scale_factor, recompute_scale_factor=True)[:, 0].byte()\n        target[\"masks\"] = mask\n    return image, target\n\n\ndef _resize_image_and_masks(image, self_min_size, self_max_size, target):\n    # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]\n    im_shape = torch.tensor(image.shape[-2:])\n    min_size = float(torch.min(im_shape))\n    max_size = float(torch.max(im_shape))\n    scale_factor = self_min_size / min_size\n    if max_size * scale_factor > self_max_size:\n        scale_factor = self_max_size / max_size\n    image = torch.nn.functional.interpolate(\n        image[None], scale_factor=scale_factor, mode='bilinear', recompute_scale_factor=True,\n        align_corners=False)[0]\n\n    if target is None:\n        return image, target\n\n    if \"masks\" in target:\n        mask = target[\"masks\"]\n        mask = F.interpolate(mask[:, None].float(), scale_factor=scale_factor, recompute_scale_factor=True)[:, 0].byte()\n        target[\"masks\"] = mask\n    return image, target\n\n\nclass GeneralizedRCNNTransform(nn.Module):\n    \"\"\"\n    Performs input / target transformation before feeding the data to a GeneralizedRCNN\n    model.\n\n    The transformations it perform are:\n        - input normalization (mean subtraction and std division)\n        - input / target resizing to match min_size / max_size\n\n    It returns a ImageList for the inputs, and a List[Dict[Tensor]] for the targets\n    \"\"\"\n\n    def __init__(self, min_size, max_size, image_mean, image_std):\n        super(GeneralizedRCNNTransform, self).__init__()\n        if not isinstance(min_size, (list, tuple)):\n            min_size = (min_size,)\n        self.min_size = min_size\n        self.max_size = max_size\n        self.image_mean = image_mean\n        self.image_std = image_std\n\n    def forward(self,\n                images,       # type: List[Tensor]\n                targets=None  # type: Optional[List[Dict[str, Tensor]]]\n                ):\n        # type: (...) -> Tuple[ImageList, Optional[List[Dict[str, Tensor]]]]\n        images = [img for img in images]\n        if targets is not None:\n            # make a copy of targets to avoid modifying it in-place\n            # once torchscript supports dict comprehension\n            # this can be simplified as follows\n            # targets = [{k: v for k,v in t.items()} for t in targets]\n            targets_copy: List[Dict[str, Tensor]] = []\n            for t in targets:\n                data: Dict[str, Tensor] = {}\n                for k, v in t.items():\n                    data[k] = v\n                targets_copy.append(data)\n            targets = targets_copy\n        for i in range(len(images)):\n            image = images[i]\n            target_index = targets[i] if targets is not None else None\n\n            if image.dim() != 3:\n                raise ValueError(\"images is expected to be a list of 3d tensors \"\n                                 \"of shape [C, H, W], got {}\".format(image.shape))\n            image = self.normalize(image)\n            image, target_index = self.resize(image, target_index)\n            images[i] = image\n            if targets is not None and target_index is not None:\n                targets[i] = target_index\n\n        image_sizes = [img.shape[-2:] for img in images]\n        images = self.batch_images(images)\n        image_sizes_list: List[Tuple[int, int]] = []\n        for image_size in image_sizes:\n            assert len(image_size) == 2\n            image_sizes_list.append((image_size[0], image_size[1]))\n\n        image_list = ImageList(images, image_sizes_list)\n        return image_list, targets\n\n    def normalize(self, image):\n        if not image.is_floating_point():\n            raise TypeError(\n                f\"Expected input images to be of floating type (in range [0, 1]), \"\n                f\"but found type {image.dtype} instead\"\n            )\n        dtype, device = image.dtype, image.device\n        mean = torch.as_tensor(self.image_mean, dtype=dtype, device=device)\n        std = torch.as_tensor(self.image_std, dtype=dtype, device=device)\n        return (image - mean[:, None, None]) / std[:, None, None]\n\n    def torch_choice(self, k):\n        # type: (List[int]) -> int\n        \"\"\"\n        Implements `random.choice` via torch ops so it can be compiled with\n        TorchScript. Remove if https://github.com/pytorch/pytorch/issues/25803\n        is fixed.\n        \"\"\"\n        index = int(torch.empty(1).uniform_(0., float(len(k))).item())\n        return k[index]\n\n    def resize(self, image, target):\n        # type: (Tensor, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]\n        h, w = image.shape[-2:]\n        if self.training:\n            size = float(self.torch_choice(self.min_size))\n        else:\n            # FIXME assume for now that testing uses the largest scale\n            size = float(self.min_size[-1])\n        if torchvision._is_tracing():\n            image, target = _resize_image_and_masks_onnx(image, size, float(self.max_size), target)\n        else:\n            image, target = _resize_image_and_masks(image, size, float(self.max_size), target)\n\n        if target is None:\n            return image, target\n\n        bbox = target[\"boxes\"]\n        bbox = resize_boxes(bbox, (h, w), image.shape[-2:])\n        target[\"boxes\"] = bbox\n\n        if \"keypoints\" in target:\n            keypoints = target[\"keypoints\"]\n            keypoints = resize_keypoints(keypoints, (h, w), image.shape[-2:])\n            target[\"keypoints\"] = keypoints\n        return image, target\n\n    # _onnx_batch_images() is an implementation of\n    # batch_images() that is supported by ONNX tracing.\n    @torch.jit.unused\n    def _onnx_batch_images(self, images, size_divisible=32):\n        # type: (List[Tensor], int) -> Tensor\n        max_size = []\n        for i in range(images[0].dim()):\n            max_size_i = torch.max(torch.stack([img.shape[i] for img in images]).to(torch.float32)).to(torch.int64)\n            max_size.append(max_size_i)\n        stride = size_divisible\n        max_size[1] = (torch.ceil((max_size[1].to(torch.float32)) / stride) * stride).to(torch.int64)\n        max_size[2] = (torch.ceil((max_size[2].to(torch.float32)) / stride) * stride).to(torch.int64)\n        max_size = tuple(max_size)\n\n        # work around for\n        # pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img)\n        # which is not yet supported in onnx\n        padded_imgs = []\n        for img in images:\n            padding = [(s1 - s2) for s1, s2 in zip(max_size, tuple(img.shape))]\n            padded_img = torch.nn.functional.pad(img, (0, padding[2], 0, padding[1], 0, padding[0]))\n            padded_imgs.append(padded_img)\n\n        return torch.stack(padded_imgs)\n\n    def max_by_axis(self, the_list):\n        # type: (List[List[int]]) -> List[int]\n        maxes = the_list[0]\n        for sublist in the_list[1:]:\n            for index, item in enumerate(sublist):\n                maxes[index] = max(maxes[index], item)\n        return maxes\n\n    def batch_images(self, images, size_divisible=32):\n        # type: (List[Tensor], int) -> Tensor\n        if torchvision._is_tracing():\n            # batch_images() does not export well to ONNX\n            # call _onnx_batch_images() instead\n            return self._onnx_batch_images(images, size_divisible)\n\n        max_size = self.max_by_axis([list(img.shape) for img in images])\n        stride = float(size_divisible)\n        max_size = list(max_size)\n        max_size[1] = int(math.ceil(float(max_size[1]) / stride) * stride)\n        max_size[2] = int(math.ceil(float(max_size[2]) / stride) * stride)\n\n        batch_shape = [len(images)] + max_size\n        batched_imgs = images[0].new_full(batch_shape, 0)\n        for img, pad_img in zip(images, batched_imgs):\n            pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img)\n\n        return batched_imgs\n\n    def postprocess(self,\n                    result,               # type: List[Dict[str, Tensor]]\n                    image_shapes,         # type: List[Tuple[int, int]]\n                    original_image_sizes  # type: List[Tuple[int, int]]\n                    ):\n        # type: (...) -> List[Dict[str, Tensor]]\n        if self.training:\n            return result\n        for i, (pred, im_s, o_im_s) in enumerate(zip(result, image_shapes, original_image_sizes)):\n            boxes = pred[\"boxes\"]\n            boxes = resize_boxes(boxes, im_s, o_im_s)\n            result[i][\"boxes\"] = boxes\n            if \"masks\" in pred:\n                masks = pred[\"masks\"]\n                masks = paste_masks_in_image(masks, boxes, o_im_s)\n                result[i][\"masks\"] = masks\n            if \"keypoints\" in pred:\n                keypoints = pred[\"keypoints\"]\n                keypoints = resize_keypoints(keypoints, im_s, o_im_s)\n                result[i][\"keypoints\"] = keypoints\n        return result\n\n    def __repr__(self):\n        format_string = self.__class__.__name__ + '('\n        _indent = '\\n    '\n        format_string += \"{0}Normalize(mean={1}, std={2})\".format(_indent, self.image_mean, self.image_std)\n        format_string += \"{0}Resize(min_size={1}, max_size={2}, mode='bilinear')\".format(_indent, self.min_size,\n                                                                                         self.max_size)\n        format_string += '\\n)'\n        return format_string\n\n\ndef resize_keypoints(keypoints, original_size, new_size):\n    # type: (Tensor, List[int], List[int]) -> Tensor\n    ratios = [\n        torch.tensor(s, dtype=torch.float32, device=keypoints.device) /\n        torch.tensor(s_orig, dtype=torch.float32, device=keypoints.device)\n        for s, s_orig in zip(new_size, original_size)\n    ]\n    ratio_h, ratio_w = ratios\n    resized_data = keypoints.clone()\n    if torch._C._get_tracing_state():\n        resized_data_0 = resized_data[:, :, 0] * ratio_w\n        resized_data_1 = resized_data[:, :, 1] * ratio_h\n        resized_data = torch.stack((resized_data_0, resized_data_1, resized_data[:, :, 2]), dim=2)\n    else:\n        resized_data[..., 0] *= ratio_w\n        resized_data[..., 1] *= ratio_h\n    return resized_data\n\n\ndef resize_boxes(boxes, original_size, new_size):\n    # type: (Tensor, List[int], List[int]) -> Tensor\n    ratios = [\n        torch.tensor(s, dtype=torch.float32, device=boxes.device) /\n        torch.tensor(s_orig, dtype=torch.float32, device=boxes.device)\n        for s, s_orig in zip(new_size, original_size)\n    ]\n    ratio_height, ratio_width = ratios\n    xmin, ymin, xmax, ymax = boxes.unbind(1)\n\n    xmin = xmin * ratio_width\n    xmax = xmax * ratio_width\n    ymin = ymin * ratio_height\n    ymax = ymax * ratio_height\n    return torch.stack((xmin, ymin, xmax, ymax), dim=1)\n", "path": "torchvision/models/detection/transform.py"}]}