We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
crpn_faster_rcnn gets "No gt bboxes" error
Hello, 

I have been trying to run crpn_faster_rcnn but the training always fails with "No gt bboxes" error. 

I am using custom models but the model does have a region proposals as I am loading the weights from pre-trained weights for crpn I created from the same dataset. 

I've played around with the learning rate but no chance.

Do you have any hint or advice on what is going on? Thanks.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mmdet/core/bbox/assigners/region_assigner.py`
Content:
```
1 import torch
2 
3 from mmdet.core import anchor_inside_flags
4 from ..builder import BBOX_ASSIGNERS
5 from .assign_result import AssignResult
6 from .base_assigner import BaseAssigner
7 
8 
9 def calc_region(bbox, ratio, stride, featmap_size=None):
10     """Calculate region of the box defined by the ratio, the ratio is from the
11     center of the box to every edge."""
12     # project bbox on the feature
13     f_bbox = bbox / stride
14     x1 = torch.round((1 - ratio) * f_bbox[0] + ratio * f_bbox[2])
15     y1 = torch.round((1 - ratio) * f_bbox[1] + ratio * f_bbox[3])
16     x2 = torch.round(ratio * f_bbox[0] + (1 - ratio) * f_bbox[2])
17     y2 = torch.round(ratio * f_bbox[1] + (1 - ratio) * f_bbox[3])
18     if featmap_size is not None:
19         x1 = x1.clamp(min=0, max=featmap_size[1])
20         y1 = y1.clamp(min=0, max=featmap_size[0])
21         x2 = x2.clamp(min=0, max=featmap_size[1])
22         y2 = y2.clamp(min=0, max=featmap_size[0])
23     return (x1, y1, x2, y2)
24 
25 
26 def anchor_ctr_inside_region_flags(anchors, stride, region):
27     """Get the flag indicate whether anchor centers are inside regions."""
28     x1, y1, x2, y2 = region
29     f_anchors = anchors / stride
30     x = (f_anchors[:, 0] + f_anchors[:, 2]) * 0.5
31     y = (f_anchors[:, 1] + f_anchors[:, 3]) * 0.5
32     flags = (x >= x1) & (x <= x2) & (y >= y1) & (y <= y2)
33     return flags
34 
35 
36 @BBOX_ASSIGNERS.register_module()
37 class RegionAssigner(BaseAssigner):
38     """Assign a corresponding gt bbox or background to each bbox.
39 
40     Each proposals will be assigned with `-1`, `0`, or a positive integer
41     indicating the ground truth index.
42 
43     - -1: don't care
44     - 0: negative sample, no assigned gt
45     - positive integer: positive sample, index (1-based) of assigned gt
46 
47     Args:
48         center_ratio: ratio of the region in the center of the bbox to
49             define positive sample.
50         ignore_ratio: ratio of the region to define ignore samples.
51     """
52 
53     def __init__(self, center_ratio=0.2, ignore_ratio=0.5):
54         self.center_ratio = center_ratio
55         self.ignore_ratio = ignore_ratio
56 
57     def assign(self,
58                mlvl_anchors,
59                mlvl_valid_flags,
60                gt_bboxes,
61                img_meta,
62                featmap_sizes,
63                anchor_scale,
64                anchor_strides,
65                gt_bboxes_ignore=None,
66                gt_labels=None,
67                allowed_border=0):
68         """Assign gt to anchors.
69 
70         This method assign a gt bbox to every bbox (proposal/anchor), each bbox
71         will be assigned with -1, 0, or a positive number. -1 means don't care,
72         0 means negative sample, positive number is the index (1-based) of
73         assigned gt.
74         The assignment is done in following steps, the order matters.
75 
76         1. Assign every anchor to 0 (negative)
77         For each gt_bboxes:
78             2. Compute ignore flags based on ignore_region then
79                 assign -1 to anchors w.r.t. ignore flags
80             3. Compute pos flags based on center_region then
81                assign gt_bboxes to anchors w.r.t. pos flags
82             4. Compute ignore flags based on adjacent anchor lvl then
83                assign -1 to anchors w.r.t. ignore flags
84             5. Assign anchor outside of image to -1
85 
86         Args:
87             mlvl_anchors (list[Tensor]): Multi level anchors.
88             mlvl_valid_flags (list[Tensor]): Multi level valid flags.
89             gt_bboxes (Tensor): Ground truth bboxes of image
90             img_meta (dict): Meta info of image.
91             featmap_sizes (list[Tensor]): Feature mapsize each level
92             anchor_scale (int): Scale of the anchor.
93             anchor_strides (list[int]): Stride of the anchor.
94             gt_bboxes (Tensor): Groundtruth boxes, shape (k, 4).
95             gt_bboxes_ignore (Tensor, optional): Ground truth bboxes that are
96                 labelled as `ignored`, e.g., crowd boxes in COCO.
97             gt_labels (Tensor, optional): Label of gt_bboxes, shape (k, ).
98             allowed_border (int, optional): The border to allow the valid
99                 anchor. Defaults to 0.
100 
101         Returns:
102             :obj:`AssignResult`: The assign result.
103         """
104         # TODO support gt_bboxes_ignore
105         if gt_bboxes_ignore is not None:
106             raise NotImplementedError
107         if gt_bboxes.shape[0] == 0:
108             raise ValueError('No gt bboxes')
109         num_gts = gt_bboxes.shape[0]
110         num_lvls = len(mlvl_anchors)
111         r1 = (1 - self.center_ratio) / 2
112         r2 = (1 - self.ignore_ratio) / 2
113 
114         scale = torch.sqrt((gt_bboxes[:, 2] - gt_bboxes[:, 0]) *
115                            (gt_bboxes[:, 3] - gt_bboxes[:, 1]))
116         min_anchor_size = scale.new_full(
117             (1, ), float(anchor_scale * anchor_strides[0]))
118         target_lvls = torch.floor(
119             torch.log2(scale) - torch.log2(min_anchor_size) + 0.5)
120         target_lvls = target_lvls.clamp(min=0, max=num_lvls - 1).long()
121 
122         # 1. assign 0 (negative) by default
123         mlvl_assigned_gt_inds = []
124         mlvl_ignore_flags = []
125         for lvl in range(num_lvls):
126             h, w = featmap_sizes[lvl]
127             assert h * w == mlvl_anchors[lvl].shape[0]
128             assigned_gt_inds = gt_bboxes.new_full((h * w, ),
129                                                   0,
130                                                   dtype=torch.long)
131             ignore_flags = torch.zeros_like(assigned_gt_inds)
132             mlvl_assigned_gt_inds.append(assigned_gt_inds)
133             mlvl_ignore_flags.append(ignore_flags)
134 
135         for gt_id in range(num_gts):
136             lvl = target_lvls[gt_id].item()
137             featmap_size = featmap_sizes[lvl]
138             stride = anchor_strides[lvl]
139             anchors = mlvl_anchors[lvl]
140             gt_bbox = gt_bboxes[gt_id, :4]
141 
142             # Compute regions
143             ignore_region = calc_region(gt_bbox, r2, stride, featmap_size)
144             ctr_region = calc_region(gt_bbox, r1, stride, featmap_size)
145 
146             # 2. Assign -1 to ignore flags
147             ignore_flags = anchor_ctr_inside_region_flags(
148                 anchors, stride, ignore_region)
149             mlvl_assigned_gt_inds[lvl][ignore_flags] = -1
150 
151             # 3. Assign gt_bboxes to pos flags
152             pos_flags = anchor_ctr_inside_region_flags(anchors, stride,
153                                                        ctr_region)
154             mlvl_assigned_gt_inds[lvl][pos_flags] = gt_id + 1
155 
156             # 4. Assign -1 to ignore adjacent lvl
157             if lvl > 0:
158                 d_lvl = lvl - 1
159                 d_anchors = mlvl_anchors[d_lvl]
160                 d_featmap_size = featmap_sizes[d_lvl]
161                 d_stride = anchor_strides[d_lvl]
162                 d_ignore_region = calc_region(gt_bbox, r2, d_stride,
163                                               d_featmap_size)
164                 ignore_flags = anchor_ctr_inside_region_flags(
165                     d_anchors, d_stride, d_ignore_region)
166                 mlvl_ignore_flags[d_lvl][ignore_flags] = 1
167             if lvl < num_lvls - 1:
168                 u_lvl = lvl + 1
169                 u_anchors = mlvl_anchors[u_lvl]
170                 u_featmap_size = featmap_sizes[u_lvl]
171                 u_stride = anchor_strides[u_lvl]
172                 u_ignore_region = calc_region(gt_bbox, r2, u_stride,
173                                               u_featmap_size)
174                 ignore_flags = anchor_ctr_inside_region_flags(
175                     u_anchors, u_stride, u_ignore_region)
176                 mlvl_ignore_flags[u_lvl][ignore_flags] = 1
177 
178         # 4. (cont.) Assign -1 to ignore adjacent lvl
179         for lvl in range(num_lvls):
180             ignore_flags = mlvl_ignore_flags[lvl]
181             mlvl_assigned_gt_inds[lvl][ignore_flags] = -1
182 
183         # 5. Assign -1 to anchor outside of image
184         flat_assigned_gt_inds = torch.cat(mlvl_assigned_gt_inds)
185         flat_anchors = torch.cat(mlvl_anchors)
186         flat_valid_flags = torch.cat(mlvl_valid_flags)
187         assert (flat_assigned_gt_inds.shape[0] == flat_anchors.shape[0] ==
188                 flat_valid_flags.shape[0])
189         inside_flags = anchor_inside_flags(flat_anchors, flat_valid_flags,
190                                            img_meta['img_shape'],
191                                            allowed_border)
192         outside_flags = ~inside_flags
193         flat_assigned_gt_inds[outside_flags] = -1
194 
195         if gt_labels is not None:
196             assigned_labels = torch.zeros_like(flat_assigned_gt_inds)
197             pos_flags = assigned_gt_inds > 0
198             assigned_labels[pos_flags] = gt_labels[
199                 flat_assigned_gt_inds[pos_flags] - 1]
200         else:
201             assigned_labels = None
202 
203         return AssignResult(
204             num_gts, flat_assigned_gt_inds, None, labels=assigned_labels)
205
```
--- 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/mmdet/core/bbox/assigners/region_assigner.py b/mmdet/core/bbox/assigners/region_assigner.py
--- a/mmdet/core/bbox/assigners/region_assigner.py
+++ b/mmdet/core/bbox/assigners/region_assigner.py
@@ -101,12 +101,29 @@
         Returns:
             :obj:`AssignResult`: The assign result.
         """
-        # TODO support gt_bboxes_ignore
         if gt_bboxes_ignore is not None:
             raise NotImplementedError
-        if gt_bboxes.shape[0] == 0:
-            raise ValueError('No gt bboxes')
+
         num_gts = gt_bboxes.shape[0]
+        num_bboxes = sum(x.shape[0] for x in mlvl_anchors)
+
+        if num_gts == 0 or num_bboxes == 0:
+            # No ground truth or boxes, return empty assignment
+            max_overlaps = gt_bboxes.new_zeros((num_bboxes, ))
+            assigned_gt_inds = gt_bboxes.new_zeros((num_bboxes, ),
+                                                   dtype=torch.long)
+            if gt_labels is None:
+                assigned_labels = None
+            else:
+                assigned_labels = gt_bboxes.new_full((num_bboxes, ),
+                                                     -1,
+                                                     dtype=torch.long)
+            return AssignResult(
+                num_gts,
+                assigned_gt_inds,
+                max_overlaps,
+                labels=assigned_labels)
+
         num_lvls = len(mlvl_anchors)
         r1 = (1 - self.center_ratio) / 2
         r2 = (1 - self.ignore_ratio) / 2

{"golden_diff": "diff --git a/mmdet/core/bbox/assigners/region_assigner.py b/mmdet/core/bbox/assigners/region_assigner.py\n--- a/mmdet/core/bbox/assigners/region_assigner.py\n+++ b/mmdet/core/bbox/assigners/region_assigner.py\n@@ -101,12 +101,29 @@\n         Returns:\n             :obj:`AssignResult`: The assign result.\n         \"\"\"\n-        # TODO support gt_bboxes_ignore\n         if gt_bboxes_ignore is not None:\n             raise NotImplementedError\n-        if gt_bboxes.shape[0] == 0:\n-            raise ValueError('No gt bboxes')\n+\n         num_gts = gt_bboxes.shape[0]\n+        num_bboxes = sum(x.shape[0] for x in mlvl_anchors)\n+\n+        if num_gts == 0 or num_bboxes == 0:\n+            # No ground truth or boxes, return empty assignment\n+            max_overlaps = gt_bboxes.new_zeros((num_bboxes, ))\n+            assigned_gt_inds = gt_bboxes.new_zeros((num_bboxes, ),\n+                                                   dtype=torch.long)\n+            if gt_labels is None:\n+                assigned_labels = None\n+            else:\n+                assigned_labels = gt_bboxes.new_full((num_bboxes, ),\n+                                                     -1,\n+                                                     dtype=torch.long)\n+            return AssignResult(\n+                num_gts,\n+                assigned_gt_inds,\n+                max_overlaps,\n+                labels=assigned_labels)\n+\n         num_lvls = len(mlvl_anchors)\n         r1 = (1 - self.center_ratio) / 2\n         r2 = (1 - self.ignore_ratio) / 2\n", "issue": "crpn_faster_rcnn gets \"No gt bboxes\" error\nHello, \r\n\r\nI have been trying to run crpn_faster_rcnn but the training always fails with \"No gt bboxes\" error. \r\n\r\nI am using custom models but the model does have a region proposals as I am loading the weights from pre-trained weights for crpn I created from the same dataset. \r\n\r\nI've played around with the learning rate but no chance.\r\n\r\nDo you have any hint or advice on what is going on? Thanks.\n", "before_files": [{"content": "import torch\n\nfrom mmdet.core import anchor_inside_flags\nfrom ..builder import BBOX_ASSIGNERS\nfrom .assign_result import AssignResult\nfrom .base_assigner import BaseAssigner\n\n\ndef calc_region(bbox, ratio, stride, featmap_size=None):\n    \"\"\"Calculate region of the box defined by the ratio, the ratio is from the\n    center of the box to every edge.\"\"\"\n    # project bbox on the feature\n    f_bbox = bbox / stride\n    x1 = torch.round((1 - ratio) * f_bbox[0] + ratio * f_bbox[2])\n    y1 = torch.round((1 - ratio) * f_bbox[1] + ratio * f_bbox[3])\n    x2 = torch.round(ratio * f_bbox[0] + (1 - ratio) * f_bbox[2])\n    y2 = torch.round(ratio * f_bbox[1] + (1 - ratio) * f_bbox[3])\n    if featmap_size is not None:\n        x1 = x1.clamp(min=0, max=featmap_size[1])\n        y1 = y1.clamp(min=0, max=featmap_size[0])\n        x2 = x2.clamp(min=0, max=featmap_size[1])\n        y2 = y2.clamp(min=0, max=featmap_size[0])\n    return (x1, y1, x2, y2)\n\n\ndef anchor_ctr_inside_region_flags(anchors, stride, region):\n    \"\"\"Get the flag indicate whether anchor centers are inside regions.\"\"\"\n    x1, y1, x2, y2 = region\n    f_anchors = anchors / stride\n    x = (f_anchors[:, 0] + f_anchors[:, 2]) * 0.5\n    y = (f_anchors[:, 1] + f_anchors[:, 3]) * 0.5\n    flags = (x >= x1) & (x <= x2) & (y >= y1) & (y <= y2)\n    return flags\n\n\n@BBOX_ASSIGNERS.register_module()\nclass RegionAssigner(BaseAssigner):\n    \"\"\"Assign a corresponding gt bbox or background to each bbox.\n\n    Each proposals will be assigned with `-1`, `0`, or a positive integer\n    indicating the ground truth index.\n\n    - -1: don't care\n    - 0: negative sample, no assigned gt\n    - positive integer: positive sample, index (1-based) of assigned gt\n\n    Args:\n        center_ratio: ratio of the region in the center of the bbox to\n            define positive sample.\n        ignore_ratio: ratio of the region to define ignore samples.\n    \"\"\"\n\n    def __init__(self, center_ratio=0.2, ignore_ratio=0.5):\n        self.center_ratio = center_ratio\n        self.ignore_ratio = ignore_ratio\n\n    def assign(self,\n               mlvl_anchors,\n               mlvl_valid_flags,\n               gt_bboxes,\n               img_meta,\n               featmap_sizes,\n               anchor_scale,\n               anchor_strides,\n               gt_bboxes_ignore=None,\n               gt_labels=None,\n               allowed_border=0):\n        \"\"\"Assign gt to anchors.\n\n        This method assign a gt bbox to every bbox (proposal/anchor), each bbox\n        will be assigned with -1, 0, or a positive number. -1 means don't care,\n        0 means negative sample, positive number is the index (1-based) of\n        assigned gt.\n        The assignment is done in following steps, the order matters.\n\n        1. Assign every anchor to 0 (negative)\n        For each gt_bboxes:\n            2. Compute ignore flags based on ignore_region then\n                assign -1 to anchors w.r.t. ignore flags\n            3. Compute pos flags based on center_region then\n               assign gt_bboxes to anchors w.r.t. pos flags\n            4. Compute ignore flags based on adjacent anchor lvl then\n               assign -1 to anchors w.r.t. ignore flags\n            5. Assign anchor outside of image to -1\n\n        Args:\n            mlvl_anchors (list[Tensor]): Multi level anchors.\n            mlvl_valid_flags (list[Tensor]): Multi level valid flags.\n            gt_bboxes (Tensor): Ground truth bboxes of image\n            img_meta (dict): Meta info of image.\n            featmap_sizes (list[Tensor]): Feature mapsize each level\n            anchor_scale (int): Scale of the anchor.\n            anchor_strides (list[int]): Stride of the anchor.\n            gt_bboxes (Tensor): Groundtruth boxes, shape (k, 4).\n            gt_bboxes_ignore (Tensor, optional): Ground truth bboxes that are\n                labelled as `ignored`, e.g., crowd boxes in COCO.\n            gt_labels (Tensor, optional): Label of gt_bboxes, shape (k, ).\n            allowed_border (int, optional): The border to allow the valid\n                anchor. Defaults to 0.\n\n        Returns:\n            :obj:`AssignResult`: The assign result.\n        \"\"\"\n        # TODO support gt_bboxes_ignore\n        if gt_bboxes_ignore is not None:\n            raise NotImplementedError\n        if gt_bboxes.shape[0] == 0:\n            raise ValueError('No gt bboxes')\n        num_gts = gt_bboxes.shape[0]\n        num_lvls = len(mlvl_anchors)\n        r1 = (1 - self.center_ratio) / 2\n        r2 = (1 - self.ignore_ratio) / 2\n\n        scale = torch.sqrt((gt_bboxes[:, 2] - gt_bboxes[:, 0]) *\n                           (gt_bboxes[:, 3] - gt_bboxes[:, 1]))\n        min_anchor_size = scale.new_full(\n            (1, ), float(anchor_scale * anchor_strides[0]))\n        target_lvls = torch.floor(\n            torch.log2(scale) - torch.log2(min_anchor_size) + 0.5)\n        target_lvls = target_lvls.clamp(min=0, max=num_lvls - 1).long()\n\n        # 1. assign 0 (negative) by default\n        mlvl_assigned_gt_inds = []\n        mlvl_ignore_flags = []\n        for lvl in range(num_lvls):\n            h, w = featmap_sizes[lvl]\n            assert h * w == mlvl_anchors[lvl].shape[0]\n            assigned_gt_inds = gt_bboxes.new_full((h * w, ),\n                                                  0,\n                                                  dtype=torch.long)\n            ignore_flags = torch.zeros_like(assigned_gt_inds)\n            mlvl_assigned_gt_inds.append(assigned_gt_inds)\n            mlvl_ignore_flags.append(ignore_flags)\n\n        for gt_id in range(num_gts):\n            lvl = target_lvls[gt_id].item()\n            featmap_size = featmap_sizes[lvl]\n            stride = anchor_strides[lvl]\n            anchors = mlvl_anchors[lvl]\n            gt_bbox = gt_bboxes[gt_id, :4]\n\n            # Compute regions\n            ignore_region = calc_region(gt_bbox, r2, stride, featmap_size)\n            ctr_region = calc_region(gt_bbox, r1, stride, featmap_size)\n\n            # 2. Assign -1 to ignore flags\n            ignore_flags = anchor_ctr_inside_region_flags(\n                anchors, stride, ignore_region)\n            mlvl_assigned_gt_inds[lvl][ignore_flags] = -1\n\n            # 3. Assign gt_bboxes to pos flags\n            pos_flags = anchor_ctr_inside_region_flags(anchors, stride,\n                                                       ctr_region)\n            mlvl_assigned_gt_inds[lvl][pos_flags] = gt_id + 1\n\n            # 4. Assign -1 to ignore adjacent lvl\n            if lvl > 0:\n                d_lvl = lvl - 1\n                d_anchors = mlvl_anchors[d_lvl]\n                d_featmap_size = featmap_sizes[d_lvl]\n                d_stride = anchor_strides[d_lvl]\n                d_ignore_region = calc_region(gt_bbox, r2, d_stride,\n                                              d_featmap_size)\n                ignore_flags = anchor_ctr_inside_region_flags(\n                    d_anchors, d_stride, d_ignore_region)\n                mlvl_ignore_flags[d_lvl][ignore_flags] = 1\n            if lvl < num_lvls - 1:\n                u_lvl = lvl + 1\n                u_anchors = mlvl_anchors[u_lvl]\n                u_featmap_size = featmap_sizes[u_lvl]\n                u_stride = anchor_strides[u_lvl]\n                u_ignore_region = calc_region(gt_bbox, r2, u_stride,\n                                              u_featmap_size)\n                ignore_flags = anchor_ctr_inside_region_flags(\n                    u_anchors, u_stride, u_ignore_region)\n                mlvl_ignore_flags[u_lvl][ignore_flags] = 1\n\n        # 4. (cont.) Assign -1 to ignore adjacent lvl\n        for lvl in range(num_lvls):\n            ignore_flags = mlvl_ignore_flags[lvl]\n            mlvl_assigned_gt_inds[lvl][ignore_flags] = -1\n\n        # 5. Assign -1 to anchor outside of image\n        flat_assigned_gt_inds = torch.cat(mlvl_assigned_gt_inds)\n        flat_anchors = torch.cat(mlvl_anchors)\n        flat_valid_flags = torch.cat(mlvl_valid_flags)\n        assert (flat_assigned_gt_inds.shape[0] == flat_anchors.shape[0] ==\n                flat_valid_flags.shape[0])\n        inside_flags = anchor_inside_flags(flat_anchors, flat_valid_flags,\n                                           img_meta['img_shape'],\n                                           allowed_border)\n        outside_flags = ~inside_flags\n        flat_assigned_gt_inds[outside_flags] = -1\n\n        if gt_labels is not None:\n            assigned_labels = torch.zeros_like(flat_assigned_gt_inds)\n            pos_flags = assigned_gt_inds > 0\n            assigned_labels[pos_flags] = gt_labels[\n                flat_assigned_gt_inds[pos_flags] - 1]\n        else:\n            assigned_labels = None\n\n        return AssignResult(\n            num_gts, flat_assigned_gt_inds, None, labels=assigned_labels)\n", "path": "mmdet/core/bbox/assigners/region_assigner.py"}], "after_files": [{"content": "import torch\n\nfrom mmdet.core import anchor_inside_flags\nfrom ..builder import BBOX_ASSIGNERS\nfrom .assign_result import AssignResult\nfrom .base_assigner import BaseAssigner\n\n\ndef calc_region(bbox, ratio, stride, featmap_size=None):\n    \"\"\"Calculate region of the box defined by the ratio, the ratio is from the\n    center of the box to every edge.\"\"\"\n    # project bbox on the feature\n    f_bbox = bbox / stride\n    x1 = torch.round((1 - ratio) * f_bbox[0] + ratio * f_bbox[2])\n    y1 = torch.round((1 - ratio) * f_bbox[1] + ratio * f_bbox[3])\n    x2 = torch.round(ratio * f_bbox[0] + (1 - ratio) * f_bbox[2])\n    y2 = torch.round(ratio * f_bbox[1] + (1 - ratio) * f_bbox[3])\n    if featmap_size is not None:\n        x1 = x1.clamp(min=0, max=featmap_size[1])\n        y1 = y1.clamp(min=0, max=featmap_size[0])\n        x2 = x2.clamp(min=0, max=featmap_size[1])\n        y2 = y2.clamp(min=0, max=featmap_size[0])\n    return (x1, y1, x2, y2)\n\n\ndef anchor_ctr_inside_region_flags(anchors, stride, region):\n    \"\"\"Get the flag indicate whether anchor centers are inside regions.\"\"\"\n    x1, y1, x2, y2 = region\n    f_anchors = anchors / stride\n    x = (f_anchors[:, 0] + f_anchors[:, 2]) * 0.5\n    y = (f_anchors[:, 1] + f_anchors[:, 3]) * 0.5\n    flags = (x >= x1) & (x <= x2) & (y >= y1) & (y <= y2)\n    return flags\n\n\n@BBOX_ASSIGNERS.register_module()\nclass RegionAssigner(BaseAssigner):\n    \"\"\"Assign a corresponding gt bbox or background to each bbox.\n\n    Each proposals will be assigned with `-1`, `0`, or a positive integer\n    indicating the ground truth index.\n\n    - -1: don't care\n    - 0: negative sample, no assigned gt\n    - positive integer: positive sample, index (1-based) of assigned gt\n\n    Args:\n        center_ratio: ratio of the region in the center of the bbox to\n            define positive sample.\n        ignore_ratio: ratio of the region to define ignore samples.\n    \"\"\"\n\n    def __init__(self, center_ratio=0.2, ignore_ratio=0.5):\n        self.center_ratio = center_ratio\n        self.ignore_ratio = ignore_ratio\n\n    def assign(self,\n               mlvl_anchors,\n               mlvl_valid_flags,\n               gt_bboxes,\n               img_meta,\n               featmap_sizes,\n               anchor_scale,\n               anchor_strides,\n               gt_bboxes_ignore=None,\n               gt_labels=None,\n               allowed_border=0):\n        \"\"\"Assign gt to anchors.\n\n        This method assign a gt bbox to every bbox (proposal/anchor), each bbox\n        will be assigned with -1, 0, or a positive number. -1 means don't care,\n        0 means negative sample, positive number is the index (1-based) of\n        assigned gt.\n        The assignment is done in following steps, the order matters.\n\n        1. Assign every anchor to 0 (negative)\n        For each gt_bboxes:\n            2. Compute ignore flags based on ignore_region then\n                assign -1 to anchors w.r.t. ignore flags\n            3. Compute pos flags based on center_region then\n               assign gt_bboxes to anchors w.r.t. pos flags\n            4. Compute ignore flags based on adjacent anchor lvl then\n               assign -1 to anchors w.r.t. ignore flags\n            5. Assign anchor outside of image to -1\n\n        Args:\n            mlvl_anchors (list[Tensor]): Multi level anchors.\n            mlvl_valid_flags (list[Tensor]): Multi level valid flags.\n            gt_bboxes (Tensor): Ground truth bboxes of image\n            img_meta (dict): Meta info of image.\n            featmap_sizes (list[Tensor]): Feature mapsize each level\n            anchor_scale (int): Scale of the anchor.\n            anchor_strides (list[int]): Stride of the anchor.\n            gt_bboxes (Tensor): Groundtruth boxes, shape (k, 4).\n            gt_bboxes_ignore (Tensor, optional): Ground truth bboxes that are\n                labelled as `ignored`, e.g., crowd boxes in COCO.\n            gt_labels (Tensor, optional): Label of gt_bboxes, shape (k, ).\n            allowed_border (int, optional): The border to allow the valid\n                anchor. Defaults to 0.\n\n        Returns:\n            :obj:`AssignResult`: The assign result.\n        \"\"\"\n        if gt_bboxes_ignore is not None:\n            raise NotImplementedError\n\n        num_gts = gt_bboxes.shape[0]\n        num_bboxes = sum(x.shape[0] for x in mlvl_anchors)\n\n        if num_gts == 0 or num_bboxes == 0:\n            # No ground truth or boxes, return empty assignment\n            max_overlaps = gt_bboxes.new_zeros((num_bboxes, ))\n            assigned_gt_inds = gt_bboxes.new_zeros((num_bboxes, ),\n                                                   dtype=torch.long)\n            if gt_labels is None:\n                assigned_labels = None\n            else:\n                assigned_labels = gt_bboxes.new_full((num_bboxes, ),\n                                                     -1,\n                                                     dtype=torch.long)\n            return AssignResult(\n                num_gts,\n                assigned_gt_inds,\n                max_overlaps,\n                labels=assigned_labels)\n\n        num_lvls = len(mlvl_anchors)\n        r1 = (1 - self.center_ratio) / 2\n        r2 = (1 - self.ignore_ratio) / 2\n\n        scale = torch.sqrt((gt_bboxes[:, 2] - gt_bboxes[:, 0]) *\n                           (gt_bboxes[:, 3] - gt_bboxes[:, 1]))\n        min_anchor_size = scale.new_full(\n            (1, ), float(anchor_scale * anchor_strides[0]))\n        target_lvls = torch.floor(\n            torch.log2(scale) - torch.log2(min_anchor_size) + 0.5)\n        target_lvls = target_lvls.clamp(min=0, max=num_lvls - 1).long()\n\n        # 1. assign 0 (negative) by default\n        mlvl_assigned_gt_inds = []\n        mlvl_ignore_flags = []\n        for lvl in range(num_lvls):\n            h, w = featmap_sizes[lvl]\n            assert h * w == mlvl_anchors[lvl].shape[0]\n            assigned_gt_inds = gt_bboxes.new_full((h * w, ),\n                                                  0,\n                                                  dtype=torch.long)\n            ignore_flags = torch.zeros_like(assigned_gt_inds)\n            mlvl_assigned_gt_inds.append(assigned_gt_inds)\n            mlvl_ignore_flags.append(ignore_flags)\n\n        for gt_id in range(num_gts):\n            lvl = target_lvls[gt_id].item()\n            featmap_size = featmap_sizes[lvl]\n            stride = anchor_strides[lvl]\n            anchors = mlvl_anchors[lvl]\n            gt_bbox = gt_bboxes[gt_id, :4]\n\n            # Compute regions\n            ignore_region = calc_region(gt_bbox, r2, stride, featmap_size)\n            ctr_region = calc_region(gt_bbox, r1, stride, featmap_size)\n\n            # 2. Assign -1 to ignore flags\n            ignore_flags = anchor_ctr_inside_region_flags(\n                anchors, stride, ignore_region)\n            mlvl_assigned_gt_inds[lvl][ignore_flags] = -1\n\n            # 3. Assign gt_bboxes to pos flags\n            pos_flags = anchor_ctr_inside_region_flags(anchors, stride,\n                                                       ctr_region)\n            mlvl_assigned_gt_inds[lvl][pos_flags] = gt_id + 1\n\n            # 4. Assign -1 to ignore adjacent lvl\n            if lvl > 0:\n                d_lvl = lvl - 1\n                d_anchors = mlvl_anchors[d_lvl]\n                d_featmap_size = featmap_sizes[d_lvl]\n                d_stride = anchor_strides[d_lvl]\n                d_ignore_region = calc_region(gt_bbox, r2, d_stride,\n                                              d_featmap_size)\n                ignore_flags = anchor_ctr_inside_region_flags(\n                    d_anchors, d_stride, d_ignore_region)\n                mlvl_ignore_flags[d_lvl][ignore_flags] = 1\n            if lvl < num_lvls - 1:\n                u_lvl = lvl + 1\n                u_anchors = mlvl_anchors[u_lvl]\n                u_featmap_size = featmap_sizes[u_lvl]\n                u_stride = anchor_strides[u_lvl]\n                u_ignore_region = calc_region(gt_bbox, r2, u_stride,\n                                              u_featmap_size)\n                ignore_flags = anchor_ctr_inside_region_flags(\n                    u_anchors, u_stride, u_ignore_region)\n                mlvl_ignore_flags[u_lvl][ignore_flags] = 1\n\n        # 4. (cont.) Assign -1 to ignore adjacent lvl\n        for lvl in range(num_lvls):\n            ignore_flags = mlvl_ignore_flags[lvl]\n            mlvl_assigned_gt_inds[lvl][ignore_flags] = -1\n\n        # 5. Assign -1 to anchor outside of image\n        flat_assigned_gt_inds = torch.cat(mlvl_assigned_gt_inds)\n        flat_anchors = torch.cat(mlvl_anchors)\n        flat_valid_flags = torch.cat(mlvl_valid_flags)\n        assert (flat_assigned_gt_inds.shape[0] == flat_anchors.shape[0] ==\n                flat_valid_flags.shape[0])\n        inside_flags = anchor_inside_flags(flat_anchors, flat_valid_flags,\n                                           img_meta['img_shape'],\n                                           allowed_border)\n        outside_flags = ~inside_flags\n        flat_assigned_gt_inds[outside_flags] = -1\n\n        if gt_labels is not None:\n            assigned_labels = torch.zeros_like(flat_assigned_gt_inds)\n            pos_flags = assigned_gt_inds > 0\n            assigned_labels[pos_flags] = gt_labels[\n                flat_assigned_gt_inds[pos_flags] - 1]\n        else:\n            assigned_labels = None\n\n        return AssignResult(\n            num_gts, flat_assigned_gt_inds, None, labels=assigned_labels)\n", "path": "mmdet/core/bbox/assigners/region_assigner.py"}]}