1# Copyright 2020 Huawei Technologies Co., Ltd 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15""" 16Testing the bounding box augment op in DE 17""" 18 19import numpy as np 20import mindspore.log as logger 21import mindspore.dataset as ds 22import mindspore.dataset.vision.c_transforms as c_vision 23 24from util import visualize_with_bounding_boxes, InvalidBBoxType, check_bad_bbox, \ 25 config_get_set_seed, config_get_set_num_parallel_workers, save_and_check_md5 26 27GENERATE_GOLDEN = False 28 29# updated VOC dataset with correct annotations 30DATA_DIR = "../data/dataset/testVOC2012_2" 31DATA_DIR_2 = ["../data/dataset/testCOCO/train/", 32 "../data/dataset/testCOCO/annotations/train.json"] # DATA_DIR, ANNOTATION_DIR 33 34 35def test_bounding_box_augment_with_rotation_op(plot_vis=False): 36 """ 37 Test BoundingBoxAugment op (passing rotation op as transform) 38 Prints images side by side with and without Aug applied + bboxes to compare and test 39 """ 40 logger.info("test_bounding_box_augment_with_rotation_op") 41 42 original_seed = config_get_set_seed(0) 43 original_num_parallel_workers = config_get_set_num_parallel_workers(1) 44 45 dataVoc1 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 46 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 47 48 # Ratio is set to 1 to apply rotation on all bounding boxes. 49 test_op = c_vision.BoundingBoxAugment(c_vision.RandomRotation(90), 1) 50 51 # map to apply ops 52 dataVoc2 = dataVoc2.map(operations=[test_op], input_columns=["image", "bbox"], 53 output_columns=["image", "bbox"], 54 column_order=["image", "bbox"]) 55 56 filename = "bounding_box_augment_rotation_c_result.npz" 57 save_and_check_md5(dataVoc2, filename, generate_golden=GENERATE_GOLDEN) 58 59 unaugSamp, augSamp = [], [] 60 61 for unAug, Aug in zip(dataVoc1.create_dict_iterator(num_epochs=1, output_numpy=True), 62 dataVoc2.create_dict_iterator(num_epochs=1, output_numpy=True)): 63 unaugSamp.append(unAug) 64 augSamp.append(Aug) 65 66 if plot_vis: 67 visualize_with_bounding_boxes(unaugSamp, augSamp) 68 69 # Restore config setting 70 ds.config.set_seed(original_seed) 71 ds.config.set_num_parallel_workers(original_num_parallel_workers) 72 73 74def test_bounding_box_augment_with_crop_op(plot_vis=False): 75 """ 76 Test BoundingBoxAugment op (passing crop op as transform) 77 Prints images side by side with and without Aug applied + bboxes to compare and test 78 """ 79 logger.info("test_bounding_box_augment_with_crop_op") 80 81 original_seed = config_get_set_seed(0) 82 original_num_parallel_workers = config_get_set_num_parallel_workers(1) 83 84 dataVoc1 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 85 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 86 87 # Ratio is set to 0.9 to apply RandomCrop of size (50, 50) on 90% of the bounding boxes. 88 test_op = c_vision.BoundingBoxAugment(c_vision.RandomCrop(50), 0.9) 89 90 # map to apply ops 91 dataVoc2 = dataVoc2.map(operations=[test_op], input_columns=["image", "bbox"], 92 output_columns=["image", "bbox"], 93 column_order=["image", "bbox"]) 94 95 filename = "bounding_box_augment_crop_c_result.npz" 96 save_and_check_md5(dataVoc2, filename, generate_golden=GENERATE_GOLDEN) 97 98 unaugSamp, augSamp = [], [] 99 100 for unAug, Aug in zip(dataVoc1.create_dict_iterator(num_epochs=1, output_numpy=True), 101 dataVoc2.create_dict_iterator(num_epochs=1, output_numpy=True)): 102 unaugSamp.append(unAug) 103 augSamp.append(Aug) 104 105 if plot_vis: 106 visualize_with_bounding_boxes(unaugSamp, augSamp) 107 108 # Restore config setting 109 ds.config.set_seed(original_seed) 110 ds.config.set_num_parallel_workers(original_num_parallel_workers) 111 112 113def test_bounding_box_augment_valid_ratio_c(plot_vis=False): 114 """ 115 Test BoundingBoxAugment op (testing with valid ratio, less than 1. 116 Prints images side by side with and without Aug applied + bboxes to compare and test 117 """ 118 logger.info("test_bounding_box_augment_valid_ratio_c") 119 120 original_seed = config_get_set_seed(1) 121 original_num_parallel_workers = config_get_set_num_parallel_workers(1) 122 123 dataVoc1 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 124 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 125 126 test_op = c_vision.BoundingBoxAugment(c_vision.RandomHorizontalFlip(1), 0.9) 127 128 # map to apply ops 129 dataVoc2 = dataVoc2.map(operations=[test_op], input_columns=["image", "bbox"], 130 output_columns=["image", "bbox"], 131 column_order=["image", "bbox"]) # Add column for "bbox" 132 133 filename = "bounding_box_augment_valid_ratio_c_result.npz" 134 save_and_check_md5(dataVoc2, filename, generate_golden=GENERATE_GOLDEN) 135 136 unaugSamp, augSamp = [], [] 137 138 for unAug, Aug in zip(dataVoc1.create_dict_iterator(num_epochs=1, output_numpy=True), 139 dataVoc2.create_dict_iterator(num_epochs=1, output_numpy=True)): 140 unaugSamp.append(unAug) 141 augSamp.append(Aug) 142 143 if plot_vis: 144 visualize_with_bounding_boxes(unaugSamp, augSamp) 145 146 # Restore config setting 147 ds.config.set_seed(original_seed) 148 ds.config.set_num_parallel_workers(original_num_parallel_workers) 149 150 151def test_bounding_box_augment_op_coco_c(plot_vis=False): 152 """ 153 Prints images and bboxes side by side with and without BoundingBoxAugment Op applied, 154 Testing with COCO dataset 155 """ 156 logger.info("test_bounding_box_augment_op_coco_c") 157 158 dataCoco1 = ds.CocoDataset(DATA_DIR_2[0], annotation_file=DATA_DIR_2[1], task="Detection", 159 decode=True, shuffle=False) 160 161 dataCoco2 = ds.CocoDataset(DATA_DIR_2[0], annotation_file=DATA_DIR_2[1], task="Detection", 162 decode=True, shuffle=False) 163 164 test_op = c_vision.BoundingBoxAugment(c_vision.RandomHorizontalFlip(1), 1) 165 166 dataCoco2 = dataCoco2.map(operations=[test_op], input_columns=["image", "bbox"], 167 output_columns=["image", "bbox"], 168 column_order=["image", "bbox"]) 169 170 unaugSamp, augSamp = [], [] 171 172 for unAug, Aug in zip(dataCoco1.create_dict_iterator(num_epochs=1, output_numpy=True), 173 dataCoco2.create_dict_iterator(num_epochs=1, output_numpy=True)): 174 unaugSamp.append(unAug) 175 augSamp.append(Aug) 176 177 if plot_vis: 178 visualize_with_bounding_boxes(unaugSamp, augSamp, "bbox") 179 180 181def test_bounding_box_augment_valid_edge_c(plot_vis=False): 182 """ 183 Test BoundingBoxAugment op (testing with valid edge case, box covering full image). 184 Prints images side by side with and without Aug applied + bboxes to compare and test 185 """ 186 logger.info("test_bounding_box_augment_valid_edge_c") 187 188 original_seed = config_get_set_seed(1) 189 original_num_parallel_workers = config_get_set_num_parallel_workers(1) 190 191 dataVoc1 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 192 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 193 194 test_op = c_vision.BoundingBoxAugment(c_vision.RandomHorizontalFlip(1), 1) 195 196 # map to apply ops 197 # Add column for "bbox" 198 dataVoc1 = dataVoc1.map( 199 operations=lambda img, bbox: (img, np.array([[0, 0, img.shape[1], img.shape[0], 0, 0, 0]]).astype(np.float32)), 200 input_columns=["image", "bbox"], 201 output_columns=["image", "bbox"], 202 column_order=["image", "bbox"]) 203 dataVoc2 = dataVoc2.map( 204 operations=lambda img, bbox: (img, np.array([[0, 0, img.shape[1], img.shape[0], 0, 0, 0]]).astype(np.float32)), 205 input_columns=["image", "bbox"], 206 output_columns=["image", "bbox"], 207 column_order=["image", "bbox"]) 208 dataVoc2 = dataVoc2.map(operations=[test_op], input_columns=["image", "bbox"], 209 output_columns=["image", "bbox"], 210 column_order=["image", "bbox"]) 211 filename = "bounding_box_augment_valid_edge_c_result.npz" 212 save_and_check_md5(dataVoc2, filename, generate_golden=GENERATE_GOLDEN) 213 214 unaugSamp, augSamp = [], [] 215 216 for unAug, Aug in zip(dataVoc1.create_dict_iterator(num_epochs=1, output_numpy=True), 217 dataVoc2.create_dict_iterator(num_epochs=1, output_numpy=True)): 218 unaugSamp.append(unAug) 219 augSamp.append(Aug) 220 221 if plot_vis: 222 visualize_with_bounding_boxes(unaugSamp, augSamp) 223 224 # Restore config setting 225 ds.config.set_seed(original_seed) 226 ds.config.set_num_parallel_workers(original_num_parallel_workers) 227 228 229def test_bounding_box_augment_invalid_ratio_c(): 230 """ 231 Test BoundingBoxAugment op with invalid input ratio 232 """ 233 logger.info("test_bounding_box_augment_invalid_ratio_c") 234 235 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 236 237 try: 238 # ratio range is from 0 - 1 239 test_op = c_vision.BoundingBoxAugment(c_vision.RandomHorizontalFlip(1), 1.5) 240 # map to apply ops 241 dataVoc2 = dataVoc2.map(operations=[test_op], input_columns=["image", "bbox"], 242 output_columns=["image", "bbox"], 243 column_order=["image", "bbox"]) # Add column for "bbox" 244 except ValueError as error: 245 logger.info("Got an exception in DE: {}".format(str(error))) 246 assert "Input ratio is not within the required interval of [0.0, 1.0]." in str(error) 247 248 249def test_bounding_box_augment_invalid_bounds_c(): 250 """ 251 Test BoundingBoxAugment op with invalid bboxes. 252 """ 253 logger.info("test_bounding_box_augment_invalid_bounds_c") 254 255 test_op = c_vision.BoundingBoxAugment(c_vision.RandomHorizontalFlip(1), 256 1) 257 258 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 259 check_bad_bbox(dataVoc2, test_op, InvalidBBoxType.WidthOverflow, "bounding boxes is out of bounds of the image") 260 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 261 check_bad_bbox(dataVoc2, test_op, InvalidBBoxType.HeightOverflow, "bounding boxes is out of bounds of the image") 262 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 263 check_bad_bbox(dataVoc2, test_op, InvalidBBoxType.NegativeXY, "negative value") 264 dataVoc2 = ds.VOCDataset(DATA_DIR, task="Detection", usage="train", shuffle=False, decode=True) 265 check_bad_bbox(dataVoc2, test_op, InvalidBBoxType.WrongShape, "4 features") 266 267 268if __name__ == "__main__": 269 # set to false to not show plots 270 test_bounding_box_augment_with_rotation_op(plot_vis=False) 271 test_bounding_box_augment_with_crop_op(plot_vis=False) 272 test_bounding_box_augment_op_coco_c(plot_vis=False) 273 test_bounding_box_augment_valid_ratio_c(plot_vis=False) 274 test_bounding_box_augment_valid_edge_c(plot_vis=False) 275 test_bounding_box_augment_invalid_ratio_c() 276 test_bounding_box_augment_invalid_bounds_c() 277