|
|
|
@ -16,7 +16,7 @@
|
|
|
|
|
Testing the bounding box augment op in DE
|
|
|
|
|
"""
|
|
|
|
|
from enum import Enum
|
|
|
|
|
from mindspore import log as logger
|
|
|
|
|
import mindspore.log as logger
|
|
|
|
|
import mindspore.dataset as ds
|
|
|
|
|
import mindspore.dataset.transforms.vision.c_transforms as c_vision
|
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
@ -39,59 +39,36 @@ class BoxType(Enum):
|
|
|
|
|
WrongShape = 5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AddBadAnnotation: # pylint: disable=too-few-public-methods
|
|
|
|
|
def add_bad_annotation(img, bboxes, box_type):
|
|
|
|
|
"""
|
|
|
|
|
Used to add erroneous bounding boxes to object detection pipelines.
|
|
|
|
|
Usage:
|
|
|
|
|
>>> # Adds a box that covers the whole image. Good for testing edge cases
|
|
|
|
|
>>> de = de.map(input_columns=["image", "annotation"],
|
|
|
|
|
>>> output_columns=["image", "annotation"],
|
|
|
|
|
>>> operations=AddBadAnnotation(BoxType.OnEdge))
|
|
|
|
|
Used to generate erroneous bounding box examples on given img.
|
|
|
|
|
:param img: image where the bounding boxes are.
|
|
|
|
|
:param bboxes: in [x_min, y_min, w, h, label, truncate, difficult] format
|
|
|
|
|
:param box_type: type of bad box
|
|
|
|
|
:return: bboxes with bad examples added
|
|
|
|
|
"""
|
|
|
|
|
height = img.shape[0]
|
|
|
|
|
width = img.shape[1]
|
|
|
|
|
if box_type == BoxType.WidthOverflow:
|
|
|
|
|
# use box that overflows on width
|
|
|
|
|
return img, np.array([[0, 0, width + 1, height, 0, 0, 0]]).astype(np.uint32)
|
|
|
|
|
|
|
|
|
|
def __init__(self, box_type):
|
|
|
|
|
self.box_type = box_type
|
|
|
|
|
|
|
|
|
|
def __call__(self, img, bboxes):
|
|
|
|
|
"""
|
|
|
|
|
Used to generate erroneous bounding box examples on given img.
|
|
|
|
|
:param img: image where the bounding boxes are.
|
|
|
|
|
:param bboxes: in [x_min, y_min, w, h, label, truncate, difficult] format
|
|
|
|
|
:return: bboxes with bad examples added
|
|
|
|
|
"""
|
|
|
|
|
height = img.shape[0]
|
|
|
|
|
width = img.shape[1]
|
|
|
|
|
if self.box_type == BoxType.WidthOverflow:
|
|
|
|
|
# use box that overflows on width
|
|
|
|
|
return img, np.array([[0, 0, width + 1, height, 0, 0, 0]]).astype(np.uint32)
|
|
|
|
|
|
|
|
|
|
if self.box_type == BoxType.HeightOverflow:
|
|
|
|
|
# use box that overflows on height
|
|
|
|
|
return img, np.array([[0, 0, width, height + 1, 0, 0, 0]]).astype(np.uint32)
|
|
|
|
|
|
|
|
|
|
if self.box_type == BoxType.NegativeXY:
|
|
|
|
|
# use box with negative xy
|
|
|
|
|
return img, np.array([[-10, -10, width, height, 0, 0, 0]]).astype(np.uint32)
|
|
|
|
|
|
|
|
|
|
if self.box_type == BoxType.OnEdge:
|
|
|
|
|
# use box that covers the whole image
|
|
|
|
|
return img, np.array([[0, 0, width, height, 0, 0, 0]]).astype(np.uint32)
|
|
|
|
|
|
|
|
|
|
if self.box_type == BoxType.WrongShape:
|
|
|
|
|
# use box that covers the whole image
|
|
|
|
|
return img, np.array([[0, 0, width - 1]]).astype(np.uint32)
|
|
|
|
|
return img, bboxes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def h_flip(image):
|
|
|
|
|
"""
|
|
|
|
|
Apply the random_horizontal
|
|
|
|
|
"""
|
|
|
|
|
if box_type == BoxType.HeightOverflow:
|
|
|
|
|
# use box that overflows on height
|
|
|
|
|
return img, np.array([[0, 0, width, height + 1, 0, 0, 0]]).astype(np.uint32)
|
|
|
|
|
|
|
|
|
|
if box_type == BoxType.NegativeXY:
|
|
|
|
|
# use box with negative xy
|
|
|
|
|
return img, np.array([[-10, -10, width, height, 0, 0, 0]]).astype(np.uint32)
|
|
|
|
|
|
|
|
|
|
if box_type == BoxType.OnEdge:
|
|
|
|
|
# use box that covers the whole image
|
|
|
|
|
return img, np.array([[0, 0, width, height, 0, 0, 0]]).astype(np.uint32)
|
|
|
|
|
|
|
|
|
|
# with the seed provided in this test case, it will always flip.
|
|
|
|
|
# that's why we flip here too
|
|
|
|
|
image = image[:, ::-1, :]
|
|
|
|
|
return image
|
|
|
|
|
if box_type == BoxType.WrongShape:
|
|
|
|
|
# use box that covers the whole image
|
|
|
|
|
return img, np.array([[0, 0, width - 1]]).astype(np.uint32)
|
|
|
|
|
return img, bboxes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_bad_box(data, box_type, expected_error):
|
|
|
|
@ -102,8 +79,8 @@ def check_bad_box(data, box_type, expected_error):
|
|
|
|
|
:return: None
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
test_op = c_vision.BoundingBoxAug(c_vision.RandomHorizontalFlip(1),
|
|
|
|
|
1) # DEFINE TEST OP HERE -- (PROB 1 IN CASE OF RANDOM)
|
|
|
|
|
test_op = c_vision.BoundingBoxAugment(c_vision.RandomHorizontalFlip(1),
|
|
|
|
|
1) # DEFINE TEST OP HERE -- (PROB 1 IN CASE OF RANDOM)
|
|
|
|
|
data = data.map(input_columns=["annotation"],
|
|
|
|
|
output_columns=["annotation"],
|
|
|
|
|
operations=fix_annotate)
|
|
|
|
@ -111,7 +88,7 @@ def check_bad_box(data, box_type, expected_error):
|
|
|
|
|
data = data.map(input_columns=["image", "annotation"],
|
|
|
|
|
output_columns=["image", "annotation"],
|
|
|
|
|
columns_order=["image", "annotation"],
|
|
|
|
|
operations=AddBadAnnotation(box_type)) # Add column for "annotation"
|
|
|
|
|
operations=lambda img, bboxes: add_bad_annotation(img, bboxes, box_type))
|
|
|
|
|
# map to apply ops
|
|
|
|
|
data = data.map(input_columns=["image", "annotation"],
|
|
|
|
|
output_columns=["image", "annotation"],
|
|
|
|
@ -187,7 +164,7 @@ def test_bounding_box_augment_with_rotation_op(plot=False):
|
|
|
|
|
data_voc1 = ds.VOCDataset(DATA_DIR, task="Detection", mode="train", decode=True, shuffle=False)
|
|
|
|
|
data_voc2 = ds.VOCDataset(DATA_DIR, task="Detection", mode="train", decode=True, shuffle=False)
|
|
|
|
|
|
|
|
|
|
test_op = c_vision.BoundingBoxAug(c_vision.RandomRotation(90), 1)
|
|
|
|
|
test_op = c_vision.BoundingBoxAugment(c_vision.RandomRotation(90), 1)
|
|
|
|
|
# DEFINE TEST OP HERE -- (PROB 1 IN CASE OF RANDOM)
|
|
|
|
|
|
|
|
|
|
# maps to fix annotations to minddata standard
|
|
|
|
@ -216,7 +193,7 @@ def test_bounding_box_augment_with_crop_op(plot=False):
|
|
|
|
|
data_voc1 = ds.VOCDataset(DATA_DIR, task="Detection", mode="train", decode=True, shuffle=False)
|
|
|
|
|
data_voc2 = ds.VOCDataset(DATA_DIR, task="Detection", mode="train", decode=True, shuffle=False)
|
|
|
|
|
|
|
|
|
|
test_op = c_vision.BoundingBoxAug(c_vision.RandomCrop(90), 1)
|
|
|
|
|
test_op = c_vision.BoundingBoxAugment(c_vision.RandomCrop(90), 1)
|
|
|
|
|
|
|
|
|
|
# maps to fix annotations to minddata standard
|
|
|
|
|
data_voc1 = data_voc1.map(input_columns=["annotation"],
|
|
|
|
@ -244,7 +221,7 @@ def test_bounding_box_augment_valid_ratio_c(plot=False):
|
|
|
|
|
data_voc1 = ds.VOCDataset(DATA_DIR, task="Detection", mode="train", decode=True, shuffle=False)
|
|
|
|
|
data_voc2 = ds.VOCDataset(DATA_DIR, task="Detection", mode="train", decode=True, shuffle=False)
|
|
|
|
|
|
|
|
|
|
test_op = c_vision.BoundingBoxAug(c_vision.RandomHorizontalFlip(1), 0.9)
|
|
|
|
|
test_op = c_vision.BoundingBoxAugment(c_vision.RandomHorizontalFlip(1), 0.9)
|
|
|
|
|
# DEFINE TEST OP HERE -- (PROB 1 IN CASE OF RANDOM)
|
|
|
|
|
|
|
|
|
|
# maps to fix annotations to minddata standard
|
|
|
|
@ -274,7 +251,7 @@ def test_bounding_box_augment_invalid_ratio_c():
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# ratio range is from 0 - 1
|
|
|
|
|
test_op = c_vision.BoundingBoxAug(c_vision.RandomHorizontalFlip(1), 1.5)
|
|
|
|
|
test_op = c_vision.BoundingBoxAugment(c_vision.RandomHorizontalFlip(1), 1.5)
|
|
|
|
|
# maps to fix annotations to minddata standard
|
|
|
|
|
data_voc1 = data_voc1.map(input_columns=["annotation"],
|
|
|
|
|
output_columns=["annotation"],
|
|
|
|
|