We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
mabe a bug in version 2.1.0
I upgrade mmdetection from 2.0.0 to 2.1.0, but I can't train with this error:ValueError: need at least one array to concatenate.
So I use version 2.0.0 and all work well, so I think maybe there is a bug in version 2.1.0

--- 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/datasets/cityscapes.py`
Content:
```
1 # Modified from https://github.com/facebookresearch/detectron2/blob/master/detectron2/data/datasets/cityscapes.py # noqa
2 # and https://github.com/mcordts/cityscapesScripts/blob/master/cityscapesscripts/evaluation/evalInstanceLevelSemanticLabeling.py # noqa
3 
4 import glob
5 import os
6 import os.path as osp
7 import tempfile
8 
9 import mmcv
10 import numpy as np
11 import pycocotools.mask as maskUtils
12 from mmcv.utils import print_log
13 
14 from .builder import DATASETS
15 from .coco import CocoDataset
16 
17 
18 @DATASETS.register_module()
19 class CityscapesDataset(CocoDataset):
20 
21     CLASSES = ('person', 'rider', 'car', 'truck', 'bus', 'train', 'motorcycle',
22                'bicycle')
23 
24     def _filter_imgs(self, min_size=32):
25         """Filter images too small or without ground truths."""
26         valid_inds = []
27         ids_with_ann = set(_['image_id'] for _ in self.coco.anns.values())
28         for i, img_info in enumerate(self.data_infos):
29             img_id = img_info['id']
30             ann_ids = self.coco.getAnnIds(imgIds=[img_id])
31             ann_info = self.coco.loadAnns(ann_ids)
32             all_iscrowd = all([_['iscrowd'] for _ in ann_info])
33             if self.filter_empty_gt and (self.img_ids[i] not in ids_with_ann
34                                          or all_iscrowd):
35                 continue
36             if min(img_info['width'], img_info['height']) >= min_size:
37                 valid_inds.append(i)
38         return valid_inds
39 
40     def _parse_ann_info(self, img_info, ann_info):
41         """Parse bbox and mask annotation.
42 
43         Args:
44             img_info (dict): Image info of an image.
45             ann_info (list[dict]): Annotation info of an image.
46 
47         Returns:
48             dict: A dict containing the following keys: bboxes, bboxes_ignore,
49                 labels, masks, seg_map.
50                 "masks" are already decoded into binary masks.
51         """
52         gt_bboxes = []
53         gt_labels = []
54         gt_bboxes_ignore = []
55         gt_masks_ann = []
56 
57         for i, ann in enumerate(ann_info):
58             if ann.get('ignore', False):
59                 continue
60             x1, y1, w, h = ann['bbox']
61             if ann['area'] <= 0 or w < 1 or h < 1:
62                 continue
63             if ann['category_id'] not in self.cat_ids:
64                 continue
65             bbox = [x1, y1, x1 + w, y1 + h]
66             if ann.get('iscrowd', False):
67                 gt_bboxes_ignore.append(bbox)
68             else:
69                 gt_bboxes.append(bbox)
70                 gt_labels.append(self.cat2label[ann['category_id']])
71                 gt_masks_ann.append(ann['segmentation'])
72 
73         if gt_bboxes:
74             gt_bboxes = np.array(gt_bboxes, dtype=np.float32)
75             gt_labels = np.array(gt_labels, dtype=np.int64)
76         else:
77             gt_bboxes = np.zeros((0, 4), dtype=np.float32)
78             gt_labels = np.array([], dtype=np.int64)
79 
80         if gt_bboxes_ignore:
81             gt_bboxes_ignore = np.array(gt_bboxes_ignore, dtype=np.float32)
82         else:
83             gt_bboxes_ignore = np.zeros((0, 4), dtype=np.float32)
84 
85         ann = dict(
86             bboxes=gt_bboxes,
87             labels=gt_labels,
88             bboxes_ignore=gt_bboxes_ignore,
89             masks=gt_masks_ann,
90             seg_map=img_info['segm_file'])
91 
92         return ann
93 
94     def results2txt(self, results, outfile_prefix):
95         """Dump the detection results to a txt file.
96 
97         Args:
98             results (list[list | tuple | ndarray]): Testing results of the
99                 dataset.
100             outfile_prefix (str): The filename prefix of the json files.
101                 If the prefix is "somepath/xxx",
102                 the txt files will be named "somepath/xxx.txt".
103 
104         Returns:
105             list[str: str]: result txt files which contains corresponding
106             instance segmentation images.
107         """
108         try:
109             import cityscapesscripts.helpers.labels as CSLabels
110         except ImportError:
111             raise ImportError('Please run "pip install citscapesscripts" to '
112                               'install cityscapesscripts first.')
113         result_files = []
114         os.makedirs(outfile_prefix, exist_ok=True)
115         prog_bar = mmcv.ProgressBar(len(self))
116         for idx in range(len(self)):
117             result = results[idx]
118             filename = self.data_infos[idx]['filename']
119             basename = osp.splitext(osp.basename(filename))[0]
120             pred_txt = osp.join(outfile_prefix, basename + '_pred.txt')
121 
122             bbox_result, segm_result = result
123             bboxes = np.vstack(bbox_result)
124             segms = mmcv.concat_list(segm_result)
125             labels = [
126                 np.full(bbox.shape[0], i, dtype=np.int32)
127                 for i, bbox in enumerate(bbox_result)
128             ]
129             labels = np.concatenate(labels)
130 
131             assert len(bboxes) == len(segms) == len(labels)
132             num_instances = len(bboxes)
133             prog_bar.update()
134             with open(pred_txt, 'w') as fout:
135                 for i in range(num_instances):
136                     pred_class = labels[i]
137                     classes = self.CLASSES[pred_class]
138                     class_id = CSLabels.name2label[classes].id
139                     score = bboxes[i, -1]
140                     mask = maskUtils.decode(segms[i]).astype(np.uint8)
141                     png_filename = osp.join(outfile_prefix,
142                                             basename + f'_{i}_{classes}.png')
143                     mmcv.imwrite(mask, png_filename)
144                     fout.write(f'{osp.basename(png_filename)} {class_id} '
145                                f'{score}\n')
146             result_files.append(pred_txt)
147 
148         return result_files
149 
150     def format_results(self, results, txtfile_prefix=None):
151         """Format the results to txt (standard format for Cityscapes evaluation).
152 
153         Args:
154             results (list): Testing results of the dataset.
155             txtfile_prefix (str | None): The prefix of txt files. It includes
156                 the file path and the prefix of filename, e.g., "a/b/prefix".
157                 If not specified, a temp file will be created. Default: None.
158 
159         Returns:
160             tuple: (result_files, tmp_dir), result_files is a dict containing
161                 the json filepaths, tmp_dir is the temporal directory created
162                 for saving txt/png files when txtfile_prefix is not specified.
163         """
164         assert isinstance(results, list), 'results must be a list'
165         assert len(results) == len(self), (
166             'The length of results is not equal to the dataset len: {} != {}'.
167             format(len(results), len(self)))
168 
169         assert isinstance(results, list), 'results must be a list'
170         assert len(results) == len(self), (
171             'The length of results is not equal to the dataset len: {} != {}'.
172             format(len(results), len(self)))
173 
174         if txtfile_prefix is None:
175             tmp_dir = tempfile.TemporaryDirectory()
176             txtfile_prefix = osp.join(tmp_dir.name, 'results')
177         else:
178             tmp_dir = None
179         result_files = self.results2txt(results, txtfile_prefix)
180 
181         return result_files, tmp_dir
182 
183     def evaluate(self,
184                  results,
185                  metric='bbox',
186                  logger=None,
187                  outfile_prefix=None,
188                  classwise=False,
189                  proposal_nums=(100, 300, 1000),
190                  iou_thrs=np.arange(0.5, 0.96, 0.05)):
191         """Evaluation in Cityscapes protocol.
192 
193         Args:
194             results (list): Testing results of the dataset.
195             metric (str | list[str]): Metrics to be evaluated.
196             logger (logging.Logger | str | None): Logger used for printing
197                 related information during evaluation. Default: None.
198             outfile_prefix (str | None):
199             classwise (bool): Whether to evaluating the AP for each class.
200             proposal_nums (Sequence[int]): Proposal number used for evaluating
201                 recalls, such as recall@100, recall@1000.
202                 Default: (100, 300, 1000).
203             iou_thrs (Sequence[float]): IoU threshold used for evaluating
204                 recalls. If set to a list, the average recall of all IoUs will
205                 also be computed. Default: 0.5.
206 
207         Returns:
208             dict[str: float]
209         """
210         eval_results = dict()
211 
212         metrics = metric.copy() if isinstance(metric, list) else [metric]
213 
214         if 'cityscapes' in metrics:
215             eval_results.update(
216                 self._evaluate_cityscapes(results, outfile_prefix, logger))
217             metrics.remove('cityscapes')
218 
219         # left metrics are all coco metric
220         if len(metrics) > 0:
221             # create CocoDataset with CityscapesDataset annotation
222             self_coco = CocoDataset(self.ann_file, self.pipeline.transforms,
223                                     None, self.data_root, self.img_prefix,
224                                     self.seg_prefix, self.proposal_file,
225                                     self.test_mode, self.filter_empty_gt)
226             # TODO: remove this in the future
227             # reload annotations of correct class
228             self_coco.CLASSES = self.CLASSES
229             self_coco.data_infos = self_coco.load_annotations(self.ann_file)
230             eval_results.update(
231                 self_coco.evaluate(results, metrics, logger, outfile_prefix,
232                                    classwise, proposal_nums, iou_thrs))
233 
234         return eval_results
235 
236     def _evaluate_cityscapes(self, results, txtfile_prefix, logger):
237         try:
238             import cityscapesscripts.evaluation.evalInstanceLevelSemanticLabeling as CSEval  # noqa
239         except ImportError:
240             raise ImportError('Please run "pip install citscapesscripts" to '
241                               'install cityscapesscripts first.')
242         msg = 'Evaluating in Cityscapes style'
243         if logger is None:
244             msg = '\n' + msg
245         print_log(msg, logger=logger)
246 
247         result_files, tmp_dir = self.format_results(results, txtfile_prefix)
248 
249         if tmp_dir is None:
250             result_dir = osp.join(txtfile_prefix, 'results')
251         else:
252             result_dir = osp.join(tmp_dir.name, 'results')
253 
254         eval_results = {}
255         print_log(f'Evaluating results under {result_dir} ...', logger=logger)
256 
257         # set global states in cityscapes evaluation API
258         CSEval.args.cityscapesPath = os.path.join(self.img_prefix, '../..')
259         CSEval.args.predictionPath = os.path.abspath(result_dir)
260         CSEval.args.predictionWalk = None
261         CSEval.args.JSONOutput = False
262         CSEval.args.colorized = False
263         CSEval.args.gtInstancesFile = os.path.join(result_dir,
264                                                    'gtInstances.json')
265         CSEval.args.groundTruthSearch = os.path.join(
266             self.img_prefix.replace('leftImg8bit', 'gtFine'),
267             '*/*_gtFine_instanceIds.png')
268 
269         groundTruthImgList = glob.glob(CSEval.args.groundTruthSearch)
270         assert len(groundTruthImgList), 'Cannot find ground truth images' \
271             f' in {CSEval.args.groundTruthSearch}.'
272         predictionImgList = []
273         for gt in groundTruthImgList:
274             predictionImgList.append(CSEval.getPrediction(gt, CSEval.args))
275         CSEval_results = CSEval.evaluateImgLists(predictionImgList,
276                                                  groundTruthImgList,
277                                                  CSEval.args)['averages']
278 
279         eval_results['mAP'] = CSEval_results['allAp']
280         eval_results['AP@50'] = CSEval_results['allAp50%']
281         if tmp_dir is not None:
282             tmp_dir.cleanup()
283         return eval_results
284
```
--- 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/datasets/cityscapes.py b/mmdet/datasets/cityscapes.py
--- a/mmdet/datasets/cityscapes.py
+++ b/mmdet/datasets/cityscapes.py
@@ -121,7 +121,17 @@
 
             bbox_result, segm_result = result
             bboxes = np.vstack(bbox_result)
-            segms = mmcv.concat_list(segm_result)
+            # segm results
+            if isinstance(segm_result, tuple):
+                # Some detectors use different scores for bbox and mask,
+                # like Mask Scoring R-CNN. Score of segm will be used instead
+                # of bbox score.
+                segms = mmcv.concat_list(segm_result[0])
+                mask_score = segm_result[1]
+            else:
+                # use bbox score for mask score
+                segms = mmcv.concat_list(segm_result)
+                mask_score = [bbox[-1] for bbox in bboxes]
             labels = [
                 np.full(bbox.shape[0], i, dtype=np.int32)
                 for i, bbox in enumerate(bbox_result)
@@ -136,7 +146,7 @@
                     pred_class = labels[i]
                     classes = self.CLASSES[pred_class]
                     class_id = CSLabels.name2label[classes].id
-                    score = bboxes[i, -1]
+                    score = mask_score[i]
                     mask = maskUtils.decode(segms[i]).astype(np.uint8)
                     png_filename = osp.join(outfile_prefix,
                                             basename + f'_{i}_{classes}.png')

{"golden_diff": "diff --git a/mmdet/datasets/cityscapes.py b/mmdet/datasets/cityscapes.py\n--- a/mmdet/datasets/cityscapes.py\n+++ b/mmdet/datasets/cityscapes.py\n@@ -121,7 +121,17 @@\n \n             bbox_result, segm_result = result\n             bboxes = np.vstack(bbox_result)\n-            segms = mmcv.concat_list(segm_result)\n+            # segm results\n+            if isinstance(segm_result, tuple):\n+                # Some detectors use different scores for bbox and mask,\n+                # like Mask Scoring R-CNN. Score of segm will be used instead\n+                # of bbox score.\n+                segms = mmcv.concat_list(segm_result[0])\n+                mask_score = segm_result[1]\n+            else:\n+                # use bbox score for mask score\n+                segms = mmcv.concat_list(segm_result)\n+                mask_score = [bbox[-1] for bbox in bboxes]\n             labels = [\n                 np.full(bbox.shape[0], i, dtype=np.int32)\n                 for i, bbox in enumerate(bbox_result)\n@@ -136,7 +146,7 @@\n                     pred_class = labels[i]\n                     classes = self.CLASSES[pred_class]\n                     class_id = CSLabels.name2label[classes].id\n-                    score = bboxes[i, -1]\n+                    score = mask_score[i]\n                     mask = maskUtils.decode(segms[i]).astype(np.uint8)\n                     png_filename = osp.join(outfile_prefix,\n                                             basename + f'_{i}_{classes}.png')\n", "issue": "mabe a bug in version 2.1.0\nI upgrade mmdetection from 2.0.0 to 2.1.0, but I can't train with this error:ValueError: need at least one array to concatenate.\r\nSo I use version 2.0.0 and all work well, so I think maybe there is a bug in version 2.1.0\n", "before_files": [{"content": "# Modified from https://github.com/facebookresearch/detectron2/blob/master/detectron2/data/datasets/cityscapes.py # noqa\n# and https://github.com/mcordts/cityscapesScripts/blob/master/cityscapesscripts/evaluation/evalInstanceLevelSemanticLabeling.py # noqa\n\nimport glob\nimport os\nimport os.path as osp\nimport tempfile\n\nimport mmcv\nimport numpy as np\nimport pycocotools.mask as maskUtils\nfrom mmcv.utils import print_log\n\nfrom .builder import DATASETS\nfrom .coco import CocoDataset\n\n\n@DATASETS.register_module()\nclass CityscapesDataset(CocoDataset):\n\n    CLASSES = ('person', 'rider', 'car', 'truck', 'bus', 'train', 'motorcycle',\n               'bicycle')\n\n    def _filter_imgs(self, min_size=32):\n        \"\"\"Filter images too small or without ground truths.\"\"\"\n        valid_inds = []\n        ids_with_ann = set(_['image_id'] for _ in self.coco.anns.values())\n        for i, img_info in enumerate(self.data_infos):\n            img_id = img_info['id']\n            ann_ids = self.coco.getAnnIds(imgIds=[img_id])\n            ann_info = self.coco.loadAnns(ann_ids)\n            all_iscrowd = all([_['iscrowd'] for _ in ann_info])\n            if self.filter_empty_gt and (self.img_ids[i] not in ids_with_ann\n                                         or all_iscrowd):\n                continue\n            if min(img_info['width'], img_info['height']) >= min_size:\n                valid_inds.append(i)\n        return valid_inds\n\n    def _parse_ann_info(self, img_info, ann_info):\n        \"\"\"Parse bbox and mask annotation.\n\n        Args:\n            img_info (dict): Image info of an image.\n            ann_info (list[dict]): Annotation info of an image.\n\n        Returns:\n            dict: A dict containing the following keys: bboxes, bboxes_ignore,\n                labels, masks, seg_map.\n                \"masks\" are already decoded into binary masks.\n        \"\"\"\n        gt_bboxes = []\n        gt_labels = []\n        gt_bboxes_ignore = []\n        gt_masks_ann = []\n\n        for i, ann in enumerate(ann_info):\n            if ann.get('ignore', False):\n                continue\n            x1, y1, w, h = ann['bbox']\n            if ann['area'] <= 0 or w < 1 or h < 1:\n                continue\n            if ann['category_id'] not in self.cat_ids:\n                continue\n            bbox = [x1, y1, x1 + w, y1 + h]\n            if ann.get('iscrowd', False):\n                gt_bboxes_ignore.append(bbox)\n            else:\n                gt_bboxes.append(bbox)\n                gt_labels.append(self.cat2label[ann['category_id']])\n                gt_masks_ann.append(ann['segmentation'])\n\n        if gt_bboxes:\n            gt_bboxes = np.array(gt_bboxes, dtype=np.float32)\n            gt_labels = np.array(gt_labels, dtype=np.int64)\n        else:\n            gt_bboxes = np.zeros((0, 4), dtype=np.float32)\n            gt_labels = np.array([], dtype=np.int64)\n\n        if gt_bboxes_ignore:\n            gt_bboxes_ignore = np.array(gt_bboxes_ignore, dtype=np.float32)\n        else:\n            gt_bboxes_ignore = np.zeros((0, 4), dtype=np.float32)\n\n        ann = dict(\n            bboxes=gt_bboxes,\n            labels=gt_labels,\n            bboxes_ignore=gt_bboxes_ignore,\n            masks=gt_masks_ann,\n            seg_map=img_info['segm_file'])\n\n        return ann\n\n    def results2txt(self, results, outfile_prefix):\n        \"\"\"Dump the detection results to a txt file.\n\n        Args:\n            results (list[list | tuple | ndarray]): Testing results of the\n                dataset.\n            outfile_prefix (str): The filename prefix of the json files.\n                If the prefix is \"somepath/xxx\",\n                the txt files will be named \"somepath/xxx.txt\".\n\n        Returns:\n            list[str: str]: result txt files which contains corresponding\n            instance segmentation images.\n        \"\"\"\n        try:\n            import cityscapesscripts.helpers.labels as CSLabels\n        except ImportError:\n            raise ImportError('Please run \"pip install citscapesscripts\" to '\n                              'install cityscapesscripts first.')\n        result_files = []\n        os.makedirs(outfile_prefix, exist_ok=True)\n        prog_bar = mmcv.ProgressBar(len(self))\n        for idx in range(len(self)):\n            result = results[idx]\n            filename = self.data_infos[idx]['filename']\n            basename = osp.splitext(osp.basename(filename))[0]\n            pred_txt = osp.join(outfile_prefix, basename + '_pred.txt')\n\n            bbox_result, segm_result = result\n            bboxes = np.vstack(bbox_result)\n            segms = mmcv.concat_list(segm_result)\n            labels = [\n                np.full(bbox.shape[0], i, dtype=np.int32)\n                for i, bbox in enumerate(bbox_result)\n            ]\n            labels = np.concatenate(labels)\n\n            assert len(bboxes) == len(segms) == len(labels)\n            num_instances = len(bboxes)\n            prog_bar.update()\n            with open(pred_txt, 'w') as fout:\n                for i in range(num_instances):\n                    pred_class = labels[i]\n                    classes = self.CLASSES[pred_class]\n                    class_id = CSLabels.name2label[classes].id\n                    score = bboxes[i, -1]\n                    mask = maskUtils.decode(segms[i]).astype(np.uint8)\n                    png_filename = osp.join(outfile_prefix,\n                                            basename + f'_{i}_{classes}.png')\n                    mmcv.imwrite(mask, png_filename)\n                    fout.write(f'{osp.basename(png_filename)} {class_id} '\n                               f'{score}\\n')\n            result_files.append(pred_txt)\n\n        return result_files\n\n    def format_results(self, results, txtfile_prefix=None):\n        \"\"\"Format the results to txt (standard format for Cityscapes evaluation).\n\n        Args:\n            results (list): Testing results of the dataset.\n            txtfile_prefix (str | None): The prefix of txt files. It includes\n                the file path and the prefix of filename, e.g., \"a/b/prefix\".\n                If not specified, a temp file will be created. Default: None.\n\n        Returns:\n            tuple: (result_files, tmp_dir), result_files is a dict containing\n                the json filepaths, tmp_dir is the temporal directory created\n                for saving txt/png files when txtfile_prefix is not specified.\n        \"\"\"\n        assert isinstance(results, list), 'results must be a list'\n        assert len(results) == len(self), (\n            'The length of results is not equal to the dataset len: {} != {}'.\n            format(len(results), len(self)))\n\n        assert isinstance(results, list), 'results must be a list'\n        assert len(results) == len(self), (\n            'The length of results is not equal to the dataset len: {} != {}'.\n            format(len(results), len(self)))\n\n        if txtfile_prefix is None:\n            tmp_dir = tempfile.TemporaryDirectory()\n            txtfile_prefix = osp.join(tmp_dir.name, 'results')\n        else:\n            tmp_dir = None\n        result_files = self.results2txt(results, txtfile_prefix)\n\n        return result_files, tmp_dir\n\n    def evaluate(self,\n                 results,\n                 metric='bbox',\n                 logger=None,\n                 outfile_prefix=None,\n                 classwise=False,\n                 proposal_nums=(100, 300, 1000),\n                 iou_thrs=np.arange(0.5, 0.96, 0.05)):\n        \"\"\"Evaluation in Cityscapes protocol.\n\n        Args:\n            results (list): Testing results of the dataset.\n            metric (str | list[str]): Metrics to be evaluated.\n            logger (logging.Logger | str | None): Logger used for printing\n                related information during evaluation. Default: None.\n            outfile_prefix (str | None):\n            classwise (bool): Whether to evaluating the AP for each class.\n            proposal_nums (Sequence[int]): Proposal number used for evaluating\n                recalls, such as recall@100, recall@1000.\n                Default: (100, 300, 1000).\n            iou_thrs (Sequence[float]): IoU threshold used for evaluating\n                recalls. If set to a list, the average recall of all IoUs will\n                also be computed. Default: 0.5.\n\n        Returns:\n            dict[str: float]\n        \"\"\"\n        eval_results = dict()\n\n        metrics = metric.copy() if isinstance(metric, list) else [metric]\n\n        if 'cityscapes' in metrics:\n            eval_results.update(\n                self._evaluate_cityscapes(results, outfile_prefix, logger))\n            metrics.remove('cityscapes')\n\n        # left metrics are all coco metric\n        if len(metrics) > 0:\n            # create CocoDataset with CityscapesDataset annotation\n            self_coco = CocoDataset(self.ann_file, self.pipeline.transforms,\n                                    None, self.data_root, self.img_prefix,\n                                    self.seg_prefix, self.proposal_file,\n                                    self.test_mode, self.filter_empty_gt)\n            # TODO: remove this in the future\n            # reload annotations of correct class\n            self_coco.CLASSES = self.CLASSES\n            self_coco.data_infos = self_coco.load_annotations(self.ann_file)\n            eval_results.update(\n                self_coco.evaluate(results, metrics, logger, outfile_prefix,\n                                   classwise, proposal_nums, iou_thrs))\n\n        return eval_results\n\n    def _evaluate_cityscapes(self, results, txtfile_prefix, logger):\n        try:\n            import cityscapesscripts.evaluation.evalInstanceLevelSemanticLabeling as CSEval  # noqa\n        except ImportError:\n            raise ImportError('Please run \"pip install citscapesscripts\" to '\n                              'install cityscapesscripts first.')\n        msg = 'Evaluating in Cityscapes style'\n        if logger is None:\n            msg = '\\n' + msg\n        print_log(msg, logger=logger)\n\n        result_files, tmp_dir = self.format_results(results, txtfile_prefix)\n\n        if tmp_dir is None:\n            result_dir = osp.join(txtfile_prefix, 'results')\n        else:\n            result_dir = osp.join(tmp_dir.name, 'results')\n\n        eval_results = {}\n        print_log(f'Evaluating results under {result_dir} ...', logger=logger)\n\n        # set global states in cityscapes evaluation API\n        CSEval.args.cityscapesPath = os.path.join(self.img_prefix, '../..')\n        CSEval.args.predictionPath = os.path.abspath(result_dir)\n        CSEval.args.predictionWalk = None\n        CSEval.args.JSONOutput = False\n        CSEval.args.colorized = False\n        CSEval.args.gtInstancesFile = os.path.join(result_dir,\n                                                   'gtInstances.json')\n        CSEval.args.groundTruthSearch = os.path.join(\n            self.img_prefix.replace('leftImg8bit', 'gtFine'),\n            '*/*_gtFine_instanceIds.png')\n\n        groundTruthImgList = glob.glob(CSEval.args.groundTruthSearch)\n        assert len(groundTruthImgList), 'Cannot find ground truth images' \\\n            f' in {CSEval.args.groundTruthSearch}.'\n        predictionImgList = []\n        for gt in groundTruthImgList:\n            predictionImgList.append(CSEval.getPrediction(gt, CSEval.args))\n        CSEval_results = CSEval.evaluateImgLists(predictionImgList,\n                                                 groundTruthImgList,\n                                                 CSEval.args)['averages']\n\n        eval_results['mAP'] = CSEval_results['allAp']\n        eval_results['AP@50'] = CSEval_results['allAp50%']\n        if tmp_dir is not None:\n            tmp_dir.cleanup()\n        return eval_results\n", "path": "mmdet/datasets/cityscapes.py"}], "after_files": [{"content": "# Modified from https://github.com/facebookresearch/detectron2/blob/master/detectron2/data/datasets/cityscapes.py # noqa\n# and https://github.com/mcordts/cityscapesScripts/blob/master/cityscapesscripts/evaluation/evalInstanceLevelSemanticLabeling.py # noqa\n\nimport glob\nimport os\nimport os.path as osp\nimport tempfile\n\nimport mmcv\nimport numpy as np\nimport pycocotools.mask as maskUtils\nfrom mmcv.utils import print_log\n\nfrom .builder import DATASETS\nfrom .coco import CocoDataset\n\n\n@DATASETS.register_module()\nclass CityscapesDataset(CocoDataset):\n\n    CLASSES = ('person', 'rider', 'car', 'truck', 'bus', 'train', 'motorcycle',\n               'bicycle')\n\n    def _filter_imgs(self, min_size=32):\n        \"\"\"Filter images too small or without ground truths.\"\"\"\n        valid_inds = []\n        ids_with_ann = set(_['image_id'] for _ in self.coco.anns.values())\n        for i, img_info in enumerate(self.data_infos):\n            img_id = img_info['id']\n            ann_ids = self.coco.getAnnIds(imgIds=[img_id])\n            ann_info = self.coco.loadAnns(ann_ids)\n            all_iscrowd = all([_['iscrowd'] for _ in ann_info])\n            if self.filter_empty_gt and (self.img_ids[i] not in ids_with_ann\n                                         or all_iscrowd):\n                continue\n            if min(img_info['width'], img_info['height']) >= min_size:\n                valid_inds.append(i)\n        return valid_inds\n\n    def _parse_ann_info(self, img_info, ann_info):\n        \"\"\"Parse bbox and mask annotation.\n\n        Args:\n            img_info (dict): Image info of an image.\n            ann_info (list[dict]): Annotation info of an image.\n\n        Returns:\n            dict: A dict containing the following keys: bboxes, bboxes_ignore,\n                labels, masks, seg_map.\n                \"masks\" are already decoded into binary masks.\n        \"\"\"\n        gt_bboxes = []\n        gt_labels = []\n        gt_bboxes_ignore = []\n        gt_masks_ann = []\n\n        for i, ann in enumerate(ann_info):\n            if ann.get('ignore', False):\n                continue\n            x1, y1, w, h = ann['bbox']\n            if ann['area'] <= 0 or w < 1 or h < 1:\n                continue\n            if ann['category_id'] not in self.cat_ids:\n                continue\n            bbox = [x1, y1, x1 + w, y1 + h]\n            if ann.get('iscrowd', False):\n                gt_bboxes_ignore.append(bbox)\n            else:\n                gt_bboxes.append(bbox)\n                gt_labels.append(self.cat2label[ann['category_id']])\n                gt_masks_ann.append(ann['segmentation'])\n\n        if gt_bboxes:\n            gt_bboxes = np.array(gt_bboxes, dtype=np.float32)\n            gt_labels = np.array(gt_labels, dtype=np.int64)\n        else:\n            gt_bboxes = np.zeros((0, 4), dtype=np.float32)\n            gt_labels = np.array([], dtype=np.int64)\n\n        if gt_bboxes_ignore:\n            gt_bboxes_ignore = np.array(gt_bboxes_ignore, dtype=np.float32)\n        else:\n            gt_bboxes_ignore = np.zeros((0, 4), dtype=np.float32)\n\n        ann = dict(\n            bboxes=gt_bboxes,\n            labels=gt_labels,\n            bboxes_ignore=gt_bboxes_ignore,\n            masks=gt_masks_ann,\n            seg_map=img_info['segm_file'])\n\n        return ann\n\n    def results2txt(self, results, outfile_prefix):\n        \"\"\"Dump the detection results to a txt file.\n\n        Args:\n            results (list[list | tuple | ndarray]): Testing results of the\n                dataset.\n            outfile_prefix (str): The filename prefix of the json files.\n                If the prefix is \"somepath/xxx\",\n                the txt files will be named \"somepath/xxx.txt\".\n\n        Returns:\n            list[str: str]: result txt files which contains corresponding\n            instance segmentation images.\n        \"\"\"\n        try:\n            import cityscapesscripts.helpers.labels as CSLabels\n        except ImportError:\n            raise ImportError('Please run \"pip install citscapesscripts\" to '\n                              'install cityscapesscripts first.')\n        result_files = []\n        os.makedirs(outfile_prefix, exist_ok=True)\n        prog_bar = mmcv.ProgressBar(len(self))\n        for idx in range(len(self)):\n            result = results[idx]\n            filename = self.data_infos[idx]['filename']\n            basename = osp.splitext(osp.basename(filename))[0]\n            pred_txt = osp.join(outfile_prefix, basename + '_pred.txt')\n\n            bbox_result, segm_result = result\n            bboxes = np.vstack(bbox_result)\n            # segm results\n            if isinstance(segm_result, tuple):\n                # Some detectors use different scores for bbox and mask,\n                # like Mask Scoring R-CNN. Score of segm will be used instead\n                # of bbox score.\n                segms = mmcv.concat_list(segm_result[0])\n                mask_score = segm_result[1]\n            else:\n                # use bbox score for mask score\n                segms = mmcv.concat_list(segm_result)\n                mask_score = [bbox[-1] for bbox in bboxes]\n            labels = [\n                np.full(bbox.shape[0], i, dtype=np.int32)\n                for i, bbox in enumerate(bbox_result)\n            ]\n            labels = np.concatenate(labels)\n\n            assert len(bboxes) == len(segms) == len(labels)\n            num_instances = len(bboxes)\n            prog_bar.update()\n            with open(pred_txt, 'w') as fout:\n                for i in range(num_instances):\n                    pred_class = labels[i]\n                    classes = self.CLASSES[pred_class]\n                    class_id = CSLabels.name2label[classes].id\n                    score = mask_score[i]\n                    mask = maskUtils.decode(segms[i]).astype(np.uint8)\n                    png_filename = osp.join(outfile_prefix,\n                                            basename + f'_{i}_{classes}.png')\n                    mmcv.imwrite(mask, png_filename)\n                    fout.write(f'{osp.basename(png_filename)} {class_id} '\n                               f'{score}\\n')\n            result_files.append(pred_txt)\n\n        return result_files\n\n    def format_results(self, results, txtfile_prefix=None):\n        \"\"\"Format the results to txt (standard format for Cityscapes evaluation).\n\n        Args:\n            results (list): Testing results of the dataset.\n            txtfile_prefix (str | None): The prefix of txt files. It includes\n                the file path and the prefix of filename, e.g., \"a/b/prefix\".\n                If not specified, a temp file will be created. Default: None.\n\n        Returns:\n            tuple: (result_files, tmp_dir), result_files is a dict containing\n                the json filepaths, tmp_dir is the temporal directory created\n                for saving txt/png files when txtfile_prefix is not specified.\n        \"\"\"\n        assert isinstance(results, list), 'results must be a list'\n        assert len(results) == len(self), (\n            'The length of results is not equal to the dataset len: {} != {}'.\n            format(len(results), len(self)))\n\n        assert isinstance(results, list), 'results must be a list'\n        assert len(results) == len(self), (\n            'The length of results is not equal to the dataset len: {} != {}'.\n            format(len(results), len(self)))\n\n        if txtfile_prefix is None:\n            tmp_dir = tempfile.TemporaryDirectory()\n            txtfile_prefix = osp.join(tmp_dir.name, 'results')\n        else:\n            tmp_dir = None\n        result_files = self.results2txt(results, txtfile_prefix)\n\n        return result_files, tmp_dir\n\n    def evaluate(self,\n                 results,\n                 metric='bbox',\n                 logger=None,\n                 outfile_prefix=None,\n                 classwise=False,\n                 proposal_nums=(100, 300, 1000),\n                 iou_thrs=np.arange(0.5, 0.96, 0.05)):\n        \"\"\"Evaluation in Cityscapes protocol.\n\n        Args:\n            results (list): Testing results of the dataset.\n            metric (str | list[str]): Metrics to be evaluated.\n            logger (logging.Logger | str | None): Logger used for printing\n                related information during evaluation. Default: None.\n            outfile_prefix (str | None):\n            classwise (bool): Whether to evaluating the AP for each class.\n            proposal_nums (Sequence[int]): Proposal number used for evaluating\n                recalls, such as recall@100, recall@1000.\n                Default: (100, 300, 1000).\n            iou_thrs (Sequence[float]): IoU threshold used for evaluating\n                recalls. If set to a list, the average recall of all IoUs will\n                also be computed. Default: 0.5.\n\n        Returns:\n            dict[str: float]\n        \"\"\"\n        eval_results = dict()\n\n        metrics = metric.copy() if isinstance(metric, list) else [metric]\n\n        if 'cityscapes' in metrics:\n            eval_results.update(\n                self._evaluate_cityscapes(results, outfile_prefix, logger))\n            metrics.remove('cityscapes')\n\n        # left metrics are all coco metric\n        if len(metrics) > 0:\n            # create CocoDataset with CityscapesDataset annotation\n            self_coco = CocoDataset(self.ann_file, self.pipeline.transforms,\n                                    None, self.data_root, self.img_prefix,\n                                    self.seg_prefix, self.proposal_file,\n                                    self.test_mode, self.filter_empty_gt)\n            # TODO: remove this in the future\n            # reload annotations of correct class\n            self_coco.CLASSES = self.CLASSES\n            self_coco.data_infos = self_coco.load_annotations(self.ann_file)\n            eval_results.update(\n                self_coco.evaluate(results, metrics, logger, outfile_prefix,\n                                   classwise, proposal_nums, iou_thrs))\n\n        return eval_results\n\n    def _evaluate_cityscapes(self, results, txtfile_prefix, logger):\n        try:\n            import cityscapesscripts.evaluation.evalInstanceLevelSemanticLabeling as CSEval  # noqa\n        except ImportError:\n            raise ImportError('Please run \"pip install citscapesscripts\" to '\n                              'install cityscapesscripts first.')\n        msg = 'Evaluating in Cityscapes style'\n        if logger is None:\n            msg = '\\n' + msg\n        print_log(msg, logger=logger)\n\n        result_files, tmp_dir = self.format_results(results, txtfile_prefix)\n\n        if tmp_dir is None:\n            result_dir = osp.join(txtfile_prefix, 'results')\n        else:\n            result_dir = osp.join(tmp_dir.name, 'results')\n\n        eval_results = {}\n        print_log(f'Evaluating results under {result_dir} ...', logger=logger)\n\n        # set global states in cityscapes evaluation API\n        CSEval.args.cityscapesPath = os.path.join(self.img_prefix, '../..')\n        CSEval.args.predictionPath = os.path.abspath(result_dir)\n        CSEval.args.predictionWalk = None\n        CSEval.args.JSONOutput = False\n        CSEval.args.colorized = False\n        CSEval.args.gtInstancesFile = os.path.join(result_dir,\n                                                   'gtInstances.json')\n        CSEval.args.groundTruthSearch = os.path.join(\n            self.img_prefix.replace('leftImg8bit', 'gtFine'),\n            '*/*_gtFine_instanceIds.png')\n\n        groundTruthImgList = glob.glob(CSEval.args.groundTruthSearch)\n        assert len(groundTruthImgList), 'Cannot find ground truth images' \\\n            f' in {CSEval.args.groundTruthSearch}.'\n        predictionImgList = []\n        for gt in groundTruthImgList:\n            predictionImgList.append(CSEval.getPrediction(gt, CSEval.args))\n        CSEval_results = CSEval.evaluateImgLists(predictionImgList,\n                                                 groundTruthImgList,\n                                                 CSEval.args)['averages']\n\n        eval_results['mAP'] = CSEval_results['allAp']\n        eval_results['AP@50'] = CSEval_results['allAp50%']\n        if tmp_dir is not None:\n            tmp_dir.cleanup()\n        return eval_results\n", "path": "mmdet/datasets/cityscapes.py"}]}