We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Swapped width and height in DefaultBoxGenerator
In the DefaultBoxGenerator module, the image sizes in the image_size argument are given as (height, width) by SSD model but the code assumes (width, height).

https://github.com/pytorch/vision/blob/15a9a93b9e0e6173b936691a2cddced0ecfd271f/torchvision/models/detection/anchor_utils.py#L216-L217

I think this has gone unnoticed because the images are usually resized into squares.

cc @datumbox

--- 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/anchor_utils.py`
Content:
```
1 import math
2 from typing import List, Optional
3 
4 import torch
5 from torch import nn, Tensor
6 
7 from .image_list import ImageList
8 
9 
10 class AnchorGenerator(nn.Module):
11     """
12     Module that generates anchors for a set of feature maps and
13     image sizes.
14 
15     The module support computing anchors at multiple sizes and aspect ratios
16     per feature map. This module assumes aspect ratio = height / width for
17     each anchor.
18 
19     sizes and aspect_ratios should have the same number of elements, and it should
20     correspond to the number of feature maps.
21 
22     sizes[i] and aspect_ratios[i] can have an arbitrary number of elements,
23     and AnchorGenerator will output a set of sizes[i] * aspect_ratios[i] anchors
24     per spatial location for feature map i.
25 
26     Args:
27         sizes (Tuple[Tuple[int]]):
28         aspect_ratios (Tuple[Tuple[float]]):
29     """
30 
31     __annotations__ = {
32         "cell_anchors": List[torch.Tensor],
33     }
34 
35     def __init__(
36         self,
37         sizes=((128, 256, 512),),
38         aspect_ratios=((0.5, 1.0, 2.0),),
39     ):
40         super().__init__()
41 
42         if not isinstance(sizes[0], (list, tuple)):
43             # TODO change this
44             sizes = tuple((s,) for s in sizes)
45         if not isinstance(aspect_ratios[0], (list, tuple)):
46             aspect_ratios = (aspect_ratios,) * len(sizes)
47 
48         self.sizes = sizes
49         self.aspect_ratios = aspect_ratios
50         self.cell_anchors = [
51             self.generate_anchors(size, aspect_ratio) for size, aspect_ratio in zip(sizes, aspect_ratios)
52         ]
53 
54     # TODO: https://github.com/pytorch/pytorch/issues/26792
55     # For every (aspect_ratios, scales) combination, output a zero-centered anchor with those values.
56     # (scales, aspect_ratios) are usually an element of zip(self.scales, self.aspect_ratios)
57     # This method assumes aspect ratio = height / width for an anchor.
58     def generate_anchors(
59         self,
60         scales: List[int],
61         aspect_ratios: List[float],
62         dtype: torch.dtype = torch.float32,
63         device: torch.device = torch.device("cpu"),
64     ):
65         scales = torch.as_tensor(scales, dtype=dtype, device=device)
66         aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device)
67         h_ratios = torch.sqrt(aspect_ratios)
68         w_ratios = 1 / h_ratios
69 
70         ws = (w_ratios[:, None] * scales[None, :]).view(-1)
71         hs = (h_ratios[:, None] * scales[None, :]).view(-1)
72 
73         base_anchors = torch.stack([-ws, -hs, ws, hs], dim=1) / 2
74         return base_anchors.round()
75 
76     def set_cell_anchors(self, dtype: torch.dtype, device: torch.device):
77         self.cell_anchors = [cell_anchor.to(dtype=dtype, device=device) for cell_anchor in self.cell_anchors]
78 
79     def num_anchors_per_location(self):
80         return [len(s) * len(a) for s, a in zip(self.sizes, self.aspect_ratios)]
81 
82     # For every combination of (a, (g, s), i) in (self.cell_anchors, zip(grid_sizes, strides), 0:2),
83     # output g[i] anchors that are s[i] distance apart in direction i, with the same dimensions as a.
84     def grid_anchors(self, grid_sizes: List[List[int]], strides: List[List[Tensor]]) -> List[Tensor]:
85         anchors = []
86         cell_anchors = self.cell_anchors
87         torch._assert(cell_anchors is not None, "cell_anchors should not be None")
88         torch._assert(
89             len(grid_sizes) == len(strides) == len(cell_anchors),
90             "Anchors should be Tuple[Tuple[int]] because each feature "
91             "map could potentially have different sizes and aspect ratios. "
92             "There needs to be a match between the number of "
93             "feature maps passed and the number of sizes / aspect ratios specified.",
94         )
95 
96         for size, stride, base_anchors in zip(grid_sizes, strides, cell_anchors):
97             grid_height, grid_width = size
98             stride_height, stride_width = stride
99             device = base_anchors.device
100 
101             # For output anchor, compute [x_center, y_center, x_center, y_center]
102             shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_width
103             shifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height
104             shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij")
105             shift_x = shift_x.reshape(-1)
106             shift_y = shift_y.reshape(-1)
107             shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1)
108 
109             # For every (base anchor, output anchor) pair,
110             # offset each zero-centered base anchor by the center of the output anchor.
111             anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4))
112 
113         return anchors
114 
115     def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:
116         grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]
117         image_size = image_list.tensors.shape[-2:]
118         dtype, device = feature_maps[0].dtype, feature_maps[0].device
119         strides = [
120             [
121                 torch.empty((), dtype=torch.int64, device=device).fill_(image_size[0] // g[0]),
122                 torch.empty((), dtype=torch.int64, device=device).fill_(image_size[1] // g[1]),
123             ]
124             for g in grid_sizes
125         ]
126         self.set_cell_anchors(dtype, device)
127         anchors_over_all_feature_maps = self.grid_anchors(grid_sizes, strides)
128         anchors: List[List[torch.Tensor]] = []
129         for _ in range(len(image_list.image_sizes)):
130             anchors_in_image = [anchors_per_feature_map for anchors_per_feature_map in anchors_over_all_feature_maps]
131             anchors.append(anchors_in_image)
132         anchors = [torch.cat(anchors_per_image) for anchors_per_image in anchors]
133         return anchors
134 
135 
136 class DefaultBoxGenerator(nn.Module):
137     """
138     This module generates the default boxes of SSD for a set of feature maps and image sizes.
139 
140     Args:
141         aspect_ratios (List[List[int]]): A list with all the aspect ratios used in each feature map.
142         min_ratio (float): The minimum scale :math:`\text{s}_{\text{min}}` of the default boxes used in the estimation
143             of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.
144         max_ratio (float): The maximum scale :math:`\text{s}_{\text{max}}`  of the default boxes used in the estimation
145             of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.
146         scales (List[float]], optional): The scales of the default boxes. If not provided it will be estimated using
147             the ``min_ratio`` and ``max_ratio`` parameters.
148         steps (List[int]], optional): It's a hyper-parameter that affects the tiling of defalt boxes. If not provided
149             it will be estimated from the data.
150         clip (bool): Whether the standardized values of default boxes should be clipped between 0 and 1. The clipping
151             is applied while the boxes are encoded in format ``(cx, cy, w, h)``.
152     """
153 
154     def __init__(
155         self,
156         aspect_ratios: List[List[int]],
157         min_ratio: float = 0.15,
158         max_ratio: float = 0.9,
159         scales: Optional[List[float]] = None,
160         steps: Optional[List[int]] = None,
161         clip: bool = True,
162     ):
163         super().__init__()
164         if steps is not None and len(aspect_ratios) != len(steps):
165             raise ValueError("aspect_ratios and steps should have the same length")
166         self.aspect_ratios = aspect_ratios
167         self.steps = steps
168         self.clip = clip
169         num_outputs = len(aspect_ratios)
170 
171         # Estimation of default boxes scales
172         if scales is None:
173             if num_outputs > 1:
174                 range_ratio = max_ratio - min_ratio
175                 self.scales = [min_ratio + range_ratio * k / (num_outputs - 1.0) for k in range(num_outputs)]
176                 self.scales.append(1.0)
177             else:
178                 self.scales = [min_ratio, max_ratio]
179         else:
180             self.scales = scales
181 
182         self._wh_pairs = self._generate_wh_pairs(num_outputs)
183 
184     def _generate_wh_pairs(
185         self, num_outputs: int, dtype: torch.dtype = torch.float32, device: torch.device = torch.device("cpu")
186     ) -> List[Tensor]:
187         _wh_pairs: List[Tensor] = []
188         for k in range(num_outputs):
189             # Adding the 2 default width-height pairs for aspect ratio 1 and scale s'k
190             s_k = self.scales[k]
191             s_prime_k = math.sqrt(self.scales[k] * self.scales[k + 1])
192             wh_pairs = [[s_k, s_k], [s_prime_k, s_prime_k]]
193 
194             # Adding 2 pairs for each aspect ratio of the feature map k
195             for ar in self.aspect_ratios[k]:
196                 sq_ar = math.sqrt(ar)
197                 w = self.scales[k] * sq_ar
198                 h = self.scales[k] / sq_ar
199                 wh_pairs.extend([[w, h], [h, w]])
200 
201             _wh_pairs.append(torch.as_tensor(wh_pairs, dtype=dtype, device=device))
202         return _wh_pairs
203 
204     def num_anchors_per_location(self):
205         # Estimate num of anchors based on aspect ratios: 2 default boxes + 2 * ratios of feaure map.
206         return [2 + 2 * len(r) for r in self.aspect_ratios]
207 
208     # Default Boxes calculation based on page 6 of SSD paper
209     def _grid_default_boxes(
210         self, grid_sizes: List[List[int]], image_size: List[int], dtype: torch.dtype = torch.float32
211     ) -> Tensor:
212         default_boxes = []
213         for k, f_k in enumerate(grid_sizes):
214             # Now add the default boxes for each width-height pair
215             if self.steps is not None:
216                 x_f_k = image_size[0] / self.steps[k]
217                 y_f_k = image_size[1] / self.steps[k]
218             else:
219                 y_f_k, x_f_k = f_k
220 
221             shifts_x = ((torch.arange(0, f_k[1]) + 0.5) / x_f_k).to(dtype=dtype)
222             shifts_y = ((torch.arange(0, f_k[0]) + 0.5) / y_f_k).to(dtype=dtype)
223             shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij")
224             shift_x = shift_x.reshape(-1)
225             shift_y = shift_y.reshape(-1)
226 
227             shifts = torch.stack((shift_x, shift_y) * len(self._wh_pairs[k]), dim=-1).reshape(-1, 2)
228             # Clipping the default boxes while the boxes are encoded in format (cx, cy, w, h)
229             _wh_pair = self._wh_pairs[k].clamp(min=0, max=1) if self.clip else self._wh_pairs[k]
230             wh_pairs = _wh_pair.repeat((f_k[0] * f_k[1]), 1)
231 
232             default_box = torch.cat((shifts, wh_pairs), dim=1)
233 
234             default_boxes.append(default_box)
235 
236         return torch.cat(default_boxes, dim=0)
237 
238     def __repr__(self) -> str:
239         s = (
240             f"{self.__class__.__name__}("
241             f"aspect_ratios={self.aspect_ratios}"
242             f", clip={self.clip}"
243             f", scales={self.scales}"
244             f", steps={self.steps}"
245             ")"
246         )
247         return s
248 
249     def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:
250         grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]
251         image_size = image_list.tensors.shape[-2:]
252         dtype, device = feature_maps[0].dtype, feature_maps[0].device
253         default_boxes = self._grid_default_boxes(grid_sizes, image_size, dtype=dtype)
254         default_boxes = default_boxes.to(device)
255 
256         dboxes = []
257         x_y_size = torch.tensor([image_size[1], image_size[0]], device=default_boxes.device)
258         for _ in image_list.image_sizes:
259             dboxes_in_image = default_boxes
260             dboxes_in_image = torch.cat(
261                 [
262                     (dboxes_in_image[:, :2] - 0.5 * dboxes_in_image[:, 2:]) * x_y_size,
263                     (dboxes_in_image[:, :2] + 0.5 * dboxes_in_image[:, 2:]) * x_y_size,
264                 ],
265                 -1,
266             )
267             dboxes.append(dboxes_in_image)
268         return dboxes
269
```
--- 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/anchor_utils.py b/torchvision/models/detection/anchor_utils.py
--- a/torchvision/models/detection/anchor_utils.py
+++ b/torchvision/models/detection/anchor_utils.py
@@ -213,8 +213,8 @@
         for k, f_k in enumerate(grid_sizes):
             # Now add the default boxes for each width-height pair
             if self.steps is not None:
-                x_f_k = image_size[0] / self.steps[k]
-                y_f_k = image_size[1] / self.steps[k]
+                x_f_k = image_size[1] / self.steps[k]
+                y_f_k = image_size[0] / self.steps[k]
             else:
                 y_f_k, x_f_k = f_k

{"golden_diff": "diff --git a/torchvision/models/detection/anchor_utils.py b/torchvision/models/detection/anchor_utils.py\n--- a/torchvision/models/detection/anchor_utils.py\n+++ b/torchvision/models/detection/anchor_utils.py\n@@ -213,8 +213,8 @@\n         for k, f_k in enumerate(grid_sizes):\n             # Now add the default boxes for each width-height pair\n             if self.steps is not None:\n-                x_f_k = image_size[0] / self.steps[k]\n-                y_f_k = image_size[1] / self.steps[k]\n+                x_f_k = image_size[1] / self.steps[k]\n+                y_f_k = image_size[0] / self.steps[k]\n             else:\n                 y_f_k, x_f_k = f_k\n", "issue": "Swapped width and height in DefaultBoxGenerator\nIn the DefaultBoxGenerator module, the image sizes in the image_size argument are given as (height, width) by SSD model but the code assumes (width, height).\r\n\r\nhttps://github.com/pytorch/vision/blob/15a9a93b9e0e6173b936691a2cddced0ecfd271f/torchvision/models/detection/anchor_utils.py#L216-L217\r\n\r\nI think this has gone unnoticed because the images are usually resized into squares.\n\ncc @datumbox\n", "before_files": [{"content": "import math\nfrom typing import List, Optional\n\nimport torch\nfrom torch import nn, Tensor\n\nfrom .image_list import ImageList\n\n\nclass AnchorGenerator(nn.Module):\n    \"\"\"\n    Module that generates anchors for a set of feature maps and\n    image sizes.\n\n    The module support computing anchors at multiple sizes and aspect ratios\n    per feature map. This module assumes aspect ratio = height / width for\n    each anchor.\n\n    sizes and aspect_ratios should have the same number of elements, and it should\n    correspond to the number of feature maps.\n\n    sizes[i] and aspect_ratios[i] can have an arbitrary number of elements,\n    and AnchorGenerator will output a set of sizes[i] * aspect_ratios[i] anchors\n    per spatial location for feature map i.\n\n    Args:\n        sizes (Tuple[Tuple[int]]):\n        aspect_ratios (Tuple[Tuple[float]]):\n    \"\"\"\n\n    __annotations__ = {\n        \"cell_anchors\": List[torch.Tensor],\n    }\n\n    def __init__(\n        self,\n        sizes=((128, 256, 512),),\n        aspect_ratios=((0.5, 1.0, 2.0),),\n    ):\n        super().__init__()\n\n        if not isinstance(sizes[0], (list, tuple)):\n            # TODO change this\n            sizes = tuple((s,) for s in sizes)\n        if not isinstance(aspect_ratios[0], (list, tuple)):\n            aspect_ratios = (aspect_ratios,) * len(sizes)\n\n        self.sizes = sizes\n        self.aspect_ratios = aspect_ratios\n        self.cell_anchors = [\n            self.generate_anchors(size, aspect_ratio) for size, aspect_ratio in zip(sizes, aspect_ratios)\n        ]\n\n    # TODO: https://github.com/pytorch/pytorch/issues/26792\n    # For every (aspect_ratios, scales) combination, output a zero-centered anchor with those values.\n    # (scales, aspect_ratios) are usually an element of zip(self.scales, self.aspect_ratios)\n    # This method assumes aspect ratio = height / width for an anchor.\n    def generate_anchors(\n        self,\n        scales: List[int],\n        aspect_ratios: List[float],\n        dtype: torch.dtype = torch.float32,\n        device: torch.device = torch.device(\"cpu\"),\n    ):\n        scales = torch.as_tensor(scales, dtype=dtype, device=device)\n        aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device)\n        h_ratios = torch.sqrt(aspect_ratios)\n        w_ratios = 1 / h_ratios\n\n        ws = (w_ratios[:, None] * scales[None, :]).view(-1)\n        hs = (h_ratios[:, None] * scales[None, :]).view(-1)\n\n        base_anchors = torch.stack([-ws, -hs, ws, hs], dim=1) / 2\n        return base_anchors.round()\n\n    def set_cell_anchors(self, dtype: torch.dtype, device: torch.device):\n        self.cell_anchors = [cell_anchor.to(dtype=dtype, device=device) for cell_anchor in self.cell_anchors]\n\n    def num_anchors_per_location(self):\n        return [len(s) * len(a) for s, a in zip(self.sizes, self.aspect_ratios)]\n\n    # For every combination of (a, (g, s), i) in (self.cell_anchors, zip(grid_sizes, strides), 0:2),\n    # output g[i] anchors that are s[i] distance apart in direction i, with the same dimensions as a.\n    def grid_anchors(self, grid_sizes: List[List[int]], strides: List[List[Tensor]]) -> List[Tensor]:\n        anchors = []\n        cell_anchors = self.cell_anchors\n        torch._assert(cell_anchors is not None, \"cell_anchors should not be None\")\n        torch._assert(\n            len(grid_sizes) == len(strides) == len(cell_anchors),\n            \"Anchors should be Tuple[Tuple[int]] because each feature \"\n            \"map could potentially have different sizes and aspect ratios. \"\n            \"There needs to be a match between the number of \"\n            \"feature maps passed and the number of sizes / aspect ratios specified.\",\n        )\n\n        for size, stride, base_anchors in zip(grid_sizes, strides, cell_anchors):\n            grid_height, grid_width = size\n            stride_height, stride_width = stride\n            device = base_anchors.device\n\n            # For output anchor, compute [x_center, y_center, x_center, y_center]\n            shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_width\n            shifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height\n            shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing=\"ij\")\n            shift_x = shift_x.reshape(-1)\n            shift_y = shift_y.reshape(-1)\n            shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1)\n\n            # For every (base anchor, output anchor) pair,\n            # offset each zero-centered base anchor by the center of the output anchor.\n            anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4))\n\n        return anchors\n\n    def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:\n        grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]\n        image_size = image_list.tensors.shape[-2:]\n        dtype, device = feature_maps[0].dtype, feature_maps[0].device\n        strides = [\n            [\n                torch.empty((), dtype=torch.int64, device=device).fill_(image_size[0] // g[0]),\n                torch.empty((), dtype=torch.int64, device=device).fill_(image_size[1] // g[1]),\n            ]\n            for g in grid_sizes\n        ]\n        self.set_cell_anchors(dtype, device)\n        anchors_over_all_feature_maps = self.grid_anchors(grid_sizes, strides)\n        anchors: List[List[torch.Tensor]] = []\n        for _ in range(len(image_list.image_sizes)):\n            anchors_in_image = [anchors_per_feature_map for anchors_per_feature_map in anchors_over_all_feature_maps]\n            anchors.append(anchors_in_image)\n        anchors = [torch.cat(anchors_per_image) for anchors_per_image in anchors]\n        return anchors\n\n\nclass DefaultBoxGenerator(nn.Module):\n    \"\"\"\n    This module generates the default boxes of SSD for a set of feature maps and image sizes.\n\n    Args:\n        aspect_ratios (List[List[int]]): A list with all the aspect ratios used in each feature map.\n        min_ratio (float): The minimum scale :math:`\\text{s}_{\\text{min}}` of the default boxes used in the estimation\n            of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.\n        max_ratio (float): The maximum scale :math:`\\text{s}_{\\text{max}}`  of the default boxes used in the estimation\n            of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.\n        scales (List[float]], optional): The scales of the default boxes. If not provided it will be estimated using\n            the ``min_ratio`` and ``max_ratio`` parameters.\n        steps (List[int]], optional): It's a hyper-parameter that affects the tiling of defalt boxes. If not provided\n            it will be estimated from the data.\n        clip (bool): Whether the standardized values of default boxes should be clipped between 0 and 1. The clipping\n            is applied while the boxes are encoded in format ``(cx, cy, w, h)``.\n    \"\"\"\n\n    def __init__(\n        self,\n        aspect_ratios: List[List[int]],\n        min_ratio: float = 0.15,\n        max_ratio: float = 0.9,\n        scales: Optional[List[float]] = None,\n        steps: Optional[List[int]] = None,\n        clip: bool = True,\n    ):\n        super().__init__()\n        if steps is not None and len(aspect_ratios) != len(steps):\n            raise ValueError(\"aspect_ratios and steps should have the same length\")\n        self.aspect_ratios = aspect_ratios\n        self.steps = steps\n        self.clip = clip\n        num_outputs = len(aspect_ratios)\n\n        # Estimation of default boxes scales\n        if scales is None:\n            if num_outputs > 1:\n                range_ratio = max_ratio - min_ratio\n                self.scales = [min_ratio + range_ratio * k / (num_outputs - 1.0) for k in range(num_outputs)]\n                self.scales.append(1.0)\n            else:\n                self.scales = [min_ratio, max_ratio]\n        else:\n            self.scales = scales\n\n        self._wh_pairs = self._generate_wh_pairs(num_outputs)\n\n    def _generate_wh_pairs(\n        self, num_outputs: int, dtype: torch.dtype = torch.float32, device: torch.device = torch.device(\"cpu\")\n    ) -> List[Tensor]:\n        _wh_pairs: List[Tensor] = []\n        for k in range(num_outputs):\n            # Adding the 2 default width-height pairs for aspect ratio 1 and scale s'k\n            s_k = self.scales[k]\n            s_prime_k = math.sqrt(self.scales[k] * self.scales[k + 1])\n            wh_pairs = [[s_k, s_k], [s_prime_k, s_prime_k]]\n\n            # Adding 2 pairs for each aspect ratio of the feature map k\n            for ar in self.aspect_ratios[k]:\n                sq_ar = math.sqrt(ar)\n                w = self.scales[k] * sq_ar\n                h = self.scales[k] / sq_ar\n                wh_pairs.extend([[w, h], [h, w]])\n\n            _wh_pairs.append(torch.as_tensor(wh_pairs, dtype=dtype, device=device))\n        return _wh_pairs\n\n    def num_anchors_per_location(self):\n        # Estimate num of anchors based on aspect ratios: 2 default boxes + 2 * ratios of feaure map.\n        return [2 + 2 * len(r) for r in self.aspect_ratios]\n\n    # Default Boxes calculation based on page 6 of SSD paper\n    def _grid_default_boxes(\n        self, grid_sizes: List[List[int]], image_size: List[int], dtype: torch.dtype = torch.float32\n    ) -> Tensor:\n        default_boxes = []\n        for k, f_k in enumerate(grid_sizes):\n            # Now add the default boxes for each width-height pair\n            if self.steps is not None:\n                x_f_k = image_size[0] / self.steps[k]\n                y_f_k = image_size[1] / self.steps[k]\n            else:\n                y_f_k, x_f_k = f_k\n\n            shifts_x = ((torch.arange(0, f_k[1]) + 0.5) / x_f_k).to(dtype=dtype)\n            shifts_y = ((torch.arange(0, f_k[0]) + 0.5) / y_f_k).to(dtype=dtype)\n            shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing=\"ij\")\n            shift_x = shift_x.reshape(-1)\n            shift_y = shift_y.reshape(-1)\n\n            shifts = torch.stack((shift_x, shift_y) * len(self._wh_pairs[k]), dim=-1).reshape(-1, 2)\n            # Clipping the default boxes while the boxes are encoded in format (cx, cy, w, h)\n            _wh_pair = self._wh_pairs[k].clamp(min=0, max=1) if self.clip else self._wh_pairs[k]\n            wh_pairs = _wh_pair.repeat((f_k[0] * f_k[1]), 1)\n\n            default_box = torch.cat((shifts, wh_pairs), dim=1)\n\n            default_boxes.append(default_box)\n\n        return torch.cat(default_boxes, dim=0)\n\n    def __repr__(self) -> str:\n        s = (\n            f\"{self.__class__.__name__}(\"\n            f\"aspect_ratios={self.aspect_ratios}\"\n            f\", clip={self.clip}\"\n            f\", scales={self.scales}\"\n            f\", steps={self.steps}\"\n            \")\"\n        )\n        return s\n\n    def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:\n        grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]\n        image_size = image_list.tensors.shape[-2:]\n        dtype, device = feature_maps[0].dtype, feature_maps[0].device\n        default_boxes = self._grid_default_boxes(grid_sizes, image_size, dtype=dtype)\n        default_boxes = default_boxes.to(device)\n\n        dboxes = []\n        x_y_size = torch.tensor([image_size[1], image_size[0]], device=default_boxes.device)\n        for _ in image_list.image_sizes:\n            dboxes_in_image = default_boxes\n            dboxes_in_image = torch.cat(\n                [\n                    (dboxes_in_image[:, :2] - 0.5 * dboxes_in_image[:, 2:]) * x_y_size,\n                    (dboxes_in_image[:, :2] + 0.5 * dboxes_in_image[:, 2:]) * x_y_size,\n                ],\n                -1,\n            )\n            dboxes.append(dboxes_in_image)\n        return dboxes\n", "path": "torchvision/models/detection/anchor_utils.py"}], "after_files": [{"content": "import math\nfrom typing import List, Optional\n\nimport torch\nfrom torch import nn, Tensor\n\nfrom .image_list import ImageList\n\n\nclass AnchorGenerator(nn.Module):\n    \"\"\"\n    Module that generates anchors for a set of feature maps and\n    image sizes.\n\n    The module support computing anchors at multiple sizes and aspect ratios\n    per feature map. This module assumes aspect ratio = height / width for\n    each anchor.\n\n    sizes and aspect_ratios should have the same number of elements, and it should\n    correspond to the number of feature maps.\n\n    sizes[i] and aspect_ratios[i] can have an arbitrary number of elements,\n    and AnchorGenerator will output a set of sizes[i] * aspect_ratios[i] anchors\n    per spatial location for feature map i.\n\n    Args:\n        sizes (Tuple[Tuple[int]]):\n        aspect_ratios (Tuple[Tuple[float]]):\n    \"\"\"\n\n    __annotations__ = {\n        \"cell_anchors\": List[torch.Tensor],\n    }\n\n    def __init__(\n        self,\n        sizes=((128, 256, 512),),\n        aspect_ratios=((0.5, 1.0, 2.0),),\n    ):\n        super().__init__()\n\n        if not isinstance(sizes[0], (list, tuple)):\n            # TODO change this\n            sizes = tuple((s,) for s in sizes)\n        if not isinstance(aspect_ratios[0], (list, tuple)):\n            aspect_ratios = (aspect_ratios,) * len(sizes)\n\n        self.sizes = sizes\n        self.aspect_ratios = aspect_ratios\n        self.cell_anchors = [\n            self.generate_anchors(size, aspect_ratio) for size, aspect_ratio in zip(sizes, aspect_ratios)\n        ]\n\n    # TODO: https://github.com/pytorch/pytorch/issues/26792\n    # For every (aspect_ratios, scales) combination, output a zero-centered anchor with those values.\n    # (scales, aspect_ratios) are usually an element of zip(self.scales, self.aspect_ratios)\n    # This method assumes aspect ratio = height / width for an anchor.\n    def generate_anchors(\n        self,\n        scales: List[int],\n        aspect_ratios: List[float],\n        dtype: torch.dtype = torch.float32,\n        device: torch.device = torch.device(\"cpu\"),\n    ):\n        scales = torch.as_tensor(scales, dtype=dtype, device=device)\n        aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device)\n        h_ratios = torch.sqrt(aspect_ratios)\n        w_ratios = 1 / h_ratios\n\n        ws = (w_ratios[:, None] * scales[None, :]).view(-1)\n        hs = (h_ratios[:, None] * scales[None, :]).view(-1)\n\n        base_anchors = torch.stack([-ws, -hs, ws, hs], dim=1) / 2\n        return base_anchors.round()\n\n    def set_cell_anchors(self, dtype: torch.dtype, device: torch.device):\n        self.cell_anchors = [cell_anchor.to(dtype=dtype, device=device) for cell_anchor in self.cell_anchors]\n\n    def num_anchors_per_location(self):\n        return [len(s) * len(a) for s, a in zip(self.sizes, self.aspect_ratios)]\n\n    # For every combination of (a, (g, s), i) in (self.cell_anchors, zip(grid_sizes, strides), 0:2),\n    # output g[i] anchors that are s[i] distance apart in direction i, with the same dimensions as a.\n    def grid_anchors(self, grid_sizes: List[List[int]], strides: List[List[Tensor]]) -> List[Tensor]:\n        anchors = []\n        cell_anchors = self.cell_anchors\n        torch._assert(cell_anchors is not None, \"cell_anchors should not be None\")\n        torch._assert(\n            len(grid_sizes) == len(strides) == len(cell_anchors),\n            \"Anchors should be Tuple[Tuple[int]] because each feature \"\n            \"map could potentially have different sizes and aspect ratios. \"\n            \"There needs to be a match between the number of \"\n            \"feature maps passed and the number of sizes / aspect ratios specified.\",\n        )\n\n        for size, stride, base_anchors in zip(grid_sizes, strides, cell_anchors):\n            grid_height, grid_width = size\n            stride_height, stride_width = stride\n            device = base_anchors.device\n\n            # For output anchor, compute [x_center, y_center, x_center, y_center]\n            shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_width\n            shifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height\n            shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing=\"ij\")\n            shift_x = shift_x.reshape(-1)\n            shift_y = shift_y.reshape(-1)\n            shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1)\n\n            # For every (base anchor, output anchor) pair,\n            # offset each zero-centered base anchor by the center of the output anchor.\n            anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4))\n\n        return anchors\n\n    def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:\n        grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]\n        image_size = image_list.tensors.shape[-2:]\n        dtype, device = feature_maps[0].dtype, feature_maps[0].device\n        strides = [\n            [\n                torch.empty((), dtype=torch.int64, device=device).fill_(image_size[0] // g[0]),\n                torch.empty((), dtype=torch.int64, device=device).fill_(image_size[1] // g[1]),\n            ]\n            for g in grid_sizes\n        ]\n        self.set_cell_anchors(dtype, device)\n        anchors_over_all_feature_maps = self.grid_anchors(grid_sizes, strides)\n        anchors: List[List[torch.Tensor]] = []\n        for _ in range(len(image_list.image_sizes)):\n            anchors_in_image = [anchors_per_feature_map for anchors_per_feature_map in anchors_over_all_feature_maps]\n            anchors.append(anchors_in_image)\n        anchors = [torch.cat(anchors_per_image) for anchors_per_image in anchors]\n        return anchors\n\n\nclass DefaultBoxGenerator(nn.Module):\n    \"\"\"\n    This module generates the default boxes of SSD for a set of feature maps and image sizes.\n\n    Args:\n        aspect_ratios (List[List[int]]): A list with all the aspect ratios used in each feature map.\n        min_ratio (float): The minimum scale :math:`\\text{s}_{\\text{min}}` of the default boxes used in the estimation\n            of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.\n        max_ratio (float): The maximum scale :math:`\\text{s}_{\\text{max}}`  of the default boxes used in the estimation\n            of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.\n        scales (List[float]], optional): The scales of the default boxes. If not provided it will be estimated using\n            the ``min_ratio`` and ``max_ratio`` parameters.\n        steps (List[int]], optional): It's a hyper-parameter that affects the tiling of defalt boxes. If not provided\n            it will be estimated from the data.\n        clip (bool): Whether the standardized values of default boxes should be clipped between 0 and 1. The clipping\n            is applied while the boxes are encoded in format ``(cx, cy, w, h)``.\n    \"\"\"\n\n    def __init__(\n        self,\n        aspect_ratios: List[List[int]],\n        min_ratio: float = 0.15,\n        max_ratio: float = 0.9,\n        scales: Optional[List[float]] = None,\n        steps: Optional[List[int]] = None,\n        clip: bool = True,\n    ):\n        super().__init__()\n        if steps is not None and len(aspect_ratios) != len(steps):\n            raise ValueError(\"aspect_ratios and steps should have the same length\")\n        self.aspect_ratios = aspect_ratios\n        self.steps = steps\n        self.clip = clip\n        num_outputs = len(aspect_ratios)\n\n        # Estimation of default boxes scales\n        if scales is None:\n            if num_outputs > 1:\n                range_ratio = max_ratio - min_ratio\n                self.scales = [min_ratio + range_ratio * k / (num_outputs - 1.0) for k in range(num_outputs)]\n                self.scales.append(1.0)\n            else:\n                self.scales = [min_ratio, max_ratio]\n        else:\n            self.scales = scales\n\n        self._wh_pairs = self._generate_wh_pairs(num_outputs)\n\n    def _generate_wh_pairs(\n        self, num_outputs: int, dtype: torch.dtype = torch.float32, device: torch.device = torch.device(\"cpu\")\n    ) -> List[Tensor]:\n        _wh_pairs: List[Tensor] = []\n        for k in range(num_outputs):\n            # Adding the 2 default width-height pairs for aspect ratio 1 and scale s'k\n            s_k = self.scales[k]\n            s_prime_k = math.sqrt(self.scales[k] * self.scales[k + 1])\n            wh_pairs = [[s_k, s_k], [s_prime_k, s_prime_k]]\n\n            # Adding 2 pairs for each aspect ratio of the feature map k\n            for ar in self.aspect_ratios[k]:\n                sq_ar = math.sqrt(ar)\n                w = self.scales[k] * sq_ar\n                h = self.scales[k] / sq_ar\n                wh_pairs.extend([[w, h], [h, w]])\n\n            _wh_pairs.append(torch.as_tensor(wh_pairs, dtype=dtype, device=device))\n        return _wh_pairs\n\n    def num_anchors_per_location(self):\n        # Estimate num of anchors based on aspect ratios: 2 default boxes + 2 * ratios of feaure map.\n        return [2 + 2 * len(r) for r in self.aspect_ratios]\n\n    # Default Boxes calculation based on page 6 of SSD paper\n    def _grid_default_boxes(\n        self, grid_sizes: List[List[int]], image_size: List[int], dtype: torch.dtype = torch.float32\n    ) -> Tensor:\n        default_boxes = []\n        for k, f_k in enumerate(grid_sizes):\n            # Now add the default boxes for each width-height pair\n            if self.steps is not None:\n                x_f_k = image_size[1] / self.steps[k]\n                y_f_k = image_size[0] / self.steps[k]\n            else:\n                y_f_k, x_f_k = f_k\n\n            shifts_x = ((torch.arange(0, f_k[1]) + 0.5) / x_f_k).to(dtype=dtype)\n            shifts_y = ((torch.arange(0, f_k[0]) + 0.5) / y_f_k).to(dtype=dtype)\n            shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing=\"ij\")\n            shift_x = shift_x.reshape(-1)\n            shift_y = shift_y.reshape(-1)\n\n            shifts = torch.stack((shift_x, shift_y) * len(self._wh_pairs[k]), dim=-1).reshape(-1, 2)\n            # Clipping the default boxes while the boxes are encoded in format (cx, cy, w, h)\n            _wh_pair = self._wh_pairs[k].clamp(min=0, max=1) if self.clip else self._wh_pairs[k]\n            wh_pairs = _wh_pair.repeat((f_k[0] * f_k[1]), 1)\n\n            default_box = torch.cat((shifts, wh_pairs), dim=1)\n\n            default_boxes.append(default_box)\n\n        return torch.cat(default_boxes, dim=0)\n\n    def __repr__(self) -> str:\n        s = (\n            f\"{self.__class__.__name__}(\"\n            f\"aspect_ratios={self.aspect_ratios}\"\n            f\", clip={self.clip}\"\n            f\", scales={self.scales}\"\n            f\", steps={self.steps}\"\n            \")\"\n        )\n        return s\n\n    def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:\n        grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]\n        image_size = image_list.tensors.shape[-2:]\n        dtype, device = feature_maps[0].dtype, feature_maps[0].device\n        default_boxes = self._grid_default_boxes(grid_sizes, image_size, dtype=dtype)\n        default_boxes = default_boxes.to(device)\n\n        dboxes = []\n        x_y_size = torch.tensor([image_size[1], image_size[0]], device=default_boxes.device)\n        for _ in image_list.image_sizes:\n            dboxes_in_image = default_boxes\n            dboxes_in_image = torch.cat(\n                [\n                    (dboxes_in_image[:, :2] - 0.5 * dboxes_in_image[:, 2:]) * x_y_size,\n                    (dboxes_in_image[:, :2] + 0.5 * dboxes_in_image[:, 2:]) * x_y_size,\n                ],\n                -1,\n            )\n            dboxes.append(dboxes_in_image)\n        return dboxes\n", "path": "torchvision/models/detection/anchor_utils.py"}]}