From ad78a2f272c0635959228828a0711fb671dc1f06 Mon Sep 17 00:00:00 2001 From: nijkah Date: Wed, 14 Jun 2023 14:19:53 +0000 Subject: [PATCH 1/4] [Feature] Support RBox CopyPaste --- mmrotate/structures/bbox/quadri_boxes.py | 17 +++++++++++++++++ mmrotate/structures/bbox/rotated_boxes.py | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/mmrotate/structures/bbox/quadri_boxes.py b/mmrotate/structures/bbox/quadri_boxes.py index d78880b69..844a434e7 100644 --- a/mmrotate/structures/bbox/quadri_boxes.py +++ b/mmrotate/structures/bbox/quadri_boxes.py @@ -296,6 +296,23 @@ def find_inside_points(self, values = (x1 - pt_x) * (y2 - pt_y) - (y1 - pt_y) * (x2 - pt_x) return (values >= eps).all(dim=-1) | (values <= -eps).all(dim=-1) + def create_masks(self, img_shape: Tuple[int, int]) -> BitmapMasks: + """ + Args: + img_shape (Tuple[int, int]): A tuple of image height and width. + Returns: + :obj:`BitmapMasks`: Converted masks + """ + img_h, img_w = img_shape + polygons = self.tensor + + gt_masks = np.zeros((len(boxes), img_h, img_w), dtype=np.uint8) + + for i, polygon in enumerate(polygons): + cv2.drawContours(gt_masks[i], [polygon], 0, 1, -1) + return BitmapMasks(gt_masks, img_h, img_w) + + @staticmethod def overlaps(boxes1: BaseBoxes, boxes2: BaseBoxes, diff --git a/mmrotate/structures/bbox/rotated_boxes.py b/mmrotate/structures/bbox/rotated_boxes.py index 8280684f1..9e889e4dc 100644 --- a/mmrotate/structures/bbox/rotated_boxes.py +++ b/mmrotate/structures/bbox/rotated_boxes.py @@ -389,6 +389,23 @@ def find_inside_points(self, return (offset_x <= w / 2 - eps) & (offset_x >= - w / 2 + eps) & \ (offset_y <= h / 2 - eps) & (offset_y >= - h / 2 + eps) + def create_masks(self, img_shape: Tuple[int, int]) -> BitmapMasks: + """ + Args: + img_shape (Tuple[int, int]): A tuple of image height and width. + Returns: + :obj:`BitmapMasks`: Converted masks + """ + img_h, img_w = img_shape + boxes = self.tensor + + polygons = cls.rbox2corner(boxes) + gt_masks = np.zeros((len(boxes), img_h, img_w), dtype=np.uint8) + + for i, polygon in enumerate(polygons): + cv2.drawContours(gt_masks[i], [polygon], 0, 1, -1) + return BitmapMasks(gt_masks, img_h, img_w) + @staticmethod def overlaps(boxes1: BaseBoxes, boxes2: BaseBoxes, From f53b708a37880f3d606f6f456fce72cef19b44e1 Mon Sep 17 00:00:00 2001 From: nijkah Date: Wed, 14 Jun 2023 14:50:12 +0000 Subject: [PATCH 2/4] fix error --- mmrotate/structures/bbox/quadri_boxes.py | 5 ++--- mmrotate/structures/bbox/rotated_boxes.py | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mmrotate/structures/bbox/quadri_boxes.py b/mmrotate/structures/bbox/quadri_boxes.py index 844a434e7..530b9357d 100644 --- a/mmrotate/structures/bbox/quadri_boxes.py +++ b/mmrotate/structures/bbox/quadri_boxes.py @@ -304,15 +304,14 @@ def create_masks(self, img_shape: Tuple[int, int]) -> BitmapMasks: :obj:`BitmapMasks`: Converted masks """ img_h, img_w = img_shape - polygons = self.tensor + polygons = self.vertices.numpy().astype(np.int0) - gt_masks = np.zeros((len(boxes), img_h, img_w), dtype=np.uint8) + gt_masks = np.zeros((len(polygons), img_h, img_w), dtype=np.uint8) for i, polygon in enumerate(polygons): cv2.drawContours(gt_masks[i], [polygon], 0, 1, -1) return BitmapMasks(gt_masks, img_h, img_w) - @staticmethod def overlaps(boxes1: BaseBoxes, boxes2: BaseBoxes, diff --git a/mmrotate/structures/bbox/rotated_boxes.py b/mmrotate/structures/bbox/rotated_boxes.py index 9e889e4dc..86cde8f93 100644 --- a/mmrotate/structures/bbox/rotated_boxes.py +++ b/mmrotate/structures/bbox/rotated_boxes.py @@ -399,7 +399,8 @@ def create_masks(self, img_shape: Tuple[int, int]) -> BitmapMasks: img_h, img_w = img_shape boxes = self.tensor - polygons = cls.rbox2corner(boxes) + polygons = self.rbox2corner(boxes).numpy() + polygons = polygons.reshape(-1, 4, 2).astype(np.int0) gt_masks = np.zeros((len(boxes), img_h, img_w), dtype=np.uint8) for i, polygon in enumerate(polygons): From 03224d1fa0e07d8ebbb5025b3834934d31337fe9 Mon Sep 17 00:00:00 2001 From: nijkah Date: Wed, 14 Jun 2023 14:57:45 +0000 Subject: [PATCH 3/4] lint --- configs/h2rbox/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configs/h2rbox/README.md b/configs/h2rbox/README.md index 148f6bf3b..43e46cf93 100644 --- a/configs/h2rbox/README.md +++ b/configs/h2rbox/README.md @@ -38,9 +38,9 @@ DOTA2.0 DIOR -| Backbone | AP50:95 | AP50 | AP75 | Angle | lr schd | Mem (GB) | Inf Time (fps) | MS | Batch Size | Configs | Download | -| :----------------------: | :-----: | :---: | :---: | :---: | :-----: | :------: | :------------: | :-: | :--------: | :------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| ResNet50 (800,800) | 33.06 | 57.40 | 32.50 | le90 | 1x | 3.83 | | - | 2 | [h2rbox-le90_r50_fpn_adamw-1x_dior](./dior/h2rbox-le90_r50_fpn_adamw-1x_dior.py) | [model](https://download.openmmlab.com/mmrotate/v1.0/h2rbox/h2rbox-le90_r50_fpn_adamw-1x_dior/h2rbox-le90_r50_fpn_adamw-1x_dior-949b0e4c.pth) \| [log](https://download.openmmlab.com/mmrotate/v1.0/h2rbox/h2rbox-le90_r50_fpn_adamw-1x_dior/h2rbox-le90_r50_fpn_adamw-1x_dior-20221130_204038.json) | +| Backbone | AP50:95 | AP50 | AP75 | Angle | lr schd | Mem (GB) | Inf Time (fps) | MS | Batch Size | Configs | Download | +| :----------------: | :-----: | :---: | :---: | :---: | :-----: | :------: | :------------: | :-: | :--------: | :------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| ResNet50 (800,800) | 33.06 | 57.40 | 32.50 | le90 | 1x | 3.83 | | - | 2 | [h2rbox-le90_r50_fpn_adamw-1x_dior](./dior/h2rbox-le90_r50_fpn_adamw-1x_dior.py) | [model](https://download.openmmlab.com/mmrotate/v1.0/h2rbox/h2rbox-le90_r50_fpn_adamw-1x_dior/h2rbox-le90_r50_fpn_adamw-1x_dior-949b0e4c.pth) \| [log](https://download.openmmlab.com/mmrotate/v1.0/h2rbox/h2rbox-le90_r50_fpn_adamw-1x_dior/h2rbox-le90_r50_fpn_adamw-1x_dior-20221130_204038.json) | **Notes:** From 1df65c2a1b5c951d4c8a276e3a43975dd379f57d Mon Sep 17 00:00:00 2001 From: nijkah Date: Wed, 14 Jun 2023 16:33:00 +0000 Subject: [PATCH 4/4] Fix mask2rbox bug --- mmrotate/structures/bbox/rotated_boxes.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/mmrotate/structures/bbox/rotated_boxes.py b/mmrotate/structures/bbox/rotated_boxes.py index 86cde8f93..7354b3327 100644 --- a/mmrotate/structures/bbox/rotated_boxes.py +++ b/mmrotate/structures/bbox/rotated_boxes.py @@ -396,16 +396,8 @@ def create_masks(self, img_shape: Tuple[int, int]) -> BitmapMasks: Returns: :obj:`BitmapMasks`: Converted masks """ - img_h, img_w = img_shape - boxes = self.tensor - - polygons = self.rbox2corner(boxes).numpy() - polygons = polygons.reshape(-1, 4, 2).astype(np.int0) - gt_masks = np.zeros((len(boxes), img_h, img_w), dtype=np.uint8) - - for i, polygon in enumerate(polygons): - cv2.drawContours(gt_masks[i], [polygon], 0, 1, -1) - return BitmapMasks(gt_masks, img_h, img_w) + qbox = self.convert_to('qbox') + return qbox.create_masks(img_shape) @staticmethod def overlaps(boxes1: BaseBoxes, @@ -460,7 +452,8 @@ def from_instance_masks(masks: MaskType) -> 'RotatedBoxes': if isinstance(masks, BitmapMasks): for idx in range(num_masks): mask = masks.masks[idx] - points = np.stack(np.nonzero(mask), axis=-1).astype(np.float32) + coor_y, coor_x = np.nonzero(mask) + points = np.stack([coor_x, coor_y], axis=-1).astype(np.float32) (x, y), (w, h), angle = cv2.minAreaRect(points) boxes.append([x, y, w, h, angle / 180 * np.pi]) elif isinstance(masks, PolygonMasks):