Repository: open-mmlab/mmdetection

Issue:
Error while using 'poly2mask'=False
**Describe the bug**
I'm currently working on Cascade Mask R-CNN with base config https://github.com/open-mmlab/mmdetection/blob/master/configs/hrnet/cascade_mask_rcnn_hrnetv2p_w32_20e_coco.py

I have modified the training pipeline as below:
```
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='LoadAnnotations',
        with_bbox=True,
        with_mask=True,
        poly2mask=False),
    dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
    dict(type='RandomFlip', flip_ratio=0.5),
    dict(
        type='Normalize',
        mean=[123.675, 116.28, 103.53],
        std=[58.395, 57.12, 57.375],
        to_rgb=True),
    dict(type='Pad', size_divisor=32),
    dict(type='DefaultFormatBundle'),
    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels', 'gt_masks'])
]
```
Here, the important thing is that I've set 'poly2mask'=False while loading annotations
I'm training the model on ICDAR2019 table dataset with annotations in COCO format

I'm getting the following error:


```
UFuncTypeError                            Traceback (most recent call last)
<ipython-input-8-fb21f0b95ec4> in <module>()
     10 # Create work_dir
     11 #mmcv.mkdir_or_exist(os.path.abspath(cfg.work_dir))
---> 12 train_detector(model, datasets, cfg, distributed=False, validate=True)

13 frames
/content/mmdetection/mmdet/apis/train.py in train_detector(model, dataset, cfg, distributed, validate, timestamp, meta)
    168     elif cfg.load_from:
    169         runner.load_checkpoint(cfg.load_from)
--> 170     runner.run(data_loaders, cfg.workflow)

/usr/local/lib/python3.7/dist-packages/mmcv/runner/epoch_based_runner.py in run(self, data_loaders, workflow, max_epochs, **kwargs)
    123                     if mode == 'train' and self.epoch >= self._max_epochs:
    124                         break
--> 125                     epoch_runner(data_loaders[i], **kwargs)
    126 
    127         time.sleep(1)  # wait for some hooks like loggers to finish

/usr/local/lib/python3.7/dist-packages/mmcv/runner/epoch_based_runner.py in train(self, data_loader, **kwargs)
     45         self.call_hook('before_train_epoch')
     46         time.sleep(2)  # Prevent possible deadlock during epoch transition
---> 47         for i, data_batch in enumerate(self.data_loader):
     48             self._inner_iter = i
     49             self.call_hook('before_train_iter')

/usr/local/lib/python3.7/dist-packages/torch/utils/data/dataloader.py in __next__(self)
    515             if self._sampler_iter is None:
    516                 self._reset()
--> 517             data = self._next_data()
    518             self._num_yielded += 1
    519             if self._dataset_kind == _DatasetKind.Iterable and \

/usr/local/lib/python3.7/dist-packages/torch/utils/data/dataloader.py in _next_data(self)
    555     def _next_data(self):
    556         index = self._next_index()  # may raise StopIteration
--> 557         data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
    558         if self._pin_memory:
    559             data = _utils.pin_memory.pin_memory(data)

/usr/local/lib/python3.7/dist-packages/torch/utils/data/_utils/fetch.py in fetch(self, possibly_batched_index)
     42     def fetch(self, possibly_batched_index):
     43         if self.auto_collation:
---> 44             data = [self.dataset[idx] for idx in possibly_batched_index]
     45         else:
     46             data = self.dataset[possibly_batched_index]

/usr/local/lib/python3.7/dist-packages/torch/utils/data/_utils/fetch.py in <listcomp>(.0)
     42     def fetch(self, possibly_batched_index):
     43         if self.auto_collation:
---> 44             data = [self.dataset[idx] for idx in possibly_batched_index]
     45         else:
     46             data = self.dataset[possibly_batched_index]

/content/mmdetection/mmdet/datasets/custom.py in __getitem__(self, idx)
    192             return self.prepare_test_img(idx)
    193         while True:
--> 194             data = self.prepare_train_img(idx)
    195             if data is None:
    196                 idx = self._rand_another(idx)

/content/mmdetection/mmdet/datasets/custom.py in prepare_train_img(self, idx)
    215             results['proposals'] = self.proposals[idx]
    216         self.pre_pipeline(results)
--> 217         return self.pipeline(results)
    218 
    219     def prepare_test_img(self, idx):

/content/mmdetection/mmdet/datasets/pipelines/compose.py in __call__(self, data)
     38 
     39         for t in self.transforms:
---> 40             data = t(data)
     41             if data is None:
     42                 return None

/content/mmdetection/mmdet/datasets/pipelines/transforms.py in __call__(self, results)
    302         self._resize_img(results)
    303         self._resize_bboxes(results)
--> 304         self._resize_masks(results)
    305         self._resize_seg(results)
    306         return results

/content/mmdetection/mmdet/datasets/pipelines/transforms.py in _resize_masks(self, results)
    248                 continue
    249             if self.keep_ratio:
--> 250                 results[key] = results[key].rescale(results['scale'])
    251             else:
    252                 results[key] = results[key].resize(results['img_shape'][:2])

/content/mmdetection/mmdet/core/mask/structures.py in rescale(self, scale, interpolation)
    615             rescaled_masks = PolygonMasks([], new_h, new_w)
    616         else:
--> 617             rescaled_masks = self.resize((new_h, new_w))
    618         return rescaled_masks
    619 

/content/mmdetection/mmdet/core/mask/structures.py in resize(self, out_shape, interpolation)
    630                 for p in poly_per_obj:
    631                     p = p.copy()
--> 632                     p[0::2] *= w_scale
    633                     p[1::2] *= h_scale
    634                     resized_poly.append(p)

UFuncTypeError: Cannot cast ufunc 'multiply' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
```
This bug can be fixed with a simple change in the code in mmdet/core/mask/structures.py
I've attached the modified structures.py file here
[structures.txt](https://github.com/open-mmlab/mmdetection/files/6414891/structures.txt)




Discussion:
@darshan2412 Thank you for your feedback. Can you create a PR？
I've created the necessary pull request here https://github.com/open-mmlab/mmdetection/pull/5130/commits/ebcb1bb473860a2f2aff68f7ec11622f014fd8f4

Resolving patch:
diff --git a/mmdet/core/mask/structures.py b/mmdet/core/mask/structures.py
--- a/mmdet/core/mask/structures.py
+++ b/mmdet/core/mask/structures.py
@@ -637,8 +637,8 @@ def resize(self, out_shape, interpolation=None):
                 resized_poly = []
                 for p in poly_per_obj:
                     p = p.copy()
-                    p[0::2] *= w_scale
-                    p[1::2] *= h_scale
+                    p[0::2] = p[0::2] * w_scale
+                    p[1::2] = p[1::2] * h_scale
                     resized_poly.append(p)
                 resized_masks.append(resized_poly)
             resized_masks = PolygonMasks(resized_masks, *out_shape)
@@ -690,8 +690,8 @@ def crop(self, bbox):
                 for p in poly_per_obj:
                     # pycocotools will clip the boundary
                     p = p.copy()
-                    p[0::2] -= bbox[0]
-                    p[1::2] -= bbox[1]
+                    p[0::2] = p[0::2] - bbox[0]
+                    p[1::2] = p[1::2] - bbox[1]
                     cropped_poly_per_obj.append(p)
                 cropped_masks.append(cropped_poly_per_obj)
             cropped_masks = PolygonMasks(cropped_masks, h, w)
@@ -736,12 +736,12 @@ def crop_and_resize(self,
                 p = p.copy()
                 # crop
                 # pycocotools will clip the boundary
-                p[0::2] -= bbox[0]
-                p[1::2] -= bbox[1]
+                p[0::2] = p[0::2] - bbox[0]
+                p[1::2] = p[1::2] - bbox[1]
 
                 # resize
-                p[0::2] *= w_scale
-                p[1::2] *= h_scale
+                p[0::2] = p[0::2] * w_scale
+                p[1::2] = p[1::2] * h_scale
                 resized_mask.append(p)
             resized_masks.append(resized_mask)
         return PolygonMasks(resized_masks, *out_shape)


Test patch: