prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  When resize_keep_ratio is False, rescaling for masks does not work.
  Thanks for your error report and we appreciate it a lot.
  
  **Checklist**
  1. I have searched related issues but cannot get the expected help.
  2. The bug has not been fixed in the latest version.
  
  **Describe the bug**
  
  When `resize_keep_ratio=False`, rescaling for masks in loading the dataset will not work. The error is:
  ```
  Scale must be a number or tuple of int, but got <class 'numpy.ndarray'>
  ```
  
  
  --- 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/transforms.py`
  Content:
  ```
  1 import mmcv
  2 import numpy as np
  3 import torch
  4 
  5 __all__ = [
  6     'ImageTransform', 'BboxTransform', 'MaskTransform', 'SegMapTransform',
  7     'Numpy2Tensor'
  8 ]
  9 
  10 
  11 class ImageTransform(object):
  12     """Preprocess an image.
  13 
  14     1. rescale the image to expected size
  15     2. normalize the image
  16     3. flip the image (if needed)
  17     4. pad the image (if needed)
  18     5. transpose to (c, h, w)
  19     """
  20 
  21     def __init__(self,
  22                  mean=(0, 0, 0),
  23                  std=(1, 1, 1),
  24                  to_rgb=True,
  25                  size_divisor=None):
  26         self.mean = np.array(mean, dtype=np.float32)
  27         self.std = np.array(std, dtype=np.float32)
  28         self.to_rgb = to_rgb
  29         self.size_divisor = size_divisor
  30 
  31     def __call__(self, img, scale, flip=False, keep_ratio=True):
  32         if keep_ratio:
  33             img, scale_factor = mmcv.imrescale(img, scale, return_scale=True)
  34         else:
  35             img, w_scale, h_scale = mmcv.imresize(
  36                 img, scale, return_scale=True)
  37             scale_factor = np.array(
  38                 [w_scale, h_scale, w_scale, h_scale], dtype=np.float32)
  39         img_shape = img.shape
  40         img = mmcv.imnormalize(img, self.mean, self.std, self.to_rgb)
  41         if flip:
  42             img = mmcv.imflip(img)
  43         if self.size_divisor is not None:
  44             img = mmcv.impad_to_multiple(img, self.size_divisor)
  45             pad_shape = img.shape
  46         else:
  47             pad_shape = img_shape
  48         img = img.transpose(2, 0, 1)
  49         return img, img_shape, pad_shape, scale_factor
  50 
  51 
  52 def bbox_flip(bboxes, img_shape):
  53     """Flip bboxes horizontally.
  54 
  55     Args:
  56         bboxes(ndarray): shape (..., 4*k)
  57         img_shape(tuple): (height, width)
  58     """
  59     assert bboxes.shape[-1] % 4 == 0
  60     w = img_shape[1]
  61     flipped = bboxes.copy()
  62     flipped[..., 0::4] = w - bboxes[..., 2::4] - 1
  63     flipped[..., 2::4] = w - bboxes[..., 0::4] - 1
  64     return flipped
  65 
  66 
  67 class BboxTransform(object):
  68     """Preprocess gt bboxes.
  69 
  70     1. rescale bboxes according to image size
  71     2. flip bboxes (if needed)
  72     3. pad the first dimension to `max_num_gts`
  73     """
  74 
  75     def __init__(self, max_num_gts=None):
  76         self.max_num_gts = max_num_gts
  77 
  78     def __call__(self, bboxes, img_shape, scale_factor, flip=False):
  79         gt_bboxes = bboxes * scale_factor
  80         if flip:
  81             gt_bboxes = bbox_flip(gt_bboxes, img_shape)
  82         gt_bboxes[:, 0::2] = np.clip(gt_bboxes[:, 0::2], 0, img_shape[1] - 1)
  83         gt_bboxes[:, 1::2] = np.clip(gt_bboxes[:, 1::2], 0, img_shape[0] - 1)
  84         if self.max_num_gts is None:
  85             return gt_bboxes
  86         else:
  87             num_gts = gt_bboxes.shape[0]
  88             padded_bboxes = np.zeros((self.max_num_gts, 4), dtype=np.float32)
  89             padded_bboxes[:num_gts, :] = gt_bboxes
  90             return padded_bboxes
  91 
  92 
  93 class MaskTransform(object):
  94     """Preprocess masks.
  95 
  96     1. resize masks to expected size and stack to a single array
  97     2. flip the masks (if needed)
  98     3. pad the masks (if needed)
  99     """
  100 
  101     def __call__(self, masks, pad_shape, scale_factor, flip=False):
  102         masks = [
  103             mmcv.imrescale(mask, scale_factor, interpolation='nearest')
  104             for mask in masks
  105         ]
  106         if flip:
  107             masks = [mask[:, ::-1] for mask in masks]
  108         padded_masks = [
  109             mmcv.impad(mask, pad_shape[:2], pad_val=0) for mask in masks
  110         ]
  111         padded_masks = np.stack(padded_masks, axis=0)
  112         return padded_masks
  113 
  114 
  115 class SegMapTransform(object):
  116     """Preprocess semantic segmentation maps.
  117 
  118     1. rescale the segmentation map to expected size
  119     3. flip the image (if needed)
  120     4. pad the image (if needed)
  121     """
  122 
  123     def __init__(self, size_divisor=None):
  124         self.size_divisor = size_divisor
  125 
  126     def __call__(self, img, scale, flip=False, keep_ratio=True):
  127         if keep_ratio:
  128             img = mmcv.imrescale(img, scale, interpolation='nearest')
  129         else:
  130             img = mmcv.imresize(img, scale, interpolation='nearest')
  131         if flip:
  132             img = mmcv.imflip(img)
  133         if self.size_divisor is not None:
  134             img = mmcv.impad_to_multiple(img, self.size_divisor)
  135         return img
  136 
  137 
  138 class Numpy2Tensor(object):
  139 
  140     def __init__(self):
  141         pass
  142 
  143     def __call__(self, *args):
  144         if len(args) == 1:
  145             return torch.from_numpy(args[0])
  146         else:
  147             return tuple([torch.from_numpy(np.array(array)) for array in args])
  148
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/mmdet/datasets/transforms.py b/mmdet/datasets/transforms.py
  --- a/mmdet/datasets/transforms.py
  +++ b/mmdet/datasets/transforms.py
  @@ -34,8 +34,8 @@
           else:
               img, w_scale, h_scale = mmcv.imresize(
                   img, scale, return_scale=True)
  -            scale_factor = np.array(
  -                [w_scale, h_scale, w_scale, h_scale], dtype=np.float32)
  +            scale_factor = np.array([w_scale, h_scale, w_scale, h_scale],
  +                                    dtype=np.float32)
           img_shape = img.shape
           img = mmcv.imnormalize(img, self.mean, self.std, self.to_rgb)
           if flip:
  @@ -99,10 +99,24 @@
       """
   
       def __call__(self, masks, pad_shape, scale_factor, flip=False):
  -        masks = [
  -            mmcv.imrescale(mask, scale_factor, interpolation='nearest')
  -            for mask in masks
  -        ]
  +        # aspect ratio unchanged
  +        if isinstance(scale_factor, float):
  +            masks = [
  +                mmcv.imrescale(mask, scale_factor, interpolation='nearest')
  +                for mask in masks
  +            ]
  +        # aspect ratio changed
  +        else:
  +            w_ratio, h_ratio = scale_factor[:2]
  +            if masks:
  +                h, w = masks[0].shape[:2]
  +                new_h = int(np.round(h * h_ratio))
  +                new_w = int(np.round(w * w_ratio))
  +                new_size = (new_w, new_h)
  +                masks = [
  +                    mmcv.imresize(mask, new_size, interpolation='nearest')
  +                    for mask in masks
  +                ]
           if flip:
               masks = [mask[:, ::-1] for mask in masks]
           padded_masks = [
  
verification_info: {"golden_diff": "diff --git a/mmdet/datasets/transforms.py b/mmdet/datasets/transforms.py\n--- a/mmdet/datasets/transforms.py\n+++ b/mmdet/datasets/transforms.py\n@@ -34,8 +34,8 @@\n         else:\n             img, w_scale, h_scale = mmcv.imresize(\n                 img, scale, return_scale=True)\n-            scale_factor = np.array(\n-                [w_scale, h_scale, w_scale, h_scale], dtype=np.float32)\n+            scale_factor = np.array([w_scale, h_scale, w_scale, h_scale],\n+                                    dtype=np.float32)\n         img_shape = img.shape\n         img = mmcv.imnormalize(img, self.mean, self.std, self.to_rgb)\n         if flip:\n@@ -99,10 +99,24 @@\n     \"\"\"\n \n     def __call__(self, masks, pad_shape, scale_factor, flip=False):\n-        masks = [\n-            mmcv.imrescale(mask, scale_factor, interpolation='nearest')\n-            for mask in masks\n-        ]\n+        # aspect ratio unchanged\n+        if isinstance(scale_factor, float):\n+            masks = [\n+                mmcv.imrescale(mask, scale_factor, interpolation='nearest')\n+                for mask in masks\n+            ]\n+        # aspect ratio changed\n+        else:\n+            w_ratio, h_ratio = scale_factor[:2]\n+            if masks:\n+                h, w = masks[0].shape[:2]\n+                new_h = int(np.round(h * h_ratio))\n+                new_w = int(np.round(w * w_ratio))\n+                new_size = (new_w, new_h)\n+                masks = [\n+                    mmcv.imresize(mask, new_size, interpolation='nearest')\n+                    for mask in masks\n+                ]\n         if flip:\n             masks = [mask[:, ::-1] for mask in masks]\n         padded_masks = [\n", "issue": "When resize_keep_ratio is False, rescaling for masks does not work.\nThanks for your error report and we appreciate it a lot.\r\n\r\n**Checklist**\r\n1. I have searched related issues but cannot get the expected help.\r\n2. The bug has not been fixed in the latest version.\r\n\r\n**Describe the bug**\r\n\r\nWhen `resize_keep_ratio=False`, rescaling for masks in loading the dataset will not work. The error is:\r\n```\r\nScale must be a number or tuple of int, but got <class 'numpy.ndarray'>\r\n```\r\n\n", "before_files": [{"content": "import mmcv\nimport numpy as np\nimport torch\n\n__all__ = [\n    'ImageTransform', 'BboxTransform', 'MaskTransform', 'SegMapTransform',\n    'Numpy2Tensor'\n]\n\n\nclass ImageTransform(object):\n    \"\"\"Preprocess an image.\n\n    1. rescale the image to expected size\n    2. normalize the image\n    3. flip the image (if needed)\n    4. pad the image (if needed)\n    5. transpose to (c, h, w)\n    \"\"\"\n\n    def __init__(self,\n                 mean=(0, 0, 0),\n                 std=(1, 1, 1),\n                 to_rgb=True,\n                 size_divisor=None):\n        self.mean = np.array(mean, dtype=np.float32)\n        self.std = np.array(std, dtype=np.float32)\n        self.to_rgb = to_rgb\n        self.size_divisor = size_divisor\n\n    def __call__(self, img, scale, flip=False, keep_ratio=True):\n        if keep_ratio:\n            img, scale_factor = mmcv.imrescale(img, scale, return_scale=True)\n        else:\n            img, w_scale, h_scale = mmcv.imresize(\n                img, scale, return_scale=True)\n            scale_factor = np.array(\n                [w_scale, h_scale, w_scale, h_scale], dtype=np.float32)\n        img_shape = img.shape\n        img = mmcv.imnormalize(img, self.mean, self.std, self.to_rgb)\n        if flip:\n            img = mmcv.imflip(img)\n        if self.size_divisor is not None:\n            img = mmcv.impad_to_multiple(img, self.size_divisor)\n            pad_shape = img.shape\n        else:\n            pad_shape = img_shape\n        img = img.transpose(2, 0, 1)\n        return img, img_shape, pad_shape, scale_factor\n\n\ndef bbox_flip(bboxes, img_shape):\n    \"\"\"Flip bboxes horizontally.\n\n    Args:\n        bboxes(ndarray): shape (..., 4*k)\n        img_shape(tuple): (height, width)\n    \"\"\"\n    assert bboxes.shape[-1] % 4 == 0\n    w = img_shape[1]\n    flipped = bboxes.copy()\n    flipped[..., 0::4] = w - bboxes[..., 2::4] - 1\n    flipped[..., 2::4] = w - bboxes[..., 0::4] - 1\n    return flipped\n\n\nclass BboxTransform(object):\n    \"\"\"Preprocess gt bboxes.\n\n    1. rescale bboxes according to image size\n    2. flip bboxes (if needed)\n    3. pad the first dimension to `max_num_gts`\n    \"\"\"\n\n    def __init__(self, max_num_gts=None):\n        self.max_num_gts = max_num_gts\n\n    def __call__(self, bboxes, img_shape, scale_factor, flip=False):\n        gt_bboxes = bboxes * scale_factor\n        if flip:\n            gt_bboxes = bbox_flip(gt_bboxes, img_shape)\n        gt_bboxes[:, 0::2] = np.clip(gt_bboxes[:, 0::2], 0, img_shape[1] - 1)\n        gt_bboxes[:, 1::2] = np.clip(gt_bboxes[:, 1::2], 0, img_shape[0] - 1)\n        if self.max_num_gts is None:\n            return gt_bboxes\n        else:\n            num_gts = gt_bboxes.shape[0]\n            padded_bboxes = np.zeros((self.max_num_gts, 4), dtype=np.float32)\n            padded_bboxes[:num_gts, :] = gt_bboxes\n            return padded_bboxes\n\n\nclass MaskTransform(object):\n    \"\"\"Preprocess masks.\n\n    1. resize masks to expected size and stack to a single array\n    2. flip the masks (if needed)\n    3. pad the masks (if needed)\n    \"\"\"\n\n    def __call__(self, masks, pad_shape, scale_factor, flip=False):\n        masks = [\n            mmcv.imrescale(mask, scale_factor, interpolation='nearest')\n            for mask in masks\n        ]\n        if flip:\n            masks = [mask[:, ::-1] for mask in masks]\n        padded_masks = [\n            mmcv.impad(mask, pad_shape[:2], pad_val=0) for mask in masks\n        ]\n        padded_masks = np.stack(padded_masks, axis=0)\n        return padded_masks\n\n\nclass SegMapTransform(object):\n    \"\"\"Preprocess semantic segmentation maps.\n\n    1. rescale the segmentation map to expected size\n    3. flip the image (if needed)\n    4. pad the image (if needed)\n    \"\"\"\n\n    def __init__(self, size_divisor=None):\n        self.size_divisor = size_divisor\n\n    def __call__(self, img, scale, flip=False, keep_ratio=True):\n        if keep_ratio:\n            img = mmcv.imrescale(img, scale, interpolation='nearest')\n        else:\n            img = mmcv.imresize(img, scale, interpolation='nearest')\n        if flip:\n            img = mmcv.imflip(img)\n        if self.size_divisor is not None:\n            img = mmcv.impad_to_multiple(img, self.size_divisor)\n        return img\n\n\nclass Numpy2Tensor(object):\n\n    def __init__(self):\n        pass\n\n    def __call__(self, *args):\n        if len(args) == 1:\n            return torch.from_numpy(args[0])\n        else:\n            return tuple([torch.from_numpy(np.array(array)) for array in args])\n", "path": "mmdet/datasets/transforms.py"}], "after_files": [{"content": "import mmcv\nimport numpy as np\nimport torch\n\n__all__ = [\n    'ImageTransform', 'BboxTransform', 'MaskTransform', 'SegMapTransform',\n    'Numpy2Tensor'\n]\n\n\nclass ImageTransform(object):\n    \"\"\"Preprocess an image.\n\n    1. rescale the image to expected size\n    2. normalize the image\n    3. flip the image (if needed)\n    4. pad the image (if needed)\n    5. transpose to (c, h, w)\n    \"\"\"\n\n    def __init__(self,\n                 mean=(0, 0, 0),\n                 std=(1, 1, 1),\n                 to_rgb=True,\n                 size_divisor=None):\n        self.mean = np.array(mean, dtype=np.float32)\n        self.std = np.array(std, dtype=np.float32)\n        self.to_rgb = to_rgb\n        self.size_divisor = size_divisor\n\n    def __call__(self, img, scale, flip=False, keep_ratio=True):\n        if keep_ratio:\n            img, scale_factor = mmcv.imrescale(img, scale, return_scale=True)\n        else:\n            img, w_scale, h_scale = mmcv.imresize(\n                img, scale, return_scale=True)\n            scale_factor = np.array([w_scale, h_scale, w_scale, h_scale],\n                                    dtype=np.float32)\n        img_shape = img.shape\n        img = mmcv.imnormalize(img, self.mean, self.std, self.to_rgb)\n        if flip:\n            img = mmcv.imflip(img)\n        if self.size_divisor is not None:\n            img = mmcv.impad_to_multiple(img, self.size_divisor)\n            pad_shape = img.shape\n        else:\n            pad_shape = img_shape\n        img = img.transpose(2, 0, 1)\n        return img, img_shape, pad_shape, scale_factor\n\n\ndef bbox_flip(bboxes, img_shape):\n    \"\"\"Flip bboxes horizontally.\n\n    Args:\n        bboxes(ndarray): shape (..., 4*k)\n        img_shape(tuple): (height, width)\n    \"\"\"\n    assert bboxes.shape[-1] % 4 == 0\n    w = img_shape[1]\n    flipped = bboxes.copy()\n    flipped[..., 0::4] = w - bboxes[..., 2::4] - 1\n    flipped[..., 2::4] = w - bboxes[..., 0::4] - 1\n    return flipped\n\n\nclass BboxTransform(object):\n    \"\"\"Preprocess gt bboxes.\n\n    1. rescale bboxes according to image size\n    2. flip bboxes (if needed)\n    3. pad the first dimension to `max_num_gts`\n    \"\"\"\n\n    def __init__(self, max_num_gts=None):\n        self.max_num_gts = max_num_gts\n\n    def __call__(self, bboxes, img_shape, scale_factor, flip=False):\n        gt_bboxes = bboxes * scale_factor\n        if flip:\n            gt_bboxes = bbox_flip(gt_bboxes, img_shape)\n        gt_bboxes[:, 0::2] = np.clip(gt_bboxes[:, 0::2], 0, img_shape[1] - 1)\n        gt_bboxes[:, 1::2] = np.clip(gt_bboxes[:, 1::2], 0, img_shape[0] - 1)\n        if self.max_num_gts is None:\n            return gt_bboxes\n        else:\n            num_gts = gt_bboxes.shape[0]\n            padded_bboxes = np.zeros((self.max_num_gts, 4), dtype=np.float32)\n            padded_bboxes[:num_gts, :] = gt_bboxes\n            return padded_bboxes\n\n\nclass MaskTransform(object):\n    \"\"\"Preprocess masks.\n\n    1. resize masks to expected size and stack to a single array\n    2. flip the masks (if needed)\n    3. pad the masks (if needed)\n    \"\"\"\n\n    def __call__(self, masks, pad_shape, scale_factor, flip=False):\n        # aspect ratio unchanged\n        if isinstance(scale_factor, float):\n            masks = [\n                mmcv.imrescale(mask, scale_factor, interpolation='nearest')\n                for mask in masks\n            ]\n        # aspect ratio changed\n        else:\n            w_ratio, h_ratio = scale_factor[:2]\n            if masks:\n                h, w = masks[0].shape[:2]\n                new_h = int(np.round(h * h_ratio))\n                new_w = int(np.round(w * w_ratio))\n                new_size = (new_w, new_h)\n                masks = [\n                    mmcv.imresize(mask, new_size, interpolation='nearest')\n                    for mask in masks\n                ]\n        if flip:\n            masks = [mask[:, ::-1] for mask in masks]\n        padded_masks = [\n            mmcv.impad(mask, pad_shape[:2], pad_val=0) for mask in masks\n        ]\n        padded_masks = np.stack(padded_masks, axis=0)\n        return padded_masks\n\n\nclass SegMapTransform(object):\n    \"\"\"Preprocess semantic segmentation maps.\n\n    1. rescale the segmentation map to expected size\n    3. flip the image (if needed)\n    4. pad the image (if needed)\n    \"\"\"\n\n    def __init__(self, size_divisor=None):\n        self.size_divisor = size_divisor\n\n    def __call__(self, img, scale, flip=False, keep_ratio=True):\n        if keep_ratio:\n            img = mmcv.imrescale(img, scale, interpolation='nearest')\n        else:\n            img = mmcv.imresize(img, scale, interpolation='nearest')\n        if flip:\n            img = mmcv.imflip(img)\n        if self.size_divisor is not None:\n            img = mmcv.impad_to_multiple(img, self.size_divisor)\n        return img\n\n\nclass Numpy2Tensor(object):\n\n    def __init__(self):\n        pass\n\n    def __call__(self, *args):\n        if len(args) == 1:\n            return torch.from_numpy(args[0])\n        else:\n            return tuple([torch.from_numpy(np.array(array)) for array in args])\n", "path": "mmdet/datasets/transforms.py"}]}