From fc357b79dbfe53c8a77865d428affe964bb2603a Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Wed, 13 Jul 2022 18:53:52 -0700 Subject: [PATCH 01/15] change box api --- forte/data/ontology/top.py | 54 ++++++++++++++++++++++++---- tests/forte/image_annotation_test.py | 38 +++++++++++++++++++- 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 39688b906..0557db313 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1079,6 +1079,43 @@ class Box(Region): """ def __init__( + self, + pack: PackType, + tl_point: List[int], + br_point: List[int], + image_payload_idx: int = 0, + ): + super().__init__(pack, image_payload_idx) + if tl_point[0] < 0 or tl_point[1] < 0: + raise ValueError( + f"input parameter top left point indices ({tl_point}) must" + "be non-negative" + ) + if br_point[0] < 0 or br_point[1] < 0: + raise ValueError( + f"input parameter bottom right point indices ({br_point}) must" + "be non-negative" + ) + if tl_point[0] >= br_point[0]: + raise ValueError( + f"top left point y coordinate({tl_point[0]}) must be less than" + f" bottom right y coordinate({br_point[0]})" + ) + if tl_point[1] >= br_point[1]: + raise ValueError( + f"top left point x coordinate({tl_point[1]}) must be less than" + f" bottom right x coordinate({br_point[1]})" + ) + + self.y0, self.x0 = tl_point + self.y1, self.x1 = br_point + self._cy = round((self.y0 + self.y1) / 2) + self._cx = round((self.x0 + self.x1) / 2) + self._height = self.y1 - self.y0 + self._width = self.x1 - self.x0 + + @classmethod + def from_center_n_shape( self, pack: PackType, cy: int, @@ -1087,13 +1124,15 @@ def __init__( width: int, image_payload_idx: int = 0, ): - # assume Box is associated with Grids - super().__init__(pack, image_payload_idx) # center location - self._cy = cy - self._cx = cx self._height = height self._width = width + return self( + pack, + [cy - round(height / 2), cx - round(width / 2)], + [cy - round(height / 2) + height, cx - round(width / 2) + width], + image_payload_idx, + ) @property def center(self): @@ -1105,9 +1144,10 @@ def corners(self): Get corners of box. """ return [ - (self._cy + h_offset, self._cx + w_offset) - for h_offset in [-0.5 * self._height, 0.5 * self._height] - for w_offset in [-0.5 * self._width, 0.5 * self._width] + (self.y0, self.x0), + (self.y0, self.x1), + (self.y1, self.x0), + (self.y1, self.x1), ] @property diff --git a/tests/forte/image_annotation_test.py b/tests/forte/image_annotation_test.py index 35f523c80..280583e3a 100644 --- a/tests/forte/image_annotation_test.py +++ b/tests/forte/image_annotation_test.py @@ -19,7 +19,7 @@ import numpy as np from numpy import array_equal -from forte.data.ontology.top import ImageAnnotation +from forte.data.ontology.top import Box, ImageAnnotation from ft.onto.base_ontology import ImagePayload @@ -56,3 +56,39 @@ def test_image_annotation(self): self.assertEqual( new_pack.audio_annotations, self.datapack.audio_annotations ) + + def testBox(self): + + b1 = Box(self.datapack, [2, 2], [7, 7], 0) + self.assertEqual(b1.corners, [(2, 2), (2, 7), (7, 2), (7, 7)]) + self.assertEqual(b1.area, 25) + self.assertEqual(b1.center, (4, 4)) + + b2 = Box.from_center_n_shape(self.datapack, 4, 4, 5, 5) + self.assertEqual(b2.corners, [(2, 2), (2, 7), (7, 2), (7, 7)]) + self.assertEqual(b2.area, 25) + self.assertEqual(b2.center, (4, 4)) + + def wrong_box(): + # negative x coordinate + Box(self.datapack, [-2, 2], [7, 7], 0) + + self.assertRaises(ValueError, wrong_box) + + def wrong_box(): + # negative y coordinate + Box(self.datapack, [2, -2], [7, 7], 0) + + self.assertRaises(ValueError, wrong_box) + + def wrong_box(): + # negative width + Box(self.datapack, [3, 2], [2, 7], 0) + + self.assertRaises(ValueError, wrong_box) + + def wrong_box(): + # negative height + Box(self.datapack, [2, 2], [2, 1], 0) + + self.assertRaises(ValueError, wrong_box) From e66c5610f8a58340a5cb20cd31cbc04a659cf870 Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Wed, 13 Jul 2022 19:01:13 -0700 Subject: [PATCH 02/15] pylint --- forte/data/ontology/top.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 0557db313..a94a47247 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1116,7 +1116,7 @@ def __init__( @classmethod def from_center_n_shape( - self, + cls, pack: PackType, cy: int, cx: int, @@ -1125,9 +1125,7 @@ def from_center_n_shape( image_payload_idx: int = 0, ): # center location - self._height = height - self._width = width - return self( + return cls( pack, [cy - round(height / 2), cx - round(width / 2)], [cy - round(height / 2) + height, cx - round(width / 2) + width], @@ -1260,7 +1258,7 @@ def __init__( image_payload_idx: int = 0, ): self.grids = Grids(pack, grid_height, grid_width, image_payload_idx) - super().__init__( + super().__init__( # pylint: disable=too-many-function-args pack, *self.grids.get_grid_cell_center(grid_cell_h_idx, grid_cell_w_idx), height, From 9d16f856322ef6846c92de2e72b4c78109b7d514 Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Wed, 13 Jul 2022 20:28:44 -0700 Subject: [PATCH 03/15] adapt bounding box inheritance of box --- forte/data/ontology/top.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index a94a47247..2dd61d93f 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1258,11 +1258,13 @@ def __init__( image_payload_idx: int = 0, ): self.grids = Grids(pack, grid_height, grid_width, image_payload_idx) - super().__init__( # pylint: disable=too-many-function-args + cy, cx = self.grids.get_grid_cell_center( + grid_cell_h_idx, grid_cell_w_idx + ) + super().__init__( pack, - *self.grids.get_grid_cell_center(grid_cell_h_idx, grid_cell_w_idx), - height, - width, + [cy - round(height / 2), cx - round(width / 2)], + [cy - round(height / 2) + height, cx - round(width / 2) + width], image_payload_idx, ) From fa402e9241259f9d2ab9c42644ebf76cbc60718b Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Thu, 14 Jul 2022 09:32:15 -0700 Subject: [PATCH 04/15] change bounding box init method as well --- forte/data/ontology/top.py | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 2dd61d93f..b2c363712 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1249,22 +1249,33 @@ class BoundingBox(Box): def __init__( self, pack: PackType, + tl_point: List[int], + br_point: List[int], + image_payload_idx: int = 0, + ): + super().__init__( + pack, + tl_point, + br_point, + image_payload_idx, + ) + + @classmethod + def from_center_n_shape( + self, + pack: PackType, + cy: int, + cx: int, height: int, width: int, - grid_height: int, - grid_width: int, - grid_cell_h_idx: int, - grid_cell_w_idx: int, image_payload_idx: int = 0, ): - self.grids = Grids(pack, grid_height, grid_width, image_payload_idx) - cy, cx = self.grids.get_grid_cell_center( - grid_cell_h_idx, grid_cell_w_idx - ) - super().__init__( + return super().from_center_n_shape( pack, - [cy - round(height / 2), cx - round(width / 2)], - [cy - round(height / 2) + height, cx - round(width / 2) + width], + cy, + cx, + height, + width, image_payload_idx, ) From 399375e9faa9a6c8671e2d8aa0e2635f8d45f221 Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Thu, 14 Jul 2022 09:57:24 -0700 Subject: [PATCH 05/15] rewrite bounding box init method and make it clean --- forte/data/ontology/top.py | 76 ++++++++++++---------------- tests/forte/image_annotation_test.py | 6 ++- 2 files changed, 37 insertions(+), 45 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index b2c363712..c5dd4418d 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1067,15 +1067,13 @@ class Box(Region): Args: pack: the container that this ``Box`` will be added to. + tl_point: the indices of top left point of the box, the unit is one + pixel. + br_point: the indices of bottom right point of the box, the unit is one + pixel. image_payload_idx: the index of the image payload in the DataPack's image payload list. If it's not set, it defaults to 0 which meaning it will load the first image payload. - cy: the row index of the box center in the image array, - the unit is one image array entry. - cx: the column index of the box center in the image array, - the unit is one image array entry. - height: the height of the box, the unit is one image array entry. - width: the width of the box, the unit is one image array entry. """ def __init__( @@ -1115,7 +1113,7 @@ def __init__( self._width = self.x1 - self.x0 @classmethod - def from_center_n_shape( + def init_from_center_n_shape( cls, pack: PackType, cy: int, @@ -1124,6 +1122,23 @@ def from_center_n_shape( width: int, image_payload_idx: int = 0, ): + """ + A class method to initialize a ``Box`` from a box's center position and + shape. + + Args: + pack: the container that this ``BoundingBox`` will be added to. + cy: the y coordinate of the box's center, the unit is one pixel. + cx: the x coordinate of the box's center, the unit is one pixel. + height: the height of the box, the unit is one pixel. + width: the width of the box, the unit is one pixel. + image_payload_idx: the index of the image payload in the DataPack's + image payload list. If it's not set, it defaults to 0 which + meaning it will load the first image payload. + + Returns: + A ``Box`` instance. + """ # center location return cls( pack, @@ -1227,42 +1242,19 @@ class BoundingBox(Box): the image/grid. Args: - pack: The container that this BoundingBox will - be added to. + pack: the container that this ``Box`` will be added to. + tl_point: the indices of top left point of the box, the unit is one + pixel. + br_point: the indices of bottom right point of the box, the unit is one + pixel. image_payload_idx: the index of the image payload in the DataPack's image payload list. If it's not set, - it defaults to 0 which means it will load the first image payload. - height: the height of the bounding box, the unit is one image array - entry. - width: the width of the bounding box, the unit is one image array entry. - grid_height: the height of the associated grid, the unit is one grid - cell. - grid_width: the width of the associated grid, the unit is one grid - cell. - grid_cell_h_idx: the height index of the associated grid cell in - the grid, the unit is one grid cell. - grid_cell_w_idx: the width index of the associated grid cell in - the grid, the unit is one grid cell. - + it defaults to 0 which meaning it will load the first image payload. """ - def __init__( - self, - pack: PackType, - tl_point: List[int], - br_point: List[int], - image_payload_idx: int = 0, - ): - super().__init__( - pack, - tl_point, - br_point, - image_payload_idx, - ) - @classmethod - def from_center_n_shape( - self, + def init_from_center_n_shape( + cls, pack: PackType, cy: int, cx: int, @@ -1270,12 +1262,10 @@ def from_center_n_shape( width: int, image_payload_idx: int = 0, ): - return super().from_center_n_shape( + return cls( pack, - cy, - cx, - height, - width, + [cy - round(height / 2), cx - round(width / 2)], + [cy - round(height / 2) + height, cx - round(width / 2) + width], image_payload_idx, ) diff --git a/tests/forte/image_annotation_test.py b/tests/forte/image_annotation_test.py index 280583e3a..29ebe703d 100644 --- a/tests/forte/image_annotation_test.py +++ b/tests/forte/image_annotation_test.py @@ -19,7 +19,7 @@ import numpy as np from numpy import array_equal -from forte.data.ontology.top import Box, ImageAnnotation +from forte.data.ontology.top import BoundingBox, Box, ImageAnnotation from ft.onto.base_ontology import ImagePayload @@ -64,7 +64,7 @@ def testBox(self): self.assertEqual(b1.area, 25) self.assertEqual(b1.center, (4, 4)) - b2 = Box.from_center_n_shape(self.datapack, 4, 4, 5, 5) + b2 = Box.init_from_center_n_shape(self.datapack, 4, 4, 5, 5) self.assertEqual(b2.corners, [(2, 2), (2, 7), (7, 2), (7, 7)]) self.assertEqual(b2.area, 25) self.assertEqual(b2.center, (4, 4)) @@ -92,3 +92,5 @@ def wrong_box(): Box(self.datapack, [2, 2], [2, 1], 0) self.assertRaises(ValueError, wrong_box) + + b3 = BoundingBox.init_from_center_n_shape(self.datapack, 4, 4, 5, 5) From d9f552688168f61e94912ee4a1bbfe17b981bc01 Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Thu, 14 Jul 2022 09:59:58 -0700 Subject: [PATCH 06/15] add compute_iou method --- forte/data/ontology/top.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index c5dd4418d..e308b5c89 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1147,6 +1147,39 @@ def init_from_center_n_shape( image_payload_idx, ) + def compute_iou(self, other) -> float: + """ + A function computes iou(intersection over union) between two boxes + (unit: pixel). + It overwrites the ``compute_iou`` function in it's parent class + ``Region``. + Args: + other: the other ``Box`` object to be computed with. + Returns: + A float value which is (intersection area/ union area) between two + boxes. + """ + if not isinstance(other, Box): + raise ValueError( + "The other object to compute iou with is" + " not a Box object." + "You need to check the type of the other object." + ) + + if not self.is_overlapped(other): + return 0 + box_x_diff = min( + abs(other.box_max_x - self.box_min_x), + abs(other.box_min_x - self.box_max_x), + ) + box_y_diff = min( + abs(other.box_max_y - self.box_min_y), + abs(other.box_min_y - self.box_max_y), + ) + intersection = box_x_diff * box_y_diff + union = self.area + other.area - intersection + return intersection / union + @property def center(self): return (self._cy, self._cx) From 597129212061a94cc69772d96d052138b5e299ef Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Thu, 14 Jul 2022 10:11:31 -0700 Subject: [PATCH 07/15] remove old compute_iou method --- forte/data/ontology/top.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index e308b5c89..712681b99 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1240,31 +1240,6 @@ def is_overlapped(self, other): return False return True - def compute_iou(self, other): - """ - A function computes iou(intersection over union) between two boxes. - - Args: - other: the other ``Box`` object to compared to. - - Returns: - A float value which is (intersection area/ union area) between two - boxes. - """ - if not self.is_overlapped(other): - return 0 - box_x_diff = min( - abs(other.box_max_x - self.box_min_x), - abs(other.box_min_x - self.box_max_x), - ) - box_y_diff = min( - abs(other.box_max_y - self.box_min_y), - abs(other.box_min_y - self.box_max_y), - ) - intersection = box_x_diff * box_y_diff - union = self.area + other.area - intersection - return intersection / union - class BoundingBox(Box): """ From 708b004b40a96e3382a387f9a2eb301fa4123874 Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Thu, 14 Jul 2022 12:58:48 -0700 Subject: [PATCH 08/15] correct return typing --- forte/data/ontology/top.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 712681b99..912c5c15b 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1052,7 +1052,7 @@ def __init__(self, pack: PackType, image_payload_idx: int = 0): else: self._image_payload_idx = image_payload_idx - def compute_iou(self, other) -> int: + def compute_iou(self, other) -> float: intersection = np.sum(np.logical_and(self.image, other.image)) union = np.sum(np.logical_or(self.image, other.image)) return intersection / union From e3a61c1ee37f91cfae0e1b69bdf98c81a138aafc Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Thu, 14 Jul 2022 17:03:35 -0700 Subject: [PATCH 09/15] correct docstring and simplify box_min/max_x/y logitc --- forte/data/ontology/top.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 912c5c15b..2699aecda 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1198,19 +1198,19 @@ def corners(self): @property def box_min_x(self): - return max(self._cx - round(0.5 * self._width), 0) + return max(self.x0, 0) @property def box_max_x(self): - return min(self._cx + round(0.5 * self._width), self.max_x) + return min(self.x1, self.pack.image_width) @property def box_min_y(self): - return max(self._cy - round(0.5 * self._height), 0) + return max(self.y0, 0) @property def box_max_y(self): - return min(self._cy + round(0.5 * self._height), self.max_y) + return min(self.y1, self.pack.image_height) @property def area(self): @@ -1250,7 +1250,7 @@ class BoundingBox(Box): the image/grid. Args: - pack: the container that this ``Box`` will be added to. + pack: the container that this ``BoundingBox`` will be added to. tl_point: the indices of top left point of the box, the unit is one pixel. br_point: the indices of bottom right point of the box, the unit is one From e1c83932d97066889783b6c2644ea7134ed660f9 Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Fri, 15 Jul 2022 09:41:39 -0700 Subject: [PATCH 10/15] add docstring for BoundingBox.init_from_center_n_shape --- forte/data/ontology/top.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 2699aecda..0a3a16e76 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1127,7 +1127,7 @@ def init_from_center_n_shape( shape. Args: - pack: the container that this ``BoundingBox`` will be added to. + pack: the container that this ``Box`` will be added to. cy: the y coordinate of the box's center, the unit is one pixel. cx: the x coordinate of the box's center, the unit is one pixel. height: the height of the box, the unit is one pixel. @@ -1270,6 +1270,23 @@ def init_from_center_n_shape( width: int, image_payload_idx: int = 0, ): + """ + A class method to initialize a ``BoundingBox`` from a box's center position and + shape. + + Args: + pack: the container that this ``BoundingBox`` will be added to. + cy: the y coordinate of the box's center, the unit is one pixel. + cx: the x coordinate of the box's center, the unit is one pixel. + height: the height of the box, the unit is one pixel. + width: the width of the box, the unit is one pixel. + image_payload_idx: the index of the image payload in the DataPack's + image payload list. If it's not set, it defaults to 0 which + meaning it will load the first image payload. + + Returns: + A ``BoundingBox`` instance. + """ return cls( pack, [cy - round(height / 2), cx - round(width / 2)], From 2d13b0b74e111b0c3783f6b4a3a630b79eab289e Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Fri, 15 Jul 2022 11:32:11 -0700 Subject: [PATCH 11/15] made changes based on the code review --- forte/data/ontology/top.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 0a3a16e76..6b9f33ca0 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1105,12 +1105,12 @@ def __init__( f" bottom right x coordinate({br_point[1]})" ) - self.y0, self.x0 = tl_point - self.y1, self.x1 = br_point - self._cy = round((self.y0 + self.y1) / 2) - self._cx = round((self.x0 + self.x1) / 2) - self._height = self.y1 - self.y0 - self._width = self.x1 - self.x0 + self._y0, self._x0 = tl_point + self._y1, self._x1 = br_point + self._cy = round((self._y0 + self._y1) / 2) + self._cx = round((self._x0 + self._x1) / 2) + self._height = self._y1 - self._y0 + self._width = self._x1 - self._x0 @classmethod def init_from_center_n_shape( @@ -1190,27 +1190,27 @@ def corners(self): Get corners of box. """ return [ - (self.y0, self.x0), - (self.y0, self.x1), - (self.y1, self.x0), - (self.y1, self.x1), + (self._y0, self._x0), + (self._y0, self._x1), + (self._y1, self._x0), + (self._y1, self._x1), ] @property def box_min_x(self): - return max(self.x0, 0) + return self._x0 @property def box_max_x(self): - return min(self.x1, self.pack.image_width) + return min(self._x1, self.max_x) @property def box_min_y(self): - return max(self.y0, 0) + return self._y0 @property def box_max_y(self): - return min(self.y1, self.pack.image_height) + return min(self._y1, self.max_y) @property def area(self): From f041f232fa3aa83276bbedc6e09f6db5868b9f61 Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Mon, 18 Jul 2022 16:20:43 -0700 Subject: [PATCH 12/15] remove bounding box --- forte/data/ontology/top.py | 59 ++------------------------------------ 1 file changed, 2 insertions(+), 57 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 6b9f33ca0..8cf698839 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -61,7 +61,6 @@ "Grids", "Region", "Box", - "BoundingBox", "Payload", ] @@ -853,7 +852,7 @@ def get( class ImageAnnotation(Entry): def __init__(self, pack: PackType, image_payload_idx: int = 0): """ - ImageAnnotation type entries, such as "edge" and "bounding box". + ImageAnnotation type entries, such as "edge" and "box". Each ImageAnnotation has a ``image_payload_idx`` corresponding to its image representation in the payload array. @@ -1221,7 +1220,7 @@ def is_overlapped(self, other): A function checks whether two boxes are overlapped(two box area have intersections). - Note: in edges cases where two bounding boxes' boundaries share the + Note: in edges cases where two boxes' boundaries share the same line segment/corner in the image array, it won't be considered overlapped. @@ -1241,60 +1240,6 @@ def is_overlapped(self, other): return True -class BoundingBox(Box): - """ - A bounding box class that associates with image payload and grids and - has a configuration of height and width. - - Note: all indices are zero-based and counted from top left corner of - the image/grid. - - Args: - pack: the container that this ``BoundingBox`` will be added to. - tl_point: the indices of top left point of the box, the unit is one - pixel. - br_point: the indices of bottom right point of the box, the unit is one - pixel. - image_payload_idx: the index of the image payload in the DataPack's - image payload list. If it's not set, - it defaults to 0 which meaning it will load the first image payload. - """ - - @classmethod - def init_from_center_n_shape( - cls, - pack: PackType, - cy: int, - cx: int, - height: int, - width: int, - image_payload_idx: int = 0, - ): - """ - A class method to initialize a ``BoundingBox`` from a box's center position and - shape. - - Args: - pack: the container that this ``BoundingBox`` will be added to. - cy: the y coordinate of the box's center, the unit is one pixel. - cx: the x coordinate of the box's center, the unit is one pixel. - height: the height of the box, the unit is one pixel. - width: the width of the box, the unit is one pixel. - image_payload_idx: the index of the image payload in the DataPack's - image payload list. If it's not set, it defaults to 0 which - meaning it will load the first image payload. - - Returns: - A ``BoundingBox`` instance. - """ - return cls( - pack, - [cy - round(height / 2), cx - round(width / 2)], - [cy - round(height / 2) + height, cx - round(width / 2) + width], - image_payload_idx, - ) - - class Payload(Entry): """ A payload class that holds data cache of one modality and its data source uri. From 310360ecb7e22198a18ebc20401189a0e9bc0d01 Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Mon, 18 Jul 2022 17:06:12 -0700 Subject: [PATCH 13/15] BoundingBox -> Box for all files --- docs/notebook_tutorial/tutorial_MT_with_forte.ipynb | 2 +- examples/bounding_box/check_overlap.py | 8 ++++---- tests/forte/image_annotation_test.py | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/notebook_tutorial/tutorial_MT_with_forte.ipynb b/docs/notebook_tutorial/tutorial_MT_with_forte.ipynb index d0b70a2d4..dcdae617e 100644 --- a/docs/notebook_tutorial/tutorial_MT_with_forte.ipynb +++ b/docs/notebook_tutorial/tutorial_MT_with_forte.ipynb @@ -329,7 +329,7 @@ "* `AudioAnnotation` is inherited by all audio entries which usually has an audio span to retrieve partial audio from the full audio.\n", " * `Recording` is an example subclass of `AudioAnnotation`, and it has extra `recording_class` field denoting the classes the audio belongs to.\n", "* `ImageAnnotation` is inherited by all image entries which usually has payload index pointing to a loaded image array.\n", - " * `BoundingBox` is an example subclass of `ImageAnnotation`. As the picture shows, it has more inheritance relationships than other ontology classes due to the nature of CV objects. The advantage of forte ontology is that it supports complex inheritance, and users can inherit from existing ontology and add new ontology features for their needs.\n", + " * `Box` is an example subclass of `ImageAnnotation`. As the picture shows, it has more inheritance relationships than other ontology classes due to the nature of CV objects. The advantage of forte ontology is that it supports complex inheritance, and users can inherit from existing ontology and add new ontology features for their needs.\n", "* `Link` is inherited by all link-like entries which has parent and child.\n", " * `RelationLink` is an example subclass of `Link`, and it has a class attribute specifying the relation type. " ] diff --git a/examples/bounding_box/check_overlap.py b/examples/bounding_box/check_overlap.py index 8d586574f..189d0a283 100644 --- a/examples/bounding_box/check_overlap.py +++ b/examples/bounding_box/check_overlap.py @@ -1,5 +1,5 @@ import numpy as np -from forte.data.ontology.top import BoundingBox, Link, Annotation +from forte.data.ontology.top import Box, Link, Annotation from forte.data.data_pack import DataPack datapack = DataPack("image") @@ -13,15 +13,15 @@ datapack.payloads.append(line) # grid config: 3 x 4 # grid cell indices: (0, 0) -bb1 = BoundingBox(datapack, 0, 2, 2, 3, 4, 0, 0) +bb1 = Box(datapack, 0, 2, 2, 3, 4, 0, 0) datapack.image_annotations.append(bb1) # grid config: 3 x 4 # grid cell indices: (1, 0) -bb2 = BoundingBox(datapack, 0, 2, 2, 3, 4, 1, 0) +bb2 = Box(datapack, 0, 2, 2, 3, 4, 1, 0) datapack.image_annotations.append(bb2) # grid config: 4 x 4 # grid cell indices: (1, 0) -bb3 = BoundingBox(datapack, 0, 2, 2, 4, 4, 0, 0) +bb3 = Box(datapack, 0, 2, 2, 4, 4, 0, 0) print(bb1.is_overlapped(bb2)) print(bb1.is_overlapped(bb3)) diff --git a/tests/forte/image_annotation_test.py b/tests/forte/image_annotation_test.py index 29ebe703d..52e61b529 100644 --- a/tests/forte/image_annotation_test.py +++ b/tests/forte/image_annotation_test.py @@ -19,7 +19,7 @@ import numpy as np from numpy import array_equal -from forte.data.ontology.top import BoundingBox, Box, ImageAnnotation +from forte.data.ontology.top import Box, Box, ImageAnnotation from ft.onto.base_ontology import ImagePayload @@ -29,7 +29,7 @@ class ImageAnnotationTest(unittest.TestCase): """ - Test ImageAnnotation related ontologies like Edge and BoundingBox. + Test ImageAnnotation related ontologies like Edge and Box. """ def setUp(self): @@ -93,4 +93,4 @@ def wrong_box(): self.assertRaises(ValueError, wrong_box) - b3 = BoundingBox.init_from_center_n_shape(self.datapack, 4, 4, 5, 5) + b3 = Box.init_from_center_n_shape(self.datapack, 4, 4, 5, 5) From 0c9e9d9ab1e269bde5bdd25e2c0c343a2d9ae03d Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Tue, 19 Jul 2022 10:01:23 -0700 Subject: [PATCH 14/15] remove duplicated import --- tests/forte/image_annotation_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/forte/image_annotation_test.py b/tests/forte/image_annotation_test.py index 52e61b529..a83fa88b6 100644 --- a/tests/forte/image_annotation_test.py +++ b/tests/forte/image_annotation_test.py @@ -19,7 +19,7 @@ import numpy as np from numpy import array_equal -from forte.data.ontology.top import Box, Box, ImageAnnotation +from forte.data.ontology.top import Box, ImageAnnotation from ft.onto.base_ontology import ImagePayload From efe4a78126316838dbe74684417ef6c329613cbf Mon Sep 17 00:00:00 2001 From: Pengfei He Date: Tue, 19 Jul 2022 10:03:48 -0700 Subject: [PATCH 15/15] improve box docstring --- forte/data/ontology/top.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/forte/data/ontology/top.py b/forte/data/ontology/top.py index 8cf698839..c3e92a1e9 100644 --- a/forte/data/ontology/top.py +++ b/forte/data/ontology/top.py @@ -1066,10 +1066,10 @@ class Box(Region): Args: pack: the container that this ``Box`` will be added to. - tl_point: the indices of top left point of the box, the unit is one - pixel. - br_point: the indices of bottom right point of the box, the unit is one - pixel. + tl_point: the indices of top left point of the box + [row index, column index], the unit is one pixel. + br_point: the indices of bottom right point of the box + [row index, column index], the unit is one pixel. image_payload_idx: the index of the image payload in the DataPack's image payload list. If it's not set, it defaults to 0 which meaning it will load the first image payload. @@ -1125,10 +1125,13 @@ def init_from_center_n_shape( A class method to initialize a ``Box`` from a box's center position and shape. + Note: all indices are zero-based and counted from top left corner of + image. + Args: pack: the container that this ``Box`` will be added to. - cy: the y coordinate of the box's center, the unit is one pixel. - cx: the x coordinate of the box's center, the unit is one pixel. + cy: the row coordinate of the box's center, the unit is one pixel. + cx: the column coordinate of the box's center, the unit is one pixel. height: the height of the box, the unit is one pixel. width: the width of the box, the unit is one pixel. image_payload_idx: the index of the image payload in the DataPack's @@ -1152,6 +1155,7 @@ def compute_iou(self, other) -> float: (unit: pixel). It overwrites the ``compute_iou`` function in it's parent class ``Region``. + Args: other: the other ``Box`` object to be computed with. Returns: