From 83a9a2391abe7319665fd7b292a665f9f8bf4160 Mon Sep 17 00:00:00 2001 From: Taylor Robie Date: Fri, 10 Aug 2018 10:38:10 -0700 Subject: [PATCH] remove fork of object_detection created for MLPerf. (#4840) --- .../Mask_RCNN/README.md | 1 - .../e2e_mask_rcnn_R-50-C4_atrous.config | 170 - .../mask_rcnn_resnet50_atrous_coco.config | 169 - .../Mask_RCNN/mask_rcnn_run_loop.py | 243 -- .../object_detection/CONTRIBUTING.md | 13 - .../Mask_RCNN/object_detection/README.md | 190 - .../Mask_RCNN/object_detection/__init__.py | 0 .../anchor_generators/__init__.py | 0 .../grid_anchor_generator.py | 205 -- .../grid_anchor_generator_test.py | 104 - .../multiple_grid_anchor_generator.py | 336 -- .../multiple_grid_anchor_generator_test.py | 289 -- .../multiscale_grid_anchor_generator.py | 138 - .../multiscale_grid_anchor_generator_test.py | 258 -- .../object_detection/box_coders/__init__.py | 0 .../box_coders/faster_rcnn_box_coder.py | 118 - .../box_coders/faster_rcnn_box_coder_test.py | 94 - .../box_coders/keypoint_box_coder.py | 171 - .../box_coders/keypoint_box_coder_test.py | 140 - .../box_coders/mean_stddev_box_coder.py | 79 - .../box_coders/mean_stddev_box_coder_test.py | 54 - .../box_coders/square_box_coder.py | 126 - .../box_coders/square_box_coder_test.py | 97 - .../object_detection/builders/__init__.py | 0 .../builders/anchor_generator_builder.py | 94 - .../builders/anchor_generator_builder_test.py | 300 -- .../builders/box_coder_builder.py | 66 - .../builders/box_coder_builder_test.py | 136 - .../builders/box_predictor_builder.py | 138 - .../builders/box_predictor_builder_test.py | 514 --- .../builders/dataset_builder.py | 196 - .../builders/dataset_builder_test.py | 260 -- .../builders/graph_rewriter_builder.py | 42 - .../builders/graph_rewriter_builder_test.py | 57 - .../builders/hyperparams_builder.py | 182 - .../builders/hyperparams_builder_test.py | 509 --- .../builders/image_resizer_builder.py | 115 - .../builders/image_resizer_builder_test.py | 113 - .../builders/input_reader_builder.py | 76 - .../builders/input_reader_builder_test.py | 144 - .../builders/losses_builder.py | 222 -- .../builders/losses_builder_test.py | 488 --- .../builders/matcher_builder.py | 53 - .../builders/matcher_builder_test.py | 99 - .../builders/model_builder.py | 377 -- .../builders/model_builder_test.py | 1056 ------ .../builders/optimizer_builder.py | 124 - .../builders/optimizer_builder_test.py | 208 -- .../builders/post_processing_builder.py | 123 - .../builders/post_processing_builder_test.py | 107 - .../builders/preprocessor_builder.py | 322 -- .../builders/preprocessor_builder_test.py | 566 --- .../region_similarity_calculator_builder.py | 56 - ...gion_similarity_calculator_builder_test.py | 67 - .../object_detection/core/__init__.py | 1 - .../object_detection/core/anchor_generator.py | 150 - .../balanced_positive_negative_sampler.py | 105 - ...balanced_positive_negative_sampler_test.py | 106 - .../object_detection/core/batcher.py | 136 - .../object_detection/core/batcher_test.py | 158 - .../object_detection/core/box_coder.py | 151 - .../object_detection/core/box_coder_test.py | 61 - .../object_detection/core/box_list.py | 207 -- .../object_detection/core/box_list_ops.py | 1061 ------ .../core/box_list_ops_test.py | 1036 ------ .../object_detection/core/box_list_test.py | 134 - .../object_detection/core/box_predictor.py | 963 ----- .../core/box_predictor_test.py | 724 ---- .../object_detection/core/data_decoder.py | 41 - .../object_detection/core/data_parser.py | 41 - .../object_detection/core/keypoint_ops.py | 282 -- .../core/keypoint_ops_test.py | 200 -- .../Mask_RCNN/object_detection/core/losses.py | 641 ---- .../object_detection/core/losses_test.py | 962 ----- .../object_detection/core/matcher.py | 259 -- .../object_detection/core/matcher_test.py | 192 - .../core/minibatch_sampler.py | 90 - .../core/minibatch_sampler_test.py | 82 - .../Mask_RCNN/object_detection/core/model.py | 305 -- .../object_detection/core/post_processing.py | 425 --- .../core/post_processing_test.py | 1078 ------ .../object_detection/core/prefetcher.py | 61 - .../object_detection/core/prefetcher_test.py | 101 - .../object_detection/core/preprocessor.py | 3176 ----------------- .../core/preprocessor_cache.py | 102 - .../core/preprocessor_test.py | 2814 --------------- .../core/region_similarity_calculator.py | 114 - .../core/region_similarity_calculator_test.py | 75 - .../object_detection/core/standard_fields.py | 227 -- .../object_detection/core/target_assigner.py | 458 --- .../core/target_assigner_test.py | 827 ----- .../data/ava_label_map_v2.1.pbtxt | 240 -- .../data/kitti_label_map.pbtxt | 9 - .../data/mscoco_label_map.pbtxt | 400 --- .../data/oid_bbox_trainable_label_map.pbtxt | 2725 -------------- ...ct_detection_challenge_500_label_map.pbtxt | 2500 ------------- .../data/pascal_label_map.pbtxt | 99 - .../object_detection/data/pet_label_map.pbtxt | 184 - .../data_decoders/__init__.py | 0 .../data_decoders/tf_example_decoder.py | 439 --- .../data_decoders/tf_example_decoder_test.py | 767 ---- .../dataset_tools/__init__.py | 0 .../dataset_tools/create_coco_tf_record.py | 273 -- .../create_coco_tf_record_test.py | 188 - .../dataset_tools/create_kitti_tf_record.py | 310 -- .../create_kitti_tf_record_test.py | 130 - .../dataset_tools/create_oid_tf_record.py | 117 - .../dataset_tools/create_pascal_tf_record.py | 185 - .../create_pascal_tf_record_test.py | 118 - .../dataset_tools/create_pet_tf_record.py | 318 -- .../download_and_preprocess_mscoco.sh | 106 - .../oid_hierarchical_labels_expansion.py | 172 - .../oid_hierarchical_labels_expansion_test.py | 88 - .../dataset_tools/oid_tfrecord_creation.py | 106 - .../oid_tfrecord_creation_test.py | 200 -- .../dataset_tools/tf_record_creation_util.py | 46 - .../tf_record_creation_util_test.py | 42 - .../Mask_RCNN/object_detection/eval.py | 147 - .../Mask_RCNN/object_detection/eval_util.py | 645 ---- .../object_detection/eval_util_test.py | 112 - .../Mask_RCNN/object_detection/evaluator.py | 278 -- .../export_inference_graph.py | 147 - .../Mask_RCNN/object_detection/exporter.py | 465 --- .../object_detection/exporter_test.py | 864 ----- .../g3doc/configuring_jobs.md | 162 - .../g3doc/defining_your_own_model.md | 137 - .../g3doc/detection_model_zoo.md | 116 - .../g3doc/evaluation_protocols.md | 129 - .../g3doc/exporting_models.md | 27 - .../Mask_RCNN/object_detection/g3doc/faq.md | 19 - .../g3doc/img/dogs_detections_output.jpg | Bin 372894 -> 0 bytes .../g3doc/img/example_cat.jpg | Bin 243955 -> 0 bytes .../g3doc/img/groupof_case_eval.png | Bin 242500 -> 0 bytes .../g3doc/img/kites_detections_output.jpg | Bin 386066 -> 0 bytes .../g3doc/img/kites_with_segment_overlay.png | Bin 7165291 -> 0 bytes .../g3doc/img/nongroupof_case_eval.png | Bin 265455 -> 0 bytes .../g3doc/img/oid_bus_72e19c28aac34ed8.jpg | Bin 249313 -> 0 bytes .../g3doc/img/oid_monkey_3b4168c89cecbc5b.jpg | Bin 281143 -> 0 bytes .../object_detection/g3doc/img/oxford_pet.png | Bin 276715 -> 0 bytes .../g3doc/img/tensorboard.png | Bin 79342 -> 0 bytes .../g3doc/img/tensorboard2.png | Bin 236549 -> 0 bytes .../g3doc/img/tf-od-api-logo.png | Bin 200506 -> 0 bytes .../object_detection/g3doc/installation.md | 104 - .../g3doc/instance_segmentation.md | 105 - .../g3doc/oid_inference_and_evaluation.md | 255 -- .../g3doc/preparing_inputs.md | 57 - .../object_detection/g3doc/running_locally.md | 81 - .../g3doc/running_notebook.md | 15 - .../g3doc/running_on_cloud.md | 132 - .../object_detection/g3doc/running_pets.md | 336 -- .../g3doc/using_your_own_dataset.md | 161 - .../object_detection/inference/__init__.py | 0 .../inference/detection_inference.py | 141 - .../inference/detection_inference_test.py | 176 - .../inference/infer_detections.py | 96 - .../Mask_RCNN/object_detection/inputs.py | 440 --- .../Mask_RCNN/object_detection/inputs_test.py | 601 ---- .../object_detection/matchers/__init__.py | 0 .../matchers/argmax_matcher.py | 204 -- .../matchers/argmax_matcher_test.py | 207 -- .../matchers/bipartite_matcher.py | 64 - .../matchers/bipartite_matcher_test.py | 71 - .../meta_architectures/__init__.py | 0 .../faster_rcnn_meta_arch.py | 2028 ----------- .../faster_rcnn_meta_arch_test.py | 370 -- .../faster_rcnn_meta_arch_test_lib.py | 1512 -------- .../meta_architectures/rfcn_meta_arch.py | 299 -- .../meta_architectures/rfcn_meta_arch_test.py | 65 - .../meta_architectures/ssd_meta_arch.py | 870 ----- .../meta_architectures/ssd_meta_arch_test.py | 554 --- .../object_detection/metrics/__init__.py | 0 .../metrics/coco_evaluation.py | 658 ---- .../metrics/coco_evaluation_test.py | 727 ---- .../object_detection/metrics/coco_tools.py | 850 ----- .../metrics/coco_tools_test.py | 295 -- .../metrics/offline_eval_map_corloc.py | 173 - .../metrics/offline_eval_map_corloc_test.py | 58 - .../metrics/oid_vrd_challenge_evaluation.py | 151 - .../oid_vrd_challenge_evaluation_utils.py | 133 - ...oid_vrd_challenge_evaluation_utils_test.py | 149 - .../metrics/tf_example_parser.py | 157 - .../metrics/tf_example_parser_test.py | 196 - .../object_detection/model_hparams.py | 44 - .../Mask_RCNN/object_detection/model_lib.py | 717 ---- .../object_detection/model_lib_test.py | 402 --- .../Mask_RCNN/object_detection/model_main.py | 86 - .../object_detection/model_tpu_main.py | 135 - .../object_detection/models/__init__.py | 0 ...dded_ssd_mobilenet_v1_feature_extractor.py | 165 - ...ssd_mobilenet_v1_feature_extractor_test.py | 129 - ...n_inception_resnet_v2_feature_extractor.py | 213 -- ...eption_resnet_v2_feature_extractor_test.py | 109 - ...ter_rcnn_inception_v2_feature_extractor.py | 254 -- ...cnn_inception_v2_feature_extractor_test.py | 126 - ...ter_rcnn_mobilenet_v1_feature_extractor.py | 194 - ...cnn_mobilenet_v1_feature_extractor_test.py | 126 - .../faster_rcnn_nas_feature_extractor.py | 324 -- .../faster_rcnn_nas_feature_extractor_test.py | 109 - .../faster_rcnn_pnas_feature_extractor.py | 318 -- ...faster_rcnn_pnas_feature_extractor_test.py | 122 - ...faster_rcnn_resnet_v1_feature_extractor.py | 253 -- ...r_rcnn_resnet_v1_feature_extractor_test.py | 137 - .../models/feature_map_generators.py | 225 -- .../models/feature_map_generators_test.py | 179 - .../models/ssd_feature_extractor_test.py | 110 - .../ssd_inception_v2_feature_extractor.py | 126 - ...ssd_inception_v2_feature_extractor_test.py | 134 - .../ssd_inception_v3_feature_extractor.py | 126 - ...ssd_inception_v3_feature_extractor_test.py | 134 - .../ssd_mobilenet_v1_feature_extractor.py | 128 - ...ssd_mobilenet_v1_feature_extractor_test.py | 166 - .../ssd_mobilenet_v2_feature_extractor.py | 129 - ...ssd_mobilenet_v2_feature_extractor_test.py | 154 - .../ssd_resnet_v1_fpn_feature_extractor.py | 290 -- ...sd_resnet_v1_fpn_feature_extractor_test.py | 84 - ...esnet_v1_fpn_feature_extractor_testbase.py | 107 - .../object_detection_tutorial.ipynb | 343 -- .../object_detection/protos/__init__.py | 0 .../protos/anchor_generator.proto | 17 - .../protos/anchor_generator_pb2.py | 102 - .../protos/argmax_matcher.proto | 29 - .../protos/argmax_matcher_pb2.py | 104 - .../protos/bipartite_matcher.proto | 11 - .../protos/bipartite_matcher_pb2.py | 69 - .../object_detection/protos/box_coder.proto | 19 - .../object_detection/protos/box_coder_pb2.py | 114 - .../protos/box_predictor.proto | 153 - .../protos/box_predictor_pb2.py | 517 --- .../object_detection/protos/eval.proto | 78 - .../object_detection/protos/eval_pb2.py | 209 -- .../object_detection/protos/faster_rcnn.proto | 155 - .../protos/faster_rcnn_box_coder.proto | 17 - .../protos/faster_rcnn_box_coder_pb2.py | 90 - .../protos/faster_rcnn_pb2.py | 333 -- .../protos/graph_rewriter.proto | 23 - .../protos/graph_rewriter_pb2.py | 123 - .../protos/grid_anchor_generator.proto | 34 - .../protos/grid_anchor_generator_pb2.py | 118 - .../object_detection/protos/hyperparams.proto | 115 - .../protos/hyperparams_pb2.py | 605 ---- .../protos/image_resizer.proto | 59 - .../protos/image_resizer_pb2.py | 260 -- .../protos/input_reader.proto | 92 - .../protos/input_reader_pb2.py | 296 -- .../protos/keypoint_box_coder.proto | 19 - .../protos/keypoint_box_coder_pb2.py | 97 - .../object_detection/protos/losses.proto | 164 - .../object_detection/protos/losses_pb2.py | 755 ---- .../object_detection/protos/matcher.proto | 15 - .../object_detection/protos/matcher_pb2.py | 90 - .../protos/mean_stddev_box_coder.proto | 10 - .../protos/mean_stddev_box_coder_pb2.py | 69 - .../object_detection/protos/model.proto | 14 - .../object_detection/protos/model_pb2.py | 90 - .../protos/multiscale_anchor_generator.proto | 26 - .../protos/multiscale_anchor_generator_pb2.py | 104 - .../object_detection/protos/optimizer.proto | 88 - .../object_detection/protos/optimizer_pb2.py | 605 ---- .../object_detection/protos/pipeline.proto | 21 - .../object_detection/protos/pipeline_pb2.py | 116 - .../protos/post_processing.proto | 46 - .../protos/post_processing_pb2.py | 173 - .../protos/preprocessor.proto | 411 --- .../protos/preprocessor_pb2.py | 2028 ----------- .../protos/region_similarity_calculator.proto | 25 - .../region_similarity_calculator_pb2.py | 194 - .../protos/square_box_coder.proto | 14 - .../protos/square_box_coder_pb2.py | 83 - .../object_detection/protos/ssd.proto | 123 - .../protos/ssd_anchor_generator.proto | 55 - .../protos/ssd_anchor_generator_pb2.py | 153 - .../object_detection/protos/ssd_pb2.py | 282 -- .../protos/string_int_label_map.proto | 24 - .../protos/string_int_label_map_pb2.py | 123 - .../object_detection/protos/train.proto | 109 - .../object_detection/protos/train_pb2.py | 237 -- .../object_detection/samples/cloud/cloud.yml | 11 - .../embedded_ssd_mobilenet_v1_coco.config | 186 - ...cnn_inception_resnet_v2_atrous_coco.config | 142 - ...ion_resnet_v2_atrous_cosine_lr_coco.config | 132 - ...rcnn_inception_resnet_v2_atrous_oid.config | 142 - ...cnn_inception_resnet_v2_atrous_pets.config | 142 - .../faster_rcnn_inception_v2_coco.config | 141 - .../faster_rcnn_inception_v2_pets.config | 141 - .../configs/faster_rcnn_nas_coco.config | 142 - .../faster_rcnn_resnet101_atrous_coco.config | 136 - .../faster_rcnn_resnet101_ava_v2.1.config | 138 - .../configs/faster_rcnn_resnet101_coco.config | 135 - .../faster_rcnn_resnet101_kitti.config | 138 - .../configs/faster_rcnn_resnet101_pets.config | 140 - .../faster_rcnn_resnet101_voc07.config | 133 - .../configs/faster_rcnn_resnet152_coco.config | 140 - .../configs/faster_rcnn_resnet152_pets.config | 140 - .../configs/faster_rcnn_resnet50_coco.config | 140 - .../configs/faster_rcnn_resnet50_pets.config | 141 - ...cnn_inception_resnet_v2_atrous_coco.config | 166 - .../mask_rcnn_inception_v2_coco.config | 165 - .../mask_rcnn_resnet101_atrous_coco.config | 166 - .../configs/mask_rcnn_resnet101_pets.config | 157 - .../mask_rcnn_resnet50_atrous_coco.config | 166 - .../configs/rfcn_resnet101_coco.config | 137 - .../configs/rfcn_resnet101_pets.config | 137 - .../configs/ssd_inception_v2_coco.config | 189 - .../configs/ssd_inception_v2_pets.config | 190 - .../configs/ssd_inception_v3_pets.config | 189 - .../configs/ssd_mobilenet_v1_coco.config | 194 - .../ssd_mobilenet_v1_focal_loss_coco.config | 192 - .../ssd_mobilenet_v1_focal_loss_pets.config | 192 - .../configs/ssd_mobilenet_v1_pets.config | 194 - .../configs/ssd_mobilenet_v2_coco.config | 194 - .../configs/ssdlite_mobilenet_v1_coco.config | 196 - .../configs/ssdlite_mobilenet_v2_coco.config | 196 - .../test_data/pets_examples.record | Bin 873919 -> 0 bytes .../object_detection/test_images/image1.jpg | Bin 129862 -> 0 bytes .../object_detection/test_images/image2.jpg | Bin 1415684 -> 0 bytes .../test_images/image_info.txt | 6 - .../Mask_RCNN/object_detection/train.py | 184 - .../Mask_RCNN/object_detection/trainer.py | 410 --- .../object_detection/trainer_test.py | 268 -- .../object_detection/utils/__init__.py | 0 .../object_detection/utils/category_util.py | 72 - .../utils/category_util_test.py | 54 - .../object_detection/utils/config_util.py | 656 ---- .../utils/config_util_test.py | 583 --- .../object_detection/utils/context_manager.py | 40 - .../utils/context_manager_test.py | 33 - .../object_detection/utils/dataset_util.py | 146 - .../utils/dataset_util_test.py | 141 - .../object_detection/utils/json_utils.py | 87 - .../object_detection/utils/json_utils_test.py | 97 - .../object_detection/utils/label_map_util.py | 181 - .../utils/label_map_util_test.py | 247 -- .../utils/learning_schedules.py | 171 - .../utils/learning_schedules_test.py | 154 - .../object_detection/utils/metrics.py | 190 - .../object_detection/utils/metrics_test.py | 143 - .../object_detection/utils/np_box_list.py | 133 - .../object_detection/utils/np_box_list_ops.py | 554 --- .../utils/np_box_list_ops_test.py | 414 --- .../utils/np_box_list_test.py | 135 - .../utils/np_box_mask_list.py | 63 - .../utils/np_box_mask_list_ops.py | 399 --- .../utils/np_box_mask_list_ops_test.py | 191 - .../utils/np_box_mask_list_test.py | 182 - .../object_detection/utils/np_box_ops.py | 97 - .../object_detection/utils/np_box_ops_test.py | 68 - .../object_detection/utils/np_mask_ops.py | 119 - .../utils/np_mask_ops_test.py | 88 - .../utils/object_detection_evaluation.py | 863 ----- .../utils/object_detection_evaluation_test.py | 687 ---- .../Mask_RCNN/object_detection/utils/ops.py | 959 ----- .../object_detection/utils/ops_test.py | 1369 ------- .../utils/per_image_evaluation.py | 584 --- .../utils/per_image_evaluation_test.py | 561 --- .../utils/per_image_vrd_evaluation.py | 219 -- .../utils/per_image_vrd_evaluation_test.py | 94 - .../object_detection/utils/shape_utils.py | 309 -- .../utils/shape_utils_test.py | 321 -- .../object_detection/utils/static_shape.py | 71 - .../utils/static_shape_test.py | 50 - .../object_detection/utils/test_case.py | 98 - .../object_detection/utils/test_utils.py | 173 - .../object_detection/utils/test_utils_test.py | 89 - .../utils/variables_helper.py | 144 - .../utils/variables_helper_test.py | 213 -- .../utils/visualization_utils.py | 733 ---- .../utils/visualization_utils_test.py | 230 -- .../object_detection/utils/vrd_evaluation.py | 572 --- .../utils/vrd_evaluation_test.py | 255 -- research/mlperf_object_detection/README.md | 1 - 370 files changed, 89836 deletions(-) delete mode 100644 research/mlperf_object_detection/Mask_RCNN/README.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/configs/e2e_mask_rcnn_R-50-C4_atrous.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/configs/mask_rcnn_resnet50_atrous_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/mask_rcnn_run_loop.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/CONTRIBUTING.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/README.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/grid_anchor_generator.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/grid_anchor_generator_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiple_grid_anchor_generator.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiple_grid_anchor_generator_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiscale_grid_anchor_generator.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiscale_grid_anchor_generator_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/faster_rcnn_box_coder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/faster_rcnn_box_coder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/keypoint_box_coder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/keypoint_box_coder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/mean_stddev_box_coder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/mean_stddev_box_coder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/square_box_coder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/square_box_coder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/anchor_generator_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/anchor_generator_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_coder_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_coder_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_predictor_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_predictor_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/dataset_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/dataset_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/graph_rewriter_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/graph_rewriter_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/hyperparams_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/hyperparams_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/image_resizer_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/image_resizer_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/input_reader_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/input_reader_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/anchor_generator.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_coder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_coder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_ops.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_ops_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_predictor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_predictor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/data_decoder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/data_parser.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/keypoint_ops.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/keypoint_ops_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/losses.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/losses_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/matcher.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/matcher_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/minibatch_sampler.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/minibatch_sampler_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/model.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/post_processing.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/post_processing_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/prefetcher.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/prefetcher_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor_cache.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/region_similarity_calculator.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/region_similarity_calculator_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/standard_fields.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/target_assigner.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/core/target_assigner_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data/ava_label_map_v2.1.pbtxt delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data/kitti_label_map.pbtxt delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data/mscoco_label_map.pbtxt delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data/oid_bbox_trainable_label_map.pbtxt delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data/oid_object_detection_challenge_500_label_map.pbtxt delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data/pascal_label_map.pbtxt delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data/pet_label_map.pbtxt delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/tf_example_decoder.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/tf_example_decoder_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_coco_tf_record.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_coco_tf_record_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_kitti_tf_record.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_kitti_tf_record_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_oid_tf_record.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pascal_tf_record.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pascal_tf_record_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pet_tf_record.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/download_and_preprocess_mscoco.sh delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_hierarchical_labels_expansion.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_hierarchical_labels_expansion_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_tfrecord_creation.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_tfrecord_creation_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/tf_record_creation_util.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/tf_record_creation_util_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/eval.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/eval_util.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/eval_util_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/evaluator.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/export_inference_graph.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/exporter.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/exporter_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/configuring_jobs.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/defining_your_own_model.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/detection_model_zoo.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/evaluation_protocols.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/exporting_models.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/faq.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/dogs_detections_output.jpg delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/example_cat.jpg delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/groupof_case_eval.png delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/kites_detections_output.jpg delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/kites_with_segment_overlay.png delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/nongroupof_case_eval.png delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/oid_bus_72e19c28aac34ed8.jpg delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/oid_monkey_3b4168c89cecbc5b.jpg delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/oxford_pet.png delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/tensorboard.png delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/tensorboard2.png delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/tf-od-api-logo.png delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/installation.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/instance_segmentation.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/oid_inference_and_evaluation.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/preparing_inputs.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/running_locally.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/running_notebook.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/running_on_cloud.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/running_pets.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/using_your_own_dataset.md delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/inference/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/inference/detection_inference.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/inference/detection_inference_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/inference/infer_detections.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/inputs.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/inputs_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/matchers/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/matchers/argmax_matcher.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/matchers/argmax_matcher_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/matchers/bipartite_matcher.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/matchers/bipartite_matcher_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/meta_architectures/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/meta_architectures/faster_rcnn_meta_arch.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/meta_architectures/faster_rcnn_meta_arch_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/meta_architectures/faster_rcnn_meta_arch_test_lib.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/meta_architectures/rfcn_meta_arch.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/meta_architectures/rfcn_meta_arch_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/meta_architectures/ssd_meta_arch.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/meta_architectures/ssd_meta_arch_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/coco_evaluation.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/coco_evaluation_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/coco_tools.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/coco_tools_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/offline_eval_map_corloc.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/offline_eval_map_corloc_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/oid_vrd_challenge_evaluation.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/oid_vrd_challenge_evaluation_utils.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/oid_vrd_challenge_evaluation_utils_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/tf_example_parser.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/metrics/tf_example_parser_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/model_hparams.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/model_lib.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/model_lib_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/model_main.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/model_tpu_main.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/embedded_ssd_mobilenet_v1_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/embedded_ssd_mobilenet_v1_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_inception_resnet_v2_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_inception_resnet_v2_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_inception_v2_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_inception_v2_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_mobilenet_v1_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_mobilenet_v1_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_nas_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_nas_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_pnas_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_pnas_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_resnet_v1_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/faster_rcnn_resnet_v1_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/feature_map_generators.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/feature_map_generators_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_inception_v2_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_inception_v2_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_inception_v3_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_inception_v3_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_mobilenet_v1_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_mobilenet_v1_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_mobilenet_v2_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_mobilenet_v2_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_resnet_v1_fpn_feature_extractor.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_resnet_v1_fpn_feature_extractor_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/models/ssd_resnet_v1_fpn_feature_extractor_testbase.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/object_detection_tutorial.ipynb delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/anchor_generator.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/anchor_generator_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/argmax_matcher.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/argmax_matcher_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/bipartite_matcher.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/bipartite_matcher_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/box_coder.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/box_coder_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/box_predictor.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/box_predictor_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/eval.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/eval_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/faster_rcnn.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/faster_rcnn_box_coder.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/faster_rcnn_box_coder_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/faster_rcnn_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/graph_rewriter.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/graph_rewriter_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/grid_anchor_generator.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/grid_anchor_generator_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/hyperparams.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/hyperparams_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/image_resizer.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/image_resizer_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/input_reader.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/input_reader_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/keypoint_box_coder.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/keypoint_box_coder_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/losses.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/losses_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/matcher.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/matcher_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/mean_stddev_box_coder.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/mean_stddev_box_coder_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/model.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/model_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/multiscale_anchor_generator.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/multiscale_anchor_generator_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/optimizer.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/optimizer_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/pipeline.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/pipeline_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/post_processing.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/post_processing_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/preprocessor.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/preprocessor_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/region_similarity_calculator.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/region_similarity_calculator_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/square_box_coder.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/square_box_coder_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/ssd.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/ssd_anchor_generator.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/ssd_anchor_generator_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/ssd_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/string_int_label_map.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/string_int_label_map_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/train.proto delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/protos/train_pb2.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/cloud/cloud.yml delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/embedded_ssd_mobilenet_v1_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_inception_resnet_v2_atrous_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_inception_resnet_v2_atrous_cosine_lr_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_inception_resnet_v2_atrous_oid.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_inception_resnet_v2_atrous_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_inception_v2_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_inception_v2_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_nas_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet101_atrous_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet101_ava_v2.1.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet101_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet101_kitti.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet101_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet101_voc07.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet152_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet152_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet50_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/faster_rcnn_resnet50_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/mask_rcnn_inception_resnet_v2_atrous_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/mask_rcnn_inception_v2_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/mask_rcnn_resnet101_atrous_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/mask_rcnn_resnet101_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/mask_rcnn_resnet50_atrous_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/rfcn_resnet101_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/rfcn_resnet101_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssd_inception_v2_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssd_inception_v2_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssd_inception_v3_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssd_mobilenet_v1_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssd_mobilenet_v1_focal_loss_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssd_mobilenet_v1_focal_loss_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssd_mobilenet_v1_pets.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssd_mobilenet_v2_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssdlite_mobilenet_v1_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/samples/configs/ssdlite_mobilenet_v2_coco.config delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/test_data/pets_examples.record delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/test_images/image1.jpg delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/test_images/image2.jpg delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/test_images/image_info.txt delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/train.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/trainer.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/trainer_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/__init__.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/category_util.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/category_util_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/config_util.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/config_util_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/context_manager.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/context_manager_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/dataset_util.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/dataset_util_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/json_utils.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/json_utils_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/label_map_util.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/label_map_util_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/learning_schedules.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/learning_schedules_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/metrics.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/metrics_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_list.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_list_ops.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_list_ops_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_list_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_mask_list.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_mask_list_ops.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_mask_list_ops_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_mask_list_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_ops.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_box_ops_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_mask_ops.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/np_mask_ops_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/object_detection_evaluation.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/object_detection_evaluation_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/ops.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/ops_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/per_image_evaluation.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/per_image_evaluation_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/per_image_vrd_evaluation.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/per_image_vrd_evaluation_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/shape_utils.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/shape_utils_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/static_shape.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/static_shape_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/test_case.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/test_utils.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/test_utils_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/variables_helper.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/variables_helper_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/visualization_utils.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/visualization_utils_test.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/vrd_evaluation.py delete mode 100644 research/mlperf_object_detection/Mask_RCNN/object_detection/utils/vrd_evaluation_test.py delete mode 100644 research/mlperf_object_detection/README.md diff --git a/research/mlperf_object_detection/Mask_RCNN/README.md b/research/mlperf_object_detection/Mask_RCNN/README.md deleted file mode 100644 index 16bdc70c4..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/README.md +++ /dev/null @@ -1 +0,0 @@ -Mask RCNN Implimentation adopted from models/research/object_detection/ diff --git a/research/mlperf_object_detection/Mask_RCNN/configs/e2e_mask_rcnn_R-50-C4_atrous.config b/research/mlperf_object_detection/Mask_RCNN/configs/e2e_mask_rcnn_R-50-C4_atrous.config deleted file mode 100644 index 6085c7838..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/configs/e2e_mask_rcnn_R-50-C4_atrous.config +++ /dev/null @@ -1,170 +0,0 @@ -# Mask R-CNN with Resnet-50 (v1), Atrous version -# Configured for MSCOCO Dataset. -# Users should configure the fine_tune_checkpoint field in the train config as -# well as the label_map_path and input_path fields in the train_input_reader and -# eval_input_reader. Search for "PATH_TO_BE_CONFIGURED" to find the fields that -# should be configured. - -model { - faster_rcnn { - num_classes: 81 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 800 - max_dimension: 1365 - } - } - number_of_stages: 3 - feature_extractor { - type: 'faster_rcnn_resnet50' - first_stage_features_stride: 8 - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.125, 0.25, 0.5, 1.0, 2.0] # base size=256**2 => anchor sizes=32 64 128 256 512 - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 8 - width_stride: 8 - } - } - first_stage_atrous_rate: 2 - first_stage_box_predictor_conv_hyperparams { - op: CONV - regularizer { - l2_regularizer { - weight: 0.0 - } - } - initializer { - truncated_normal_initializer { - stddev: 0.01 - } - } - } - first_stage_nms_score_threshold: 0.0 - first_stage_nms_iou_threshold: 0.7 - first_stage_max_proposals: 512 - first_stage_localization_loss_weight: 2.0 - first_stage_objectness_loss_weight: 1.0 - initial_crop_size: 14 - maxpool_kernel_size: 2 - maxpool_stride: 2 - second_stage_batch_size: 512 - second_stage_box_predictor { - mask_rcnn_box_predictor { - use_dropout: false - dropout_keep_probability: 1.0 - predict_instance_masks: true - mask_height: 14 - mask_width: 14 - mask_prediction_conv_depth: 0 - mask_prediction_num_conv_layers: 3 #from mask rcnn heads - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - weight: 0.0 - } - } - initializer { - variance_scaling_initializer { - factor: 1.0 - uniform: true - mode: FAN_AVG - } - } - } - conv_hyperparams { - op: CONV - regularizer { - l2_regularizer { - weight: 0.0 - } - } - initializer { - truncated_normal_initializer { - stddev: 0.01 - } - } - } - } - } - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.0 - iou_threshold: 0.6 - max_detections_per_class: 2000 - max_total_detections: 2000 - } - score_converter: SOFTMAX - } - second_stage_localization_loss_weight: 2.0 - second_stage_classification_loss_weight: 1.0 - second_stage_mask_prediction_loss_weight: 4.0 - } -} - -train_config: { - batch_size: 4 - optimizer { - momentum_optimizer: { - learning_rate: { - manual_step_learning_rate { - initial_learning_rate: 0.01 - schedule { - step: 120000 - learning_rate: .001 - } - schedule { - step: 160000 - learning_rate: .0001 - } - } - } - momentum_optimizer_value: 0.9 - } - use_moving_average: false - } - gradient_clipping_by_norm: 10.0 - #fine_tune_checkpoint: "/home/mehdisharif/data/coco/resnet_v1_50.ckpt" - #from_detection_checkpoint: True - # Note: The below line limits the training process to 200K steps, which we - # empirically found to be sufficient enough to train the pets dataset. This - # effectively bypasses the learning rate schedule (the learning rate will - # never decay). Remove the below line to train indefinitely. - num_steps: 20000000 - data_augmentation_options { - random_horizontal_flip { - } - } -} - -train_input_reader: { - tf_record_input_reader { - input_path: "/home/mehdisharif/data/coco/output2017/coco_train.record" - } - label_map_path: "/home/mehdisharif/data/coco/output2017/mscoco_label_map.pbtxt" - load_instance_masks: true - mask_type: PNG_MASKS -} - -eval_config: { - metrics_set: ['coco_detection_metrics', 'coco_mask_metrics'] - num_examples: 50 - # Note: The below line limits the evaluation process to 10 evaluations. - # Remove the below line to evaluate indefinitely. - max_evals: 1 - num_visualizations: 50 - eval_interval_secs: 120 -} - -eval_input_reader: { - tf_record_input_reader { - input_path: "/home/mehdisharif/data/coco/output2017/coco_val.record" - } - label_map_path: "/home/mehdisharif/data/coco/output2017/mscoco_label_map.pbtxt" - load_instance_masks: true - mask_type: PNG_MASKS - shuffle: false - num_readers: 1 -} diff --git a/research/mlperf_object_detection/Mask_RCNN/configs/mask_rcnn_resnet50_atrous_coco.config b/research/mlperf_object_detection/Mask_RCNN/configs/mask_rcnn_resnet50_atrous_coco.config deleted file mode 100644 index 17c8bd5e7..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/configs/mask_rcnn_resnet50_atrous_coco.config +++ /dev/null @@ -1,169 +0,0 @@ -# Mask R-CNN with Resnet-50 (v1), Atrous version -# Configured for MSCOCO Dataset. -# Users should configure the fine_tune_checkpoint field in the train config as -# well as the label_map_path and input_path fields in the train_input_reader and -# eval_input_reader. Search for "PATH_TO_BE_CONFIGURED" to find the fields that -# should be configured. - -model { - faster_rcnn { - num_classes: 90 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 800 - max_dimension: 1365 - } - } - number_of_stages: 3 - feature_extractor { - type: 'faster_rcnn_resnet50' - first_stage_features_stride: 8 - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 8 - width_stride: 8 - } - } - first_stage_atrous_rate: 2 - first_stage_box_predictor_conv_hyperparams { - op: CONV - regularizer { - l2_regularizer { - weight: 0.0 - } - } - initializer { - truncated_normal_initializer { - stddev: 0.01 - } - } - } - first_stage_nms_score_threshold: 0.0 - first_stage_nms_iou_threshold: 0.7 - first_stage_max_proposals: 300 - first_stage_localization_loss_weight: 2.0 - first_stage_objectness_loss_weight: 1.0 - initial_crop_size: 14 - maxpool_kernel_size: 2 - maxpool_stride: 2 - second_stage_box_predictor { - mask_rcnn_box_predictor { - use_dropout: false - dropout_keep_probability: 1.0 - predict_instance_masks: true - mask_height: 33 - mask_width: 33 - mask_prediction_conv_depth: 0 - mask_prediction_num_conv_layers: 4 - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - weight: 0.0 - } - } - initializer { - variance_scaling_initializer { - factor: 1.0 - uniform: true - mode: FAN_AVG - } - } - } - conv_hyperparams { - op: CONV - regularizer { - l2_regularizer { - weight: 0.0 - } - } - initializer { - truncated_normal_initializer { - stddev: 0.01 - } - } - } - } - } - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.0 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - score_converter: SOFTMAX - } - second_stage_localization_loss_weight: 2.0 - second_stage_classification_loss_weight: 1.0 - second_stage_mask_prediction_loss_weight: 4.0 - } -} - -train_config: { - batch_size: 2 - optimizer { - momentum_optimizer: { - learning_rate: { - manual_step_learning_rate { - initial_learning_rate: 0.0003 - schedule { - step: 900000 - learning_rate: .00003 - } - schedule { - step: 1200000 - learning_rate: .000003 - } - } - } - momentum_optimizer_value: 0.9 - } - use_moving_average: false - } - gradient_clipping_by_norm: 10.0 - #fine_tune_checkpoint: "" - from_detection_checkpoint: false - # Note: The below line limits the training process to 200K steps, which we - # empirically found to be sufficient enough to train the pets dataset. This - # effectively bypasses the learning rate schedule (the learning rate will - # never decay). Remove the below line to train indefinitely. - #num_steps: 200000 - data_augmentation_options { - random_horizontal_flip { - } - } -} - -train_input_reader: { - tf_record_input_reader { - input_path: "PATH_TO_BE_CONFIGURED/coco_train.record" - } - label_map_path: "PATH_TO_BE_CONFIGURED/mscoco_label_map.pbtxt" - load_instance_masks: true - mask_type: PNG_MASKS -} - -eval_config: { - metrics_set: ['coco_detection_metrics', 'coco_mask_metrics'] - num_examples: 50 - # Note: The below line limits the evaluation process to 10 evaluations. - # Remove the below line to evaluate indefinitely. - max_evals: 1 - num_visualizations: 50 - eval_interval_secs: 120 -} - -eval_input_reader: { - tf_record_input_reader { - input_path: "PATH_TO_BE_CONFIGURED/coco_val.record" - } - label_map_path: "PATH_TO_BE_CONFIGURED/mscoco_label_map.pbtxt" - load_instance_masks: true - mask_type: PNG_MASKS - shuffle: true - num_readers: 1 -} diff --git a/research/mlperf_object_detection/Mask_RCNN/mask_rcnn_run_loop.py b/research/mlperf_object_detection/Mask_RCNN/mask_rcnn_run_loop.py deleted file mode 100644 index 70c9185c9..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/mask_rcnn_run_loop.py +++ /dev/null @@ -1,243 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Training and evaluation for Mask_RCNN. - - This module repeatedly runs 1 training epoch and then evaluation - ##add explanation for all the options!!!!!!! -""" - -import functools -import json -import os - -from object_detection import evaluator -from object_detection import trainer -from object_detection.builders import dataset_builder -from object_detection.builders import graph_rewriter_builder -from object_detection.builders import model_builder -from object_detection.utils import config_util -from object_detection.utils import dataset_util -from object_detection.utils import label_map_util - -import tensorflow as tf - -tf.logging.set_verbosity(tf.logging.INFO) - -flags = tf.app.flags -flags.DEFINE_string('master', '', 'Name of the TensorFlow master to use.') -flags.DEFINE_integer('task', 0, 'task id') -flags.DEFINE_integer('num_clones', 1, 'Number of clones to deploy per worker.') -flags.DEFINE_boolean('clone_on_cpu', False, - 'Force clones to be deployed on CPU. Note that even if ' - 'set to False (allowing ops to run on gpu), some ops may ' - 'still be run on the CPU if they have no GPU kernel.') -flags.DEFINE_integer('worker_replicas', 1, 'Number of worker+trainer ' - 'replicas.') -flags.DEFINE_integer('parameter_server_tasks', 0, - 'Number of parameter server tasks. If None, does not use ' - 'a parameter server.') -flags.DEFINE_string('train_dir', '', - 'Directory to save the checkpoints and training summaries.') - -flags.DEFINE_string('pipeline_config_path', '', - 'Path to a pipeline_pb2.TrainEvalPipelineConfig config ' - 'file. If provided, other configs are ignored') - -flags.DEFINE_boolean('eval_training_data', False, - 'If training data should be evaluated for this job.') - -flags.DEFINE_string('eval_dir', '', - 'Directory to write eval summaries to.') - -flags.DEFINE_boolean('run_once', False, 'Option to only run a single pass of ' - 'evaluation. Overrides the `max_evals`' - ' parameter in the provided config.') -flags.DEFINE_float('box_min_ap', -1, 'Option to run until the box average' - 'precision reaches this number') -flags.DEFINE_float('mask_min_ap', -1, 'Option to run until the mask average' - 'precision reaches this number') -flags.DEFINE_integer('epochs_between_evals', 1, 'Number of training epochs to ' - 'run before running eval.') -FLAGS = flags.FLAGS - - -def stopping_criteria_met(eval_metrics, mask_min_ap, box_min_ap): - """Returns true if both of the min precision criteria are met in the given - evaluation metrics. - - Args: - eval_metrics: dict of metrics names as keys and their corresponding values, - containing "DetectionMasks_Precision/mAP", and - "DetectionBoxes_Precision/mAP" fields. - mask_min_ap: minimum desired mask average precision, will be ignored if -1 - box_min_ap: minimum desired box average precision, will be ignored if -1 - - Returns: - True if non -1 criteria are met, false o.w. - """ - assert mask_min_ap == -1 or 0 < mask_min_ap < 1 - assert box_min_ap == -1 or 0 < box_min_ap < 1 - try: - mask_mAP_reached = eval_metrics['DetectionMasks_Precision/mAP'] - box_mAP_reached = eval_metrics['DetectionBoxes_Precision/mAP'] - except KeyError as err: - raise Exception('eval_metrics dict does not contain the mAP field') from err - - return (mask_min_ap == -1 or mask_mAP_reached > mask_min_ap) & \ - (box_min_ap == -1 or box_mAP_reached > box_min_ap) & \ - (mask_min_ap != -1 or box_min_ap != -1) - - -def main(_): - assert FLAGS.train_dir, '`train_dir` is missing.' - assert FLAGS.pipeline_config_path, '`pipeline_config_path` is missing' - assert FLAGS.eval_dir, '`eval_dir` is missing.' - - configs = config_util.get_configs_from_pipeline_file( - FLAGS.pipeline_config_path) - if FLAGS.task == 0: - tf.gfile.MakeDirs(FLAGS.train_dir) - tf.gfile.Copy(FLAGS.pipeline_config_path, - os.path.join(FLAGS.train_dir, 'pipeline.config'), - overwrite=True) - - tf.gfile.MakeDirs(FLAGS.eval_dir) - tf.gfile.Copy(FLAGS.pipeline_config_path, - os.path.join(FLAGS.eval_dir, 'pipeline.config'), - overwrite=True) - - model_config = configs['model'] - - train_config = configs['train_config'] - train_input_config = configs['train_input_config'] - - eval_config = configs['eval_config'] - if FLAGS.eval_training_data: - eval_input_config = configs['train_input_config'] - else: - eval_input_config = configs['eval_input_config'] - - # setting to run evaluation after EPOCHS_BETWEEN_EVALS epochs of training. - # total number of training is set to total_num_epochs provided in the config - if train_config.num_steps: - total_num_epochs = train_config.num_steps - train_config.num_steps = FLAGS.epochs_between_evals - total_training_cycle = total_num_epochs // train_config.num_steps - else: - # TODO(mehdi): make it run indef - total_num_epochs = 20000000 - train_config.num_steps = FLAGS.epochs_between_evals - total_training_cycle = total_num_epochs // train_config.num_steps - - train_model_fn = functools.partial(model_builder.build, - model_config=model_config, - is_training=True) - eval_model_fn = functools.partial(model_builder.build, - model_config=model_config, - is_training=False) - - def get_next(config): - return dataset_util.make_initializable_iterator( - dataset_builder.build(config)).get_next() - - # functions to create a tensor input dictionary for both training & evaluation - train_input_dict_fn = functools.partial(get_next, train_input_config) - eval_input_dict_fn = functools.partial(get_next, eval_input_config) - - # If not explicitly specified in the constructor and the TF_CONFIG - # environment variable is present, load cluster_spec from TF_CONFIG. - env = json.loads(os.environ.get('TF_CONFIG', '{}')) - cluster_data = env.get('cluster', None) - cluster = tf.train.ClusterSpec(cluster_data) if cluster_data else None - task_data = env.get('task', {'type': 'master', 'index': 0}) - task_info = type('TaskSpec', (object,), task_data) - - # Parameters for a single worker. - parameter_server_tasks = 0 - worker_replicas = 1 - worker_job_name = 'lonely_worker' - task = 0 - is_chief = True - master = '' - - if cluster_data and 'worker' in cluster_data: - # Number of total worker replicas include "worker"s and the "master". - worker_replicas = len(cluster_data['worker']) + 1 - if cluster_data and 'ps' in cluster_data: - parameter_server_tasks = len(cluster_data['ps']) - - if worker_replicas > 1 and parameter_server_tasks < 1: - raise ValueError('At least 1 ps task is needed for distributed training.') - - if worker_replicas >= 1 and parameter_server_tasks > 0: - # Set up distributed training. - server = tf.train.Server(tf.train.ClusterSpec(cluster), protocol='grpc', - job_name=task_info.type, - task_index=task_info.index) - if task_info.type == 'ps': - server.join() - return - - worker_job_name = '%s/task:%d' % (task_info.type, task_info.index) - task = task_info.index - is_chief = (task_info.type == 'master') - master = server.target - - label_map = label_map_util.load_labelmap(eval_input_config.label_map_path) - max_num_classes = max([item.id for item in label_map.item]) - categories = label_map_util.convert_label_map_to_categories(label_map, - max_num_classes) - - if FLAGS.run_once: - eval_config.max_evals = 1 - - train_graph_rewriter_fn = eval_graph_rewriter_fn = None - if 'graph_rewriter_config' in configs: - train_graph_rewriter_fn = graph_rewriter_builder.build( - configs['graph_rewriter_config'], is_training=True) - eval_graph_rewriter_fn = graph_rewriter_builder.build( - configs['eval_rewriter_config'], is_training=False) - - def train(): - return trainer.train(create_tensor_dict_fn=train_input_dict_fn, - create_model_fn=train_model_fn, - train_config=train_config, master=master, task=task, - num_clones=FLAGS.num_clones, - worker_replicas=worker_replicas, - clone_on_cpu=FLAGS.clone_on_cpu, - ps_tasks=parameter_server_tasks, - worker_job_name=worker_job_name, - is_chief=is_chief, train_dir=FLAGS.train_dir, - graph_hook_fn=train_graph_rewriter_fn) - - def evaluate(): - return evaluator.evaluate(eval_input_dict_fn, eval_model_fn, eval_config, - categories, FLAGS.train_dir, FLAGS.eval_dir, - graph_hook_fn=eval_graph_rewriter_fn) - - for cycle_index in range(total_training_cycle): - tf.logging.info('Starting a training cycle: %d/%d', - cycle_index, total_training_cycle) - train() - tf.logging.info('Starting to evaluate.') - eval_metrics = evaluate() - if stopping_criteria_met(eval_metrics, FLAGS.mask_min_ap, FLAGS.box_min_ap): - tf.logging.info('Stopping criteria met. Training stopped') - break - - -if __name__ == '__main__': - tf.app.run() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/CONTRIBUTING.md b/research/mlperf_object_detection/Mask_RCNN/object_detection/CONTRIBUTING.md deleted file mode 100644 index e3d87e3ce..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/CONTRIBUTING.md +++ /dev/null @@ -1,13 +0,0 @@ -# Contributing to the Tensorflow Object Detection API - -Patches to Tensorflow Object Detection API are welcome! - -We require contributors to fill out either the individual or corporate -Contributor License Agreement (CLA). - - * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html). - * If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html). - -Please follow the -[Tensorflow contributing guidelines](https://github.com/tensorflow/tensorflow/blob/master/CONTRIBUTING.md) -when submitting pull requests. diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/README.md b/research/mlperf_object_detection/Mask_RCNN/object_detection/README.md deleted file mode 100644 index 52bf3565e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/README.md +++ /dev/null @@ -1,190 +0,0 @@ - -# Tensorflow Object Detection API -Creating accurate machine learning models capable of localizing and identifying -multiple objects in a single image remains a core challenge in computer vision. -The TensorFlow Object Detection API is an open source framework built on top of -TensorFlow that makes it easy to construct, train and deploy object detection -models. At Google we’ve certainly found this codebase to be useful for our -computer vision needs, and we hope that you will as well. -

- -

-Contributions to the codebase are welcome and we would love to hear back from -you if you find this API useful. Finally if you use the Tensorflow Object -Detection API for a research publication, please consider citing: - -``` -"Speed/accuracy trade-offs for modern convolutional object detectors." -Huang J, Rathod V, Sun C, Zhu M, Korattikara A, Fathi A, Fischer I, Wojna Z, -Song Y, Guadarrama S, Murphy K, CVPR 2017 -``` -\[[link](https://arxiv.org/abs/1611.10012)\]\[[bibtex]( -https://scholar.googleusercontent.com/scholar.bib?q=info:l291WsrB-hQJ:scholar.google.com/&output=citation&scisig=AAGBfm0AAAAAWUIIlnPZ_L9jxvPwcC49kDlELtaeIyU-&scisf=4&ct=citation&cd=-1&hl=en&scfhb=1)\] - -

- -

- -## Maintainers - -* Jonathan Huang, github: [jch1](https://github.com/jch1) -* Vivek Rathod, github: [tombstone](https://github.com/tombstone) -* Ronny Votel, github: [ronnyvotel](https://github.com/ronnyvotel) -* Derek Chow, github: [derekjchow](https://github.com/derekjchow) -* Chen Sun, github: [jesu9](https://github.com/jesu9) -* Menglong Zhu, github: [dreamdragon](https://github.com/dreamdragon) -* Alireza Fathi, github: [afathi3](https://github.com/afathi3) -* Zhichao Lu, github: [pkulzc](https://github.com/pkulzc) - - -## Table of contents - -Quick Start: - - * - Quick Start: Jupyter notebook for off-the-shelf inference
- * Quick Start: Training a pet detector
- -Setup: - - * Installation
- * - Configuring an object detection pipeline
- * Preparing inputs
- -Running: - - * Running locally
- * Running on the cloud
- -Extras: - - * Tensorflow detection model zoo
- * - Exporting a trained model for inference
- * - Defining your own model architecture
- * - Bringing in your own dataset
- * - Supported object detection evaluation protocols
- * - Inference and evaluation on the Open Images dataset
- * - Run an instance segmentation model
- -## Getting Help - -To get help with issues you may encounter using the Tensorflow Object Detection -API, create a new question on [StackOverflow](https://stackoverflow.com/) with -the tags "tensorflow" and "object-detection". - -Please report bugs (actually broken code, not usage questions) to the -tensorflow/models GitHub -[issue tracker](https://github.com/tensorflow/models/issues), prefixing the -issue name with "object_detection". - -Please check [FAQ](g3doc/faq.md) for frequently asked questions before -reporting an issue. - - -## Release information - -### April 30, 2018 - -We have released a Faster R-CNN detector with ResNet-101 feature extractor trained on [AVA](https://research.google.com/ava/) v2.1. -Compared with other commonly used object detectors, it changes the action classification loss function to per-class Sigmoid loss to handle boxes with multiple labels. -The model is trained on the training split of AVA v2.1 for 1.5M iterations, it achieves mean AP of 11.25% over 60 classes on the validation split of AVA v2.1. -For more details please refer to this [paper](https://arxiv.org/abs/1705.08421). - -Thanks to contributors: Chen Sun, David Ross - -### April 2, 2018 - -Supercharge your mobile phones with the next generation mobile object detector! -We are adding support for MobileNet V2 with SSDLite presented in -[MobileNetV2: Inverted Residuals and Linear Bottlenecks](https://arxiv.org/abs/1801.04381). -This model is 35% faster than Mobilenet V1 SSD on a Google Pixel phone CPU (200ms vs. 270ms) at the same accuracy. -Along with the model definition, we are also releasing a model checkpoint trained on the COCO dataset. - -Thanks to contributors: Menglong Zhu, Mark Sandler, Zhichao Lu, Vivek Rathod, Jonathan Huang - -### February 9, 2018 - -We now support instance segmentation!! In this API update we support a number of instance segmentation models similar to those discussed in the [Mask R-CNN paper](https://arxiv.org/abs/1703.06870). For further details refer to -[our slides](http://presentations.cocodataset.org/Places17-GMRI.pdf) from the 2017 Coco + Places Workshop. -Refer to the section on [Running an Instance Segmentation Model](g3doc/instance_segmentation.md) for instructions on how to configure a model -that predicts masks in addition to object bounding boxes. - -Thanks to contributors: Alireza Fathi, Zhichao Lu, Vivek Rathod, Ronny Votel, Jonathan Huang - -### November 17, 2017 - -As a part of the Open Images V3 release we have released: - -* An implementation of the Open Images evaluation metric and the [protocol](g3doc/evaluation_protocols.md#open-images). -* Additional tools to separate inference of detection and evaluation (see [this tutorial](g3doc/oid_inference_and_evaluation.md)). -* A new detection model trained on the Open Images V2 data release (see [Open Images model](g3doc/detection_model_zoo.md#open-images-models)). - -See more information on the [Open Images website](https://github.com/openimages/dataset)! - -Thanks to contributors: Stefan Popov, Alina Kuznetsova - -### November 6, 2017 - -We have re-released faster versions of our (pre-trained) models in the -model zoo. In addition to what -was available before, we are also adding Faster R-CNN models trained on COCO -with Inception V2 and Resnet-50 feature extractors, as well as a Faster R-CNN -with Resnet-101 model trained on the KITTI dataset. - -Thanks to contributors: Jonathan Huang, Vivek Rathod, Derek Chow, -Tal Remez, Chen Sun. - -### October 31, 2017 - -We have released a new state-of-the-art model for object detection using -the Faster-RCNN with the -[NASNet-A image featurization](https://arxiv.org/abs/1707.07012). This -model achieves mAP of 43.1% on the test-dev validation dataset for COCO, -improving on the best available model in the zoo by 6% in terms -of absolute mAP. - -Thanks to contributors: Barret Zoph, Vijay Vasudevan, Jonathon Shlens, Quoc Le - -### August 11, 2017 - -We have released an update to the [Android Detect -demo](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android) -which will now run models trained using the Tensorflow Object -Detection API on an Android device. By default, it currently runs a -frozen SSD w/Mobilenet detector trained on COCO, but we encourage -you to try out other detection models! - -Thanks to contributors: Jonathan Huang, Andrew Harp - - -### June 15, 2017 - -In addition to our base Tensorflow detection model definitions, this -release includes: - -* A selection of trainable detection models, including: - * Single Shot Multibox Detector (SSD) with MobileNet, - * SSD with Inception V2, - * Region-Based Fully Convolutional Networks (R-FCN) with Resnet 101, - * Faster RCNN with Resnet 101, - * Faster RCNN with Inception Resnet v2 -* Frozen weights (trained on the COCO dataset) for each of the above models to - be used for out-of-the-box inference purposes. -* A [Jupyter notebook](object_detection_tutorial.ipynb) for performing - out-of-the-box inference with one of our released models -* Convenient [local training](g3doc/running_locally.md) scripts as well as - distributed training and evaluation pipelines via - [Google Cloud](g3doc/running_on_cloud.md). - - -Thanks to contributors: Jonathan Huang, Vivek Rathod, Derek Chow, -Chen Sun, Menglong Zhu, Matthew Tang, Anoop Korattikara, Alireza Fathi, Ian Fischer, Zbigniew Wojna, Yang Song, Sergio Guadarrama, Jasper Uijlings, -Viacheslav Kovalevskyi, Kevin Murphy - diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/__init__.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/__init__.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/grid_anchor_generator.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/grid_anchor_generator.py deleted file mode 100644 index ba43f0135..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/grid_anchor_generator.py +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Generates grid anchors on the fly as used in Faster RCNN. - -Generates grid anchors on the fly as described in: -"Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks" -Shaoqing Ren, Kaiming He, Ross Girshick, and Jian Sun. -""" - -import tensorflow as tf - -from object_detection.core import anchor_generator -from object_detection.core import box_list -from object_detection.utils import ops - - -class GridAnchorGenerator(anchor_generator.AnchorGenerator): - """Generates a grid of anchors at given scales and aspect ratios.""" - - def __init__(self, - scales=(0.5, 1.0, 2.0), - aspect_ratios=(0.5, 1.0, 2.0), - base_anchor_size=None, - anchor_stride=None, - anchor_offset=None): - """Constructs a GridAnchorGenerator. - - Args: - scales: a list of (float) scales, default=(0.5, 1.0, 2.0) - aspect_ratios: a list of (float) aspect ratios, default=(0.5, 1.0, 2.0) - base_anchor_size: base anchor size as height, width ( - (length-2 float32 list or tensor, default=[256, 256]) - anchor_stride: difference in centers between base anchors for adjacent - grid positions (length-2 float32 list or tensor, - default=[16, 16]) - anchor_offset: center of the anchor with scale and aspect ratio 1 for the - upper left element of the grid, this should be zero for - feature networks with only VALID padding and even receptive - field size, but may need additional calculation if other - padding is used (length-2 float32 list or tensor, - default=[0, 0]) - """ - # Handle argument defaults - if base_anchor_size is None: - base_anchor_size = [256, 256] - base_anchor_size = tf.to_float(tf.convert_to_tensor(base_anchor_size)) - if anchor_stride is None: - anchor_stride = [16, 16] - anchor_stride = tf.to_float(tf.convert_to_tensor(anchor_stride)) - if anchor_offset is None: - anchor_offset = [0, 0] - anchor_offset = tf.to_float(tf.convert_to_tensor(anchor_offset)) - - self._scales = scales - self._aspect_ratios = aspect_ratios - self._base_anchor_size = base_anchor_size - self._anchor_stride = anchor_stride - self._anchor_offset = anchor_offset - - def name_scope(self): - return 'GridAnchorGenerator' - - def num_anchors_per_location(self): - """Returns the number of anchors per spatial location. - - Returns: - a list of integers, one for each expected feature map to be passed to - the `generate` function. - """ - return [len(self._scales) * len(self._aspect_ratios)] - - def _generate(self, feature_map_shape_list): - """Generates a collection of bounding boxes to be used as anchors. - - Args: - feature_map_shape_list: list of pairs of convnet layer resolutions in the - format [(height_0, width_0)]. For example, setting - feature_map_shape_list=[(8, 8)] asks for anchors that correspond - to an 8x8 layer. For this anchor generator, only lists of length 1 are - allowed. - - Returns: - boxes_list: a list of BoxLists each holding anchor boxes corresponding to - the input feature map shapes. - - Raises: - ValueError: if feature_map_shape_list, box_specs_list do not have the same - length. - ValueError: if feature_map_shape_list does not consist of pairs of - integers - """ - if not (isinstance(feature_map_shape_list, list) - and len(feature_map_shape_list) == 1): - raise ValueError('feature_map_shape_list must be a list of length 1.') - if not all([isinstance(list_item, tuple) and len(list_item) == 2 - for list_item in feature_map_shape_list]): - raise ValueError('feature_map_shape_list must be a list of pairs.') - grid_height, grid_width = feature_map_shape_list[0] - scales_grid, aspect_ratios_grid = ops.meshgrid(self._scales, - self._aspect_ratios) - scales_grid = tf.reshape(scales_grid, [-1]) - aspect_ratios_grid = tf.reshape(aspect_ratios_grid, [-1]) - anchors = tile_anchors(grid_height, - grid_width, - scales_grid, - aspect_ratios_grid, - self._base_anchor_size, - self._anchor_stride, - self._anchor_offset) - - num_anchors = anchors.num_boxes_static() - if num_anchors is None: - num_anchors = anchors.num_boxes() - anchor_indices = tf.zeros([num_anchors]) - anchors.add_field('feature_map_index', anchor_indices) - return [anchors] - - -def tile_anchors(grid_height, - grid_width, - scales, - aspect_ratios, - base_anchor_size, - anchor_stride, - anchor_offset): - """Create a tiled set of anchors strided along a grid in image space. - - This op creates a set of anchor boxes by placing a "basis" collection of - boxes with user-specified scales and aspect ratios centered at evenly - distributed points along a grid. The basis collection is specified via the - scale and aspect_ratios arguments. For example, setting scales=[.1, .2, .2] - and aspect ratios = [2,2,1/2] means that we create three boxes: one with scale - .1, aspect ratio 2, one with scale .2, aspect ratio 2, and one with scale .2 - and aspect ratio 1/2. Each box is multiplied by "base_anchor_size" before - placing it over its respective center. - - Grid points are specified via grid_height, grid_width parameters as well as - the anchor_stride and anchor_offset parameters. - - Args: - grid_height: size of the grid in the y direction (int or int scalar tensor) - grid_width: size of the grid in the x direction (int or int scalar tensor) - scales: a 1-d (float) tensor representing the scale of each box in the - basis set. - aspect_ratios: a 1-d (float) tensor representing the aspect ratio of each - box in the basis set. The length of the scales and aspect_ratios tensors - must be equal. - base_anchor_size: base anchor size as [height, width] - (float tensor of shape [2]) - anchor_stride: difference in centers between base anchors for adjacent grid - positions (float tensor of shape [2]) - anchor_offset: center of the anchor with scale and aspect ratio 1 for the - upper left element of the grid, this should be zero for - feature networks with only VALID padding and even receptive - field size, but may need some additional calculation if other - padding is used (float tensor of shape [2]) - Returns: - a BoxList holding a collection of N anchor boxes - """ - ratio_sqrts = tf.sqrt(aspect_ratios) - heights = scales / ratio_sqrts * base_anchor_size[0] - widths = scales * ratio_sqrts * base_anchor_size[1] - - # Get a grid of box centers - y_centers = tf.to_float(tf.range(grid_height)) - y_centers = y_centers * anchor_stride[0] + anchor_offset[0] - x_centers = tf.to_float(tf.range(grid_width)) - x_centers = x_centers * anchor_stride[1] + anchor_offset[1] - x_centers, y_centers = ops.meshgrid(x_centers, y_centers) - - widths_grid, x_centers_grid = ops.meshgrid(widths, x_centers) - heights_grid, y_centers_grid = ops.meshgrid(heights, y_centers) - bbox_centers = tf.stack([y_centers_grid, x_centers_grid], axis=3) - bbox_sizes = tf.stack([heights_grid, widths_grid], axis=3) - bbox_centers = tf.reshape(bbox_centers, [-1, 2]) - bbox_sizes = tf.reshape(bbox_sizes, [-1, 2]) - bbox_corners = _center_size_bbox_to_corners_bbox(bbox_centers, bbox_sizes) - return box_list.BoxList(bbox_corners) - - -def _center_size_bbox_to_corners_bbox(centers, sizes): - """Converts bbox center-size representation to corners representation. - - Args: - centers: a tensor with shape [N, 2] representing bounding box centers - sizes: a tensor with shape [N, 2] representing bounding boxes - - Returns: - corners: tensor with shape [N, 4] representing bounding boxes in corners - representation - """ - return tf.concat([centers - .5 * sizes, centers + .5 * sizes], 1) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/grid_anchor_generator_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/grid_anchor_generator_test.py deleted file mode 100644 index 8de74aa7e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/grid_anchor_generator_test.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.grid_anchor_generator.""" -import numpy as np -import tensorflow as tf - -from object_detection.anchor_generators import grid_anchor_generator -from object_detection.utils import test_case - - -class GridAnchorGeneratorTest(test_case.TestCase): - - def test_construct_single_anchor(self): - """Builds a 1x1 anchor grid to test the size of the output boxes.""" - def graph_fn(): - scales = [0.5, 1.0, 2.0] - aspect_ratios = [0.25, 1.0, 4.0] - anchor_offset = [7, -3] - anchor_generator = grid_anchor_generator.GridAnchorGenerator( - scales, aspect_ratios, anchor_offset=anchor_offset) - anchors_list = anchor_generator.generate(feature_map_shape_list=[(1, 1)]) - anchor_corners = anchors_list[0].get() - return (anchor_corners,) - exp_anchor_corners = [[-121, -35, 135, 29], [-249, -67, 263, 61], - [-505, -131, 519, 125], [-57, -67, 71, 61], - [-121, -131, 135, 125], [-249, -259, 263, 253], - [-25, -131, 39, 125], [-57, -259, 71, 253], - [-121, -515, 135, 509]] - anchor_corners_out = self.execute(graph_fn, []) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_anchor_grid(self): - def graph_fn(): - base_anchor_size = [10, 10] - anchor_stride = [19, 19] - anchor_offset = [0, 0] - scales = [0.5, 1.0, 2.0] - aspect_ratios = [1.0] - - anchor_generator = grid_anchor_generator.GridAnchorGenerator( - scales, - aspect_ratios, - base_anchor_size=base_anchor_size, - anchor_stride=anchor_stride, - anchor_offset=anchor_offset) - - anchors_list = anchor_generator.generate(feature_map_shape_list=[(2, 2)]) - anchor_corners = anchors_list[0].get() - return (anchor_corners,) - exp_anchor_corners = [[-2.5, -2.5, 2.5, 2.5], [-5., -5., 5., 5.], - [-10., -10., 10., 10.], [-2.5, 16.5, 2.5, 21.5], - [-5., 14., 5, 24], [-10., 9., 10, 29], - [16.5, -2.5, 21.5, 2.5], [14., -5., 24, 5], - [9., -10., 29, 10], [16.5, 16.5, 21.5, 21.5], - [14., 14., 24, 24], [9., 9., 29, 29]] - anchor_corners_out = self.execute(graph_fn, []) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_anchor_grid_with_dynamic_feature_map_shapes(self): - def graph_fn(feature_map_height, feature_map_width): - base_anchor_size = [10, 10] - anchor_stride = [19, 19] - anchor_offset = [0, 0] - scales = [0.5, 1.0, 2.0] - aspect_ratios = [1.0] - anchor_generator = grid_anchor_generator.GridAnchorGenerator( - scales, - aspect_ratios, - base_anchor_size=base_anchor_size, - anchor_stride=anchor_stride, - anchor_offset=anchor_offset) - - anchors_list = anchor_generator.generate( - feature_map_shape_list=[(feature_map_height, feature_map_width)]) - anchor_corners = anchors_list[0].get() - return (anchor_corners,) - - exp_anchor_corners = [[-2.5, -2.5, 2.5, 2.5], [-5., -5., 5., 5.], - [-10., -10., 10., 10.], [-2.5, 16.5, 2.5, 21.5], - [-5., 14., 5, 24], [-10., 9., 10, 29], - [16.5, -2.5, 21.5, 2.5], [14., -5., 24, 5], - [9., -10., 29, 10], [16.5, 16.5, 21.5, 21.5], - [14., 14., 24, 24], [9., 9., 29, 29]] - anchor_corners_out = self.execute_cpu(graph_fn, - [np.array(2, dtype=np.int32), - np.array(2, dtype=np.int32)]) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiple_grid_anchor_generator.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiple_grid_anchor_generator.py deleted file mode 100644 index bd785c171..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiple_grid_anchor_generator.py +++ /dev/null @@ -1,336 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Generates grid anchors on the fly corresponding to multiple CNN layers. - -Generates grid anchors on the fly corresponding to multiple CNN layers as -described in: -"SSD: Single Shot MultiBox Detector" -Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, Scott Reed, -Cheng-Yang Fu, Alexander C. Berg -(see Section 2.2: Choosing scales and aspect ratios for default boxes) -""" - -import numpy as np - -import tensorflow as tf - -from object_detection.anchor_generators import grid_anchor_generator -from object_detection.core import anchor_generator -from object_detection.core import box_list_ops - - -class MultipleGridAnchorGenerator(anchor_generator.AnchorGenerator): - """Generate a grid of anchors for multiple CNN layers.""" - - def __init__(self, - box_specs_list, - base_anchor_size=None, - anchor_strides=None, - anchor_offsets=None, - clip_window=None): - """Constructs a MultipleGridAnchorGenerator. - - To construct anchors, at multiple grid resolutions, one must provide a - list of feature_map_shape_list (e.g., [(8, 8), (4, 4)]), and for each grid - size, a corresponding list of (scale, aspect ratio) box specifications. - - For example: - box_specs_list = [[(.1, 1.0), (.1, 2.0)], # for 8x8 grid - [(.2, 1.0), (.3, 1.0), (.2, 2.0)]] # for 4x4 grid - - To support the fully convolutional setting, we pass grid sizes in at - generation time, while scale and aspect ratios are fixed at construction - time. - - Args: - box_specs_list: list of list of (scale, aspect ratio) pairs with the - outside list having the same number of entries as feature_map_shape_list - (which is passed in at generation time). - base_anchor_size: base anchor size as [height, width] - (length-2 float tensor, default=[1.0, 1.0]). - The height and width values are normalized to the - minimum dimension of the input height and width, so that - when the base anchor height equals the base anchor - width, the resulting anchor is square even if the input - image is not square. - anchor_strides: list of pairs of strides in pixels (in y and x directions - respectively). For example, setting anchor_strides=[(25, 25), (50, 50)] - means that we want the anchors corresponding to the first layer to be - strided by 25 pixels and those in the second layer to be strided by 50 - pixels in both y and x directions. If anchor_strides=None, they are set - to be the reciprocal of the corresponding feature map shapes. - anchor_offsets: list of pairs of offsets in pixels (in y and x directions - respectively). The offset specifies where we want the center of the - (0, 0)-th anchor to lie for each layer. For example, setting - anchor_offsets=[(10, 10), (20, 20)]) means that we want the - (0, 0)-th anchor of the first layer to lie at (10, 10) in pixel space - and likewise that we want the (0, 0)-th anchor of the second layer to - lie at (25, 25) in pixel space. If anchor_offsets=None, then they are - set to be half of the corresponding anchor stride. - clip_window: a tensor of shape [4] specifying a window to which all - anchors should be clipped. If clip_window is None, then no clipping - is performed. - - Raises: - ValueError: if box_specs_list is not a list of list of pairs - ValueError: if clip_window is not either None or a tensor of shape [4] - """ - if isinstance(box_specs_list, list) and all( - [isinstance(list_item, list) for list_item in box_specs_list]): - self._box_specs = box_specs_list - else: - raise ValueError('box_specs_list is expected to be a ' - 'list of lists of pairs') - if base_anchor_size is None: - base_anchor_size = tf.constant([256, 256], dtype=tf.float32) - self._base_anchor_size = base_anchor_size - self._anchor_strides = anchor_strides - self._anchor_offsets = anchor_offsets - if clip_window is not None and clip_window.get_shape().as_list() != [4]: - raise ValueError('clip_window must either be None or a shape [4] tensor') - self._clip_window = clip_window - self._scales = [] - self._aspect_ratios = [] - for box_spec in self._box_specs: - if not all([isinstance(entry, tuple) and len(entry) == 2 - for entry in box_spec]): - raise ValueError('box_specs_list is expected to be a ' - 'list of lists of pairs') - scales, aspect_ratios = zip(*box_spec) - self._scales.append(scales) - self._aspect_ratios.append(aspect_ratios) - - for arg, arg_name in zip([self._anchor_strides, self._anchor_offsets], - ['anchor_strides', 'anchor_offsets']): - if arg and not (isinstance(arg, list) and - len(arg) == len(self._box_specs)): - raise ValueError('%s must be a list with the same length ' - 'as self._box_specs' % arg_name) - if arg and not all([ - isinstance(list_item, tuple) and len(list_item) == 2 - for list_item in arg - ]): - raise ValueError('%s must be a list of pairs.' % arg_name) - - def name_scope(self): - return 'MultipleGridAnchorGenerator' - - def num_anchors_per_location(self): - """Returns the number of anchors per spatial location. - - Returns: - a list of integers, one for each expected feature map to be passed to - the Generate function. - """ - return [len(box_specs) for box_specs in self._box_specs] - - def _generate(self, feature_map_shape_list, im_height=1, im_width=1): - """Generates a collection of bounding boxes to be used as anchors. - - The number of anchors generated for a single grid with shape MxM where we - place k boxes over each grid center is k*M^2 and thus the total number of - anchors is the sum over all grids. In our box_specs_list example - (see the constructor docstring), we would place two boxes over each grid - point on an 8x8 grid and three boxes over each grid point on a 4x4 grid and - thus end up with 2*8^2 + 3*4^2 = 176 anchors in total. The layout of the - output anchors follows the order of how the grid sizes and box_specs are - specified (with box_spec index varying the fastest, followed by width - index, then height index, then grid index). - - Args: - feature_map_shape_list: list of pairs of convnet layer resolutions in the - format [(height_0, width_0), (height_1, width_1), ...]. For example, - setting feature_map_shape_list=[(8, 8), (7, 7)] asks for anchors that - correspond to an 8x8 layer followed by a 7x7 layer. - im_height: the height of the image to generate the grid for. If both - im_height and im_width are 1, the generated anchors default to - normalized coordinates, otherwise absolute coordinates are used for the - grid. - im_width: the width of the image to generate the grid for. If both - im_height and im_width are 1, the generated anchors default to - normalized coordinates, otherwise absolute coordinates are used for the - grid. - - Returns: - boxes_list: a list of BoxLists each holding anchor boxes corresponding to - the input feature map shapes. - - Raises: - ValueError: if feature_map_shape_list, box_specs_list do not have the same - length. - ValueError: if feature_map_shape_list does not consist of pairs of - integers - """ - if not (isinstance(feature_map_shape_list, list) - and len(feature_map_shape_list) == len(self._box_specs)): - raise ValueError('feature_map_shape_list must be a list with the same ' - 'length as self._box_specs') - if not all([isinstance(list_item, tuple) and len(list_item) == 2 - for list_item in feature_map_shape_list]): - raise ValueError('feature_map_shape_list must be a list of pairs.') - - im_height = tf.to_float(im_height) - im_width = tf.to_float(im_width) - - if not self._anchor_strides: - anchor_strides = [(1.0 / tf.to_float(pair[0]), 1.0 / tf.to_float(pair[1])) - for pair in feature_map_shape_list] - else: - anchor_strides = [(tf.to_float(stride[0]) / im_height, - tf.to_float(stride[1]) / im_width) - for stride in self._anchor_strides] - if not self._anchor_offsets: - anchor_offsets = [(0.5 * stride[0], 0.5 * stride[1]) - for stride in anchor_strides] - else: - anchor_offsets = [(tf.to_float(offset[0]) / im_height, - tf.to_float(offset[1]) / im_width) - for offset in self._anchor_offsets] - - for arg, arg_name in zip([anchor_strides, anchor_offsets], - ['anchor_strides', 'anchor_offsets']): - if not (isinstance(arg, list) and len(arg) == len(self._box_specs)): - raise ValueError('%s must be a list with the same length ' - 'as self._box_specs' % arg_name) - if not all([isinstance(list_item, tuple) and len(list_item) == 2 - for list_item in arg]): - raise ValueError('%s must be a list of pairs.' % arg_name) - - anchor_grid_list = [] - min_im_shape = tf.minimum(im_height, im_width) - scale_height = min_im_shape / im_height - scale_width = min_im_shape / im_width - base_anchor_size = [ - scale_height * self._base_anchor_size[0], - scale_width * self._base_anchor_size[1] - ] - for feature_map_index, (grid_size, scales, aspect_ratios, stride, - offset) in enumerate( - zip(feature_map_shape_list, self._scales, - self._aspect_ratios, anchor_strides, - anchor_offsets)): - tiled_anchors = grid_anchor_generator.tile_anchors( - grid_height=grid_size[0], - grid_width=grid_size[1], - scales=scales, - aspect_ratios=aspect_ratios, - base_anchor_size=base_anchor_size, - anchor_stride=stride, - anchor_offset=offset) - if self._clip_window is not None: - tiled_anchors = box_list_ops.clip_to_window( - tiled_anchors, self._clip_window, filter_nonoverlapping=False) - num_anchors_in_layer = tiled_anchors.num_boxes_static() - if num_anchors_in_layer is None: - num_anchors_in_layer = tiled_anchors.num_boxes() - anchor_indices = feature_map_index * tf.ones([num_anchors_in_layer]) - tiled_anchors.add_field('feature_map_index', anchor_indices) - anchor_grid_list.append(tiled_anchors) - - return anchor_grid_list - - -def create_ssd_anchors(num_layers=6, - min_scale=0.2, - max_scale=0.95, - scales=None, - aspect_ratios=(1.0, 2.0, 3.0, 1.0 / 2, 1.0 / 3), - interpolated_scale_aspect_ratio=1.0, - base_anchor_size=None, - anchor_strides=None, - anchor_offsets=None, - reduce_boxes_in_lowest_layer=True): - """Creates MultipleGridAnchorGenerator for SSD anchors. - - This function instantiates a MultipleGridAnchorGenerator that reproduces - ``default box`` construction proposed by Liu et al in the SSD paper. - See Section 2.2 for details. Grid sizes are assumed to be passed in - at generation time from finest resolution to coarsest resolution --- this is - used to (linearly) interpolate scales of anchor boxes corresponding to the - intermediate grid sizes. - - Anchors that are returned by calling the `generate` method on the returned - MultipleGridAnchorGenerator object are always in normalized coordinates - and clipped to the unit square: (i.e. all coordinates lie in [0, 1]x[0, 1]). - - Args: - num_layers: integer number of grid layers to create anchors for (actual - grid sizes passed in at generation time) - min_scale: scale of anchors corresponding to finest resolution (float) - max_scale: scale of anchors corresponding to coarsest resolution (float) - scales: As list of anchor scales to use. When not None and not empty, - min_scale and max_scale are not used. - aspect_ratios: list or tuple of (float) aspect ratios to place on each - grid point. - interpolated_scale_aspect_ratio: An additional anchor is added with this - aspect ratio and a scale interpolated between the scale for a layer - and the scale for the next layer (1.0 for the last layer). - This anchor is not included if this value is 0. - base_anchor_size: base anchor size as [height, width]. - The height and width values are normalized to the minimum dimension of the - input height and width, so that when the base anchor height equals the - base anchor width, the resulting anchor is square even if the input image - is not square. - anchor_strides: list of pairs of strides in pixels (in y and x directions - respectively). For example, setting anchor_strides=[(25, 25), (50, 50)] - means that we want the anchors corresponding to the first layer to be - strided by 25 pixels and those in the second layer to be strided by 50 - pixels in both y and x directions. If anchor_strides=None, they are set to - be the reciprocal of the corresponding feature map shapes. - anchor_offsets: list of pairs of offsets in pixels (in y and x directions - respectively). The offset specifies where we want the center of the - (0, 0)-th anchor to lie for each layer. For example, setting - anchor_offsets=[(10, 10), (20, 20)]) means that we want the - (0, 0)-th anchor of the first layer to lie at (10, 10) in pixel space - and likewise that we want the (0, 0)-th anchor of the second layer to lie - at (25, 25) in pixel space. If anchor_offsets=None, then they are set to - be half of the corresponding anchor stride. - reduce_boxes_in_lowest_layer: a boolean to indicate whether the fixed 3 - boxes per location is used in the lowest layer. - - Returns: - a MultipleGridAnchorGenerator - """ - if base_anchor_size is None: - base_anchor_size = [1.0, 1.0] - base_anchor_size = tf.constant(base_anchor_size, dtype=tf.float32) - box_specs_list = [] - if scales is None or not scales: - scales = [min_scale + (max_scale - min_scale) * i / (num_layers - 1) - for i in range(num_layers)] + [1.0] - else: - # Add 1.0 to the end, which will only be used in scale_next below and used - # for computing an interpolated scale for the largest scale in the list. - scales += [1.0] - - for layer, scale, scale_next in zip( - range(num_layers), scales[:-1], scales[1:]): - layer_box_specs = [] - if layer == 0 and reduce_boxes_in_lowest_layer: - layer_box_specs = [(0.1, 1.0), (scale, 2.0), (scale, 0.5)] - else: - for aspect_ratio in aspect_ratios: - layer_box_specs.append((scale, aspect_ratio)) - # Add one more anchor, with a scale between the current scale, and the - # scale for the next layer, with a specified aspect ratio (1.0 by - # default). - if interpolated_scale_aspect_ratio > 0.0: - layer_box_specs.append((np.sqrt(scale*scale_next), - interpolated_scale_aspect_ratio)) - box_specs_list.append(layer_box_specs) - - return MultipleGridAnchorGenerator(box_specs_list, base_anchor_size, - anchor_strides, anchor_offsets) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiple_grid_anchor_generator_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiple_grid_anchor_generator_test.py deleted file mode 100644 index 070d81d36..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiple_grid_anchor_generator_test.py +++ /dev/null @@ -1,289 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for anchor_generators.multiple_grid_anchor_generator_test.py.""" - -import numpy as np - -import tensorflow as tf - -from object_detection.anchor_generators import multiple_grid_anchor_generator as ag -from object_detection.utils import test_case - - -class MultipleGridAnchorGeneratorTest(test_case.TestCase): - - def test_construct_single_anchor_grid(self): - """Builds a 1x1 anchor grid to test the size of the output boxes.""" - def graph_fn(): - - box_specs_list = [[(.5, .25), (1.0, .25), (2.0, .25), - (.5, 1.0), (1.0, 1.0), (2.0, 1.0), - (.5, 4.0), (1.0, 4.0), (2.0, 4.0)]] - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([256, 256], dtype=tf.float32), - anchor_strides=[(16, 16)], - anchor_offsets=[(7, -3)]) - anchors_list = anchor_generator.generate(feature_map_shape_list=[(1, 1)]) - return anchors_list[0].get() - exp_anchor_corners = [[-121, -35, 135, 29], [-249, -67, 263, 61], - [-505, -131, 519, 125], [-57, -67, 71, 61], - [-121, -131, 135, 125], [-249, -259, 263, 253], - [-25, -131, 39, 125], [-57, -259, 71, 253], - [-121, -515, 135, 509]] - - anchor_corners_out = self.execute(graph_fn, []) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_anchor_grid(self): - def graph_fn(): - box_specs_list = [[(0.5, 1.0), (1.0, 1.0), (2.0, 1.0)]] - - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([10, 10], dtype=tf.float32), - anchor_strides=[(19, 19)], - anchor_offsets=[(0, 0)]) - anchors_list = anchor_generator.generate(feature_map_shape_list=[(2, 2)]) - return anchors_list[0].get() - exp_anchor_corners = [[-2.5, -2.5, 2.5, 2.5], [-5., -5., 5., 5.], - [-10., -10., 10., 10.], [-2.5, 16.5, 2.5, 21.5], - [-5., 14., 5, 24], [-10., 9., 10, 29], - [16.5, -2.5, 21.5, 2.5], [14., -5., 24, 5], - [9., -10., 29, 10], [16.5, 16.5, 21.5, 21.5], - [14., 14., 24, 24], [9., 9., 29, 29]] - - anchor_corners_out = self.execute(graph_fn, []) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_anchor_grid_non_square(self): - - def graph_fn(): - box_specs_list = [[(1.0, 1.0)]] - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, base_anchor_size=tf.constant([1, 1], - dtype=tf.float32)) - anchors_list = anchor_generator.generate(feature_map_shape_list=[( - tf.constant(1, dtype=tf.int32), tf.constant(2, dtype=tf.int32))]) - return anchors_list[0].get() - - exp_anchor_corners = [[0., -0.25, 1., 0.75], [0., 0.25, 1., 1.25]] - anchor_corners_out = self.execute(graph_fn, []) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_dynamic_size_anchor_grid(self): - - def graph_fn(height, width): - box_specs_list = [[(1.0, 1.0)]] - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, base_anchor_size=tf.constant([1, 1], - dtype=tf.float32)) - anchors_list = anchor_generator.generate(feature_map_shape_list=[(height, - width)]) - return anchors_list[0].get() - - exp_anchor_corners = [[0., -0.25, 1., 0.75], [0., 0.25, 1., 1.25]] - - anchor_corners_out = self.execute_cpu(graph_fn, - [np.array(1, dtype=np.int32), - np.array(2, dtype=np.int32)]) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_anchor_grid_normalized(self): - def graph_fn(): - box_specs_list = [[(1.0, 1.0)]] - - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, base_anchor_size=tf.constant([1, 1], - dtype=tf.float32)) - anchors_list = anchor_generator.generate( - feature_map_shape_list=[(tf.constant(1, dtype=tf.int32), tf.constant( - 2, dtype=tf.int32))], - im_height=320, - im_width=640) - return anchors_list[0].get() - - exp_anchor_corners = [[0., 0., 1., 0.5], [0., 0.5, 1., 1.]] - anchor_corners_out = self.execute(graph_fn, []) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_multiple_grids(self): - - def graph_fn(): - box_specs_list = [[(1.0, 1.0), (2.0, 1.0), (1.0, 0.5)], - [(1.0, 1.0), (1.0, 0.5)]] - - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([1.0, 1.0], dtype=tf.float32), - anchor_strides=[(.25, .25), (.5, .5)], - anchor_offsets=[(.125, .125), (.25, .25)]) - anchors_list = anchor_generator.generate(feature_map_shape_list=[(4, 4), ( - 2, 2)]) - return [anchors.get() for anchors in anchors_list] - # height and width of box with .5 aspect ratio - h = np.sqrt(2) - w = 1.0/np.sqrt(2) - exp_small_grid_corners = [[-.25, -.25, .75, .75], - [.25-.5*h, .25-.5*w, .25+.5*h, .25+.5*w], - [-.25, .25, .75, 1.25], - [.25-.5*h, .75-.5*w, .25+.5*h, .75+.5*w], - [.25, -.25, 1.25, .75], - [.75-.5*h, .25-.5*w, .75+.5*h, .25+.5*w], - [.25, .25, 1.25, 1.25], - [.75-.5*h, .75-.5*w, .75+.5*h, .75+.5*w]] - # only test first entry of larger set of anchors - exp_big_grid_corners = [[.125-.5, .125-.5, .125+.5, .125+.5], - [.125-1.0, .125-1.0, .125+1.0, .125+1.0], - [.125-.5*h, .125-.5*w, .125+.5*h, .125+.5*w],] - - anchor_corners_out = np.concatenate(self.execute(graph_fn, []), axis=0) - self.assertEquals(anchor_corners_out.shape, (56, 4)) - big_grid_corners = anchor_corners_out[0:3, :] - small_grid_corners = anchor_corners_out[48:, :] - self.assertAllClose(small_grid_corners, exp_small_grid_corners) - self.assertAllClose(big_grid_corners, exp_big_grid_corners) - - def test_construct_multiple_grids_with_clipping(self): - - def graph_fn(): - box_specs_list = [[(1.0, 1.0), (2.0, 1.0), (1.0, 0.5)], - [(1.0, 1.0), (1.0, 0.5)]] - - clip_window = tf.constant([0, 0, 1, 1], dtype=tf.float32) - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([1.0, 1.0], dtype=tf.float32), - clip_window=clip_window) - anchors_list = anchor_generator.generate(feature_map_shape_list=[(4, 4), ( - 2, 2)]) - return [anchors.get() for anchors in anchors_list] - # height and width of box with .5 aspect ratio - h = np.sqrt(2) - w = 1.0/np.sqrt(2) - exp_small_grid_corners = [[0, 0, .75, .75], - [0, 0, .25+.5*h, .25+.5*w], - [0, .25, .75, 1], - [0, .75-.5*w, .25+.5*h, 1], - [.25, 0, 1, .75], - [.75-.5*h, 0, 1, .25+.5*w], - [.25, .25, 1, 1], - [.75-.5*h, .75-.5*w, 1, 1]] - - anchor_corners_out = np.concatenate(self.execute(graph_fn, []), axis=0) - small_grid_corners = anchor_corners_out[48:, :] - self.assertAllClose(small_grid_corners, exp_small_grid_corners) - - def test_invalid_box_specs(self): - # not all box specs are pairs - box_specs_list = [[(1.0, 1.0), (2.0, 1.0), (1.0, 0.5)], - [(1.0, 1.0), (1.0, 0.5, .3)]] - with self.assertRaises(ValueError): - ag.MultipleGridAnchorGenerator(box_specs_list) - - # box_specs_list is not a list of lists - box_specs_list = [(1.0, 1.0), (2.0, 1.0), (1.0, 0.5)] - with self.assertRaises(ValueError): - ag.MultipleGridAnchorGenerator(box_specs_list) - - def test_invalid_generate_arguments(self): - box_specs_list = [[(1.0, 1.0), (2.0, 1.0), (1.0, 0.5)], - [(1.0, 1.0), (1.0, 0.5)]] - - # incompatible lengths with box_specs_list - with self.assertRaises(ValueError): - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([1.0, 1.0], dtype=tf.float32), - anchor_strides=[(.25, .25)], - anchor_offsets=[(.125, .125), (.25, .25)]) - anchor_generator.generate(feature_map_shape_list=[(4, 4), (2, 2)]) - with self.assertRaises(ValueError): - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([1.0, 1.0], dtype=tf.float32), - anchor_strides=[(.25, .25), (.5, .5)], - anchor_offsets=[(.125, .125), (.25, .25)]) - anchor_generator.generate(feature_map_shape_list=[(4, 4), (2, 2), (1, 1)]) - with self.assertRaises(ValueError): - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([1.0, 1.0], dtype=tf.float32), - anchor_strides=[(.5, .5)], - anchor_offsets=[(.25, .25)]) - anchor_generator.generate(feature_map_shape_list=[(4, 4), (2, 2)]) - - # not pairs - with self.assertRaises(ValueError): - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([1.0, 1.0], dtype=tf.float32), - anchor_strides=[(.25, .25), (.5, .5)], - anchor_offsets=[(.125, .125), (.25, .25)]) - anchor_generator.generate(feature_map_shape_list=[(4, 4, 4), (2, 2)]) - with self.assertRaises(ValueError): - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([1.0, 1.0], dtype=tf.float32), - anchor_strides=[(.25, .25, .1), (.5, .5)], - anchor_offsets=[(.125, .125), (.25, .25)]) - anchor_generator.generate(feature_map_shape_list=[(4, 4), (2, 2)]) - with self.assertRaises(ValueError): - anchor_generator = ag.MultipleGridAnchorGenerator( - box_specs_list, - base_anchor_size=tf.constant([1.0, 1.0], dtype=tf.float32), - anchor_strides=[(.25, .25), (.5, .5)], - anchor_offsets=[(.125, .125), (.25, .25)]) - anchor_generator.generate(feature_map_shape_list=[(4), (2, 2)]) - - -class CreateSSDAnchorsTest(test_case.TestCase): - - def test_create_ssd_anchors_returns_correct_shape(self): - - def graph_fn1(): - anchor_generator = ag.create_ssd_anchors( - num_layers=6, - min_scale=0.2, - max_scale=0.95, - aspect_ratios=(1.0, 2.0, 3.0, 1.0 / 2, 1.0 / 3), - reduce_boxes_in_lowest_layer=True) - - feature_map_shape_list = [(38, 38), (19, 19), (10, 10), - (5, 5), (3, 3), (1, 1)] - anchors_list = anchor_generator.generate( - feature_map_shape_list=feature_map_shape_list) - return [anchors.get() for anchors in anchors_list] - anchor_corners_out = np.concatenate(self.execute(graph_fn1, []), axis=0) - self.assertEquals(anchor_corners_out.shape, (7308, 4)) - - def graph_fn2(): - anchor_generator = ag.create_ssd_anchors( - num_layers=6, min_scale=0.2, max_scale=0.95, - aspect_ratios=(1.0, 2.0, 3.0, 1.0/2, 1.0/3), - reduce_boxes_in_lowest_layer=False) - - feature_map_shape_list = [(38, 38), (19, 19), (10, 10), - (5, 5), (3, 3), (1, 1)] - anchors_list = anchor_generator.generate( - feature_map_shape_list=feature_map_shape_list) - return [anchors.get() for anchors in anchors_list] - anchor_corners_out = np.concatenate(self.execute(graph_fn2, []), axis=0) - self.assertEquals(anchor_corners_out.shape, (11640, 4)) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiscale_grid_anchor_generator.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiscale_grid_anchor_generator.py deleted file mode 100644 index a8d227c77..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiscale_grid_anchor_generator.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Generates grid anchors on the fly corresponding to multiple CNN layers. - -Generates grid anchors on the fly corresponding to multiple CNN layers as -described in: -"Focal Loss for Dense Object Detection" (https://arxiv.org/abs/1708.02002) -T.-Y. Lin, P. Goyal, R. Girshick, K. He, P. Dollar -""" - -from object_detection.anchor_generators import grid_anchor_generator -from object_detection.core import anchor_generator -from object_detection.core import box_list_ops - - -class MultiscaleGridAnchorGenerator(anchor_generator.AnchorGenerator): - """Generate a grid of anchors for multiple CNN layers of different scale.""" - - def __init__(self, min_level, max_level, anchor_scale, aspect_ratios, - scales_per_octave, normalize_coordinates=True): - """Constructs a MultiscaleGridAnchorGenerator. - - To construct anchors, at multiple scale resolutions, one must provide a - the minimum level and maximum levels on a scale pyramid. To define the size - of anchor, the anchor scale is provided to decide the size relatively to the - stride of the corresponding feature map. The generator allows one pixel - location on feature map maps to multiple anchors, that have different aspect - ratios and intermediate scales. - - Args: - min_level: minimum level in feature pyramid. - max_level: maximum level in feature pyramid. - anchor_scale: anchor scale and feature stride define the size of the base - anchor on an image. For example, given a feature pyramid with strides - [2^3, ..., 2^7] and anchor scale 4. The base anchor size is - 4 * [2^3, ..., 2^7]. - aspect_ratios: list or tuple of (float) aspect ratios to place on each - grid point. - scales_per_octave: integer number of intermediate scales per scale octave. - normalize_coordinates: whether to produce anchors in normalized - coordinates. (defaults to True). - """ - self._anchor_grid_info = [] - self._aspect_ratios = aspect_ratios - self._scales_per_octave = scales_per_octave - self._normalize_coordinates = normalize_coordinates - - for level in range(min_level, max_level + 1): - anchor_stride = [2**level, 2**level] - scales = [] - aspects = [] - for scale in range(scales_per_octave): - scales.append(2**(float(scale) / scales_per_octave)) - for aspect_ratio in aspect_ratios: - aspects.append(aspect_ratio) - base_anchor_size = [2**level * anchor_scale, 2**level * anchor_scale] - self._anchor_grid_info.append({ - 'level': level, - 'info': [scales, aspects, base_anchor_size, anchor_stride] - }) - - def name_scope(self): - return 'MultiscaleGridAnchorGenerator' - - def num_anchors_per_location(self): - """Returns the number of anchors per spatial location. - - Returns: - a list of integers, one for each expected feature map to be passed to - the Generate function. - """ - return len(self._anchor_grid_info) * [ - len(self._aspect_ratios) * self._scales_per_octave] - - def _generate(self, feature_map_shape_list, im_height, im_width): - """Generates a collection of bounding boxes to be used as anchors. - - Currently we require the input image shape to be statically defined. That - is, im_height and im_width should be integers rather than tensors. - - Args: - feature_map_shape_list: list of pairs of convnet layer resolutions in the - format [(height_0, width_0), (height_1, width_1), ...]. For example, - setting feature_map_shape_list=[(8, 8), (7, 7)] asks for anchors that - correspond to an 8x8 layer followed by a 7x7 layer. - im_height: the height of the image to generate the grid for. - im_width: the width of the image to generate the grid for. - - Returns: - boxes_list: a list of BoxLists each holding anchor boxes corresponding to - the input feature map shapes. - Raises: - ValueError: if im_height and im_width are not integers. - """ - if not isinstance(im_height, int) or not isinstance(im_width, int): - raise ValueError('MultiscaleGridAnchorGenerator currently requires ' - 'input image shape to be statically defined.') - anchor_grid_list = [] - for feat_shape, grid_info in zip(feature_map_shape_list, - self._anchor_grid_info): - # TODO(rathodv) check the feature_map_shape_list is consistent with - # self._anchor_grid_info - level = grid_info['level'] - stride = 2**level - scales, aspect_ratios, base_anchor_size, anchor_stride = grid_info['info'] - feat_h = feat_shape[0] - feat_w = feat_shape[1] - anchor_offset = [0, 0] - if im_height % 2.0**level == 0: - anchor_offset[0] = stride / 2.0 - if im_width % 2.0**level == 0: - anchor_offset[1] = stride / 2.0 - ag = grid_anchor_generator.GridAnchorGenerator( - scales, - aspect_ratios, - base_anchor_size=base_anchor_size, - anchor_stride=anchor_stride, - anchor_offset=anchor_offset) - (anchor_grid,) = ag.generate(feature_map_shape_list=[(feat_h, feat_w)]) - - if self._normalize_coordinates: - anchor_grid = box_list_ops.to_normalized_coordinates( - anchor_grid, im_height, im_width, check_range=False) - anchor_grid_list.append(anchor_grid) - - return anchor_grid_list diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiscale_grid_anchor_generator_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiscale_grid_anchor_generator_test.py deleted file mode 100644 index c96bdae7b..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/anchor_generators/multiscale_grid_anchor_generator_test.py +++ /dev/null @@ -1,258 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for anchor_generators.multiscale_grid_anchor_generator_test.py.""" -import numpy as np -import tensorflow as tf - -from object_detection.anchor_generators import multiscale_grid_anchor_generator as mg -from object_detection.utils import test_case - - -class MultiscaleGridAnchorGeneratorTest(test_case.TestCase): - - def test_construct_single_anchor(self): - min_level = 5 - max_level = 5 - anchor_scale = 4.0 - aspect_ratios = [1.0] - scales_per_octave = 1 - im_height = 64 - im_width = 64 - feature_map_shape_list = [(2, 2)] - exp_anchor_corners = [[-48, -48, 80, 80], - [-48, -16, 80, 112], - [-16, -48, 112, 80], - [-16, -16, 112, 112]] - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=False) - anchors_list = anchor_generator.generate( - feature_map_shape_list, im_height=im_height, im_width=im_width) - anchor_corners = anchors_list[0].get() - - with self.test_session(): - anchor_corners_out = anchor_corners.eval() - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_single_anchor_in_normalized_coordinates(self): - min_level = 5 - max_level = 5 - anchor_scale = 4.0 - aspect_ratios = [1.0] - scales_per_octave = 1 - im_height = 64 - im_width = 128 - feature_map_shape_list = [(2, 2)] - exp_anchor_corners = [[-48./64, -48./128, 80./64, 80./128], - [-48./64, -16./128, 80./64, 112./128], - [-16./64, -48./128, 112./64, 80./128], - [-16./64, -16./128, 112./64, 112./128]] - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=True) - anchors_list = anchor_generator.generate( - feature_map_shape_list, im_height=im_height, im_width=im_width) - anchor_corners = anchors_list[0].get() - - with self.test_session(): - anchor_corners_out = anchor_corners.eval() - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_num_anchors_per_location(self): - min_level = 5 - max_level = 6 - anchor_scale = 4.0 - aspect_ratios = [1.0, 2.0] - scales_per_octave = 3 - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=False) - self.assertEqual(anchor_generator.num_anchors_per_location(), [6, 6]) - - def test_construct_single_anchor_fails_with_tensor_image_size(self): - min_level = 5 - max_level = 5 - anchor_scale = 4.0 - aspect_ratios = [1.0] - scales_per_octave = 1 - im_height = tf.constant(64) - im_width = tf.constant(64) - feature_map_shape_list = [(2, 2)] - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=False) - with self.assertRaises(ValueError): - anchor_generator.generate( - feature_map_shape_list, im_height=im_height, im_width=im_width) - - def test_construct_single_anchor_with_odd_input_dimension(self): - - def graph_fn(): - min_level = 5 - max_level = 5 - anchor_scale = 4.0 - aspect_ratios = [1.0] - scales_per_octave = 1 - im_height = 65 - im_width = 65 - feature_map_shape_list = [(3, 3)] - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=False) - anchors_list = anchor_generator.generate( - feature_map_shape_list, im_height=im_height, im_width=im_width) - anchor_corners = anchors_list[0].get() - return (anchor_corners,) - anchor_corners_out = self.execute(graph_fn, []) - exp_anchor_corners = [[-64, -64, 64, 64], - [-64, -32, 64, 96], - [-64, 0, 64, 128], - [-32, -64, 96, 64], - [-32, -32, 96, 96], - [-32, 0, 96, 128], - [0, -64, 128, 64], - [0, -32, 128, 96], - [0, 0, 128, 128]] - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_single_anchor_on_two_feature_maps(self): - - def graph_fn(): - min_level = 5 - max_level = 6 - anchor_scale = 4.0 - aspect_ratios = [1.0] - scales_per_octave = 1 - im_height = 64 - im_width = 64 - feature_map_shape_list = [(2, 2), (1, 1)] - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=False) - anchors_list = anchor_generator.generate(feature_map_shape_list, - im_height=im_height, - im_width=im_width) - anchor_corners = [anchors.get() for anchors in anchors_list] - return anchor_corners - - anchor_corners_out = np.concatenate(self.execute(graph_fn, []), axis=0) - exp_anchor_corners = [[-48, -48, 80, 80], - [-48, -16, 80, 112], - [-16, -48, 112, 80], - [-16, -16, 112, 112], - [-96, -96, 160, 160]] - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_single_anchor_with_two_scales_per_octave(self): - - def graph_fn(): - min_level = 6 - max_level = 6 - anchor_scale = 4.0 - aspect_ratios = [1.0] - scales_per_octave = 2 - im_height = 64 - im_width = 64 - feature_map_shape_list = [(1, 1)] - - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=False) - anchors_list = anchor_generator.generate(feature_map_shape_list, - im_height=im_height, - im_width=im_width) - anchor_corners = [anchors.get() for anchors in anchors_list] - return anchor_corners - # There are 4 set of anchors in this configuration. The order is: - # [[2**0.0 intermediate scale + 1.0 aspect], - # [2**0.5 intermediate scale + 1.0 aspect]] - exp_anchor_corners = [[-96., -96., 160., 160.], - [-149.0193, -149.0193, 213.0193, 213.0193]] - - anchor_corners_out = self.execute(graph_fn, []) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_single_anchor_with_two_scales_per_octave_and_aspect(self): - def graph_fn(): - min_level = 6 - max_level = 6 - anchor_scale = 4.0 - aspect_ratios = [1.0, 2.0] - scales_per_octave = 2 - im_height = 64 - im_width = 64 - feature_map_shape_list = [(1, 1)] - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=False) - anchors_list = anchor_generator.generate(feature_map_shape_list, - im_height=im_height, - im_width=im_width) - anchor_corners = [anchors.get() for anchors in anchors_list] - return anchor_corners - # There are 4 set of anchors in this configuration. The order is: - # [[2**0.0 intermediate scale + 1.0 aspect], - # [2**0.5 intermediate scale + 1.0 aspect], - # [2**0.0 intermediate scale + 2.0 aspect], - # [2**0.5 intermediate scale + 2.0 aspect]] - - exp_anchor_corners = [[-96., -96., 160., 160.], - [-149.0193, -149.0193, 213.0193, 213.0193], - [-58.50967, -149.0193, 122.50967, 213.0193], - [-96., -224., 160., 288.]] - anchor_corners_out = self.execute(graph_fn, []) - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - def test_construct_single_anchors_on_feature_maps_with_dynamic_shape(self): - - def graph_fn(feature_map1_height, feature_map1_width, feature_map2_height, - feature_map2_width): - min_level = 5 - max_level = 6 - anchor_scale = 4.0 - aspect_ratios = [1.0] - scales_per_octave = 1 - im_height = 64 - im_width = 64 - feature_map_shape_list = [(feature_map1_height, feature_map1_width), - (feature_map2_height, feature_map2_width)] - anchor_generator = mg.MultiscaleGridAnchorGenerator( - min_level, max_level, anchor_scale, aspect_ratios, scales_per_octave, - normalize_coordinates=False) - anchors_list = anchor_generator.generate(feature_map_shape_list, - im_height=im_height, - im_width=im_width) - anchor_corners = [anchors.get() for anchors in anchors_list] - return anchor_corners - - anchor_corners_out = np.concatenate( - self.execute_cpu(graph_fn, [ - np.array(2, dtype=np.int32), - np.array(2, dtype=np.int32), - np.array(1, dtype=np.int32), - np.array(1, dtype=np.int32) - ]), - axis=0) - exp_anchor_corners = [[-48, -48, 80, 80], - [-48, -16, 80, 112], - [-16, -48, 112, 80], - [-16, -16, 112, 112], - [-96, -96, 160, 160]] - self.assertAllClose(anchor_corners_out, exp_anchor_corners) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/__init__.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/faster_rcnn_box_coder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/faster_rcnn_box_coder.py deleted file mode 100644 index af25e21a1..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/faster_rcnn_box_coder.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Faster RCNN box coder. - -Faster RCNN box coder follows the coding schema described below: - ty = (y - ya) / ha - tx = (x - xa) / wa - th = log(h / ha) - tw = log(w / wa) - where x, y, w, h denote the box's center coordinates, width and height - respectively. Similarly, xa, ya, wa, ha denote the anchor's center - coordinates, width and height. tx, ty, tw and th denote the anchor-encoded - center, width and height respectively. - - See http://arxiv.org/abs/1506.01497 for details. -""" - -import tensorflow as tf - -from object_detection.core import box_coder -from object_detection.core import box_list - -EPSILON = 1e-8 - - -class FasterRcnnBoxCoder(box_coder.BoxCoder): - """Faster RCNN box coder.""" - - def __init__(self, scale_factors=None): - """Constructor for FasterRcnnBoxCoder. - - Args: - scale_factors: List of 4 positive scalars to scale ty, tx, th and tw. - If set to None, does not perform scaling. For Faster RCNN, - the open-source implementation recommends using [10.0, 10.0, 5.0, 5.0]. - """ - if scale_factors: - assert len(scale_factors) == 4 - for scalar in scale_factors: - assert scalar > 0 - self._scale_factors = scale_factors - - @property - def code_size(self): - return 4 - - def _encode(self, boxes, anchors): - """Encode a box collection with respect to anchor collection. - - Args: - boxes: BoxList holding N boxes to be encoded. - anchors: BoxList of anchors. - - Returns: - a tensor representing N anchor-encoded boxes of the format - [ty, tx, th, tw]. - """ - # Convert anchors to the center coordinate representation. - ycenter_a, xcenter_a, ha, wa = anchors.get_center_coordinates_and_sizes() - ycenter, xcenter, h, w = boxes.get_center_coordinates_and_sizes() - # Avoid NaN in division and log below. - ha += EPSILON - wa += EPSILON - h += EPSILON - w += EPSILON - - tx = (xcenter - xcenter_a) / wa - ty = (ycenter - ycenter_a) / ha - tw = tf.log(w / wa) - th = tf.log(h / ha) - # Scales location targets as used in paper for joint training. - if self._scale_factors: - ty *= self._scale_factors[0] - tx *= self._scale_factors[1] - th *= self._scale_factors[2] - tw *= self._scale_factors[3] - return tf.transpose(tf.stack([ty, tx, th, tw])) - - def _decode(self, rel_codes, anchors): - """Decode relative codes to boxes. - - Args: - rel_codes: a tensor representing N anchor-encoded boxes. - anchors: BoxList of anchors. - - Returns: - boxes: BoxList holding N bounding boxes. - """ - ycenter_a, xcenter_a, ha, wa = anchors.get_center_coordinates_and_sizes() - - ty, tx, th, tw = tf.unstack(tf.transpose(rel_codes)) - if self._scale_factors: - ty /= self._scale_factors[0] - tx /= self._scale_factors[1] - th /= self._scale_factors[2] - tw /= self._scale_factors[3] - w = tf.exp(tw) * wa - h = tf.exp(th) * ha - ycenter = ty * ha + ycenter_a - xcenter = tx * wa + xcenter_a - ymin = ycenter - h / 2. - xmin = xcenter - w / 2. - ymax = ycenter + h / 2. - xmax = xcenter + w / 2. - return box_list.BoxList(tf.transpose(tf.stack([ymin, xmin, ymax, xmax]))) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/faster_rcnn_box_coder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/faster_rcnn_box_coder_test.py deleted file mode 100644 index b2135f06e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/faster_rcnn_box_coder_test.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.box_coder.faster_rcnn_box_coder.""" - -import tensorflow as tf - -from object_detection.box_coders import faster_rcnn_box_coder -from object_detection.core import box_list - - -class FasterRcnnBoxCoderTest(tf.test.TestCase): - - def test_get_correct_relative_codes_after_encoding(self): - boxes = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - anchors = [[15.0, 12.0, 30.0, 18.0], [0.1, 0.0, 0.7, 0.9]] - expected_rel_codes = [[-0.5, -0.416666, -0.405465, -0.182321], - [-0.083333, -0.222222, -0.693147, -1.098612]] - boxes = box_list.BoxList(tf.constant(boxes)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = faster_rcnn_box_coder.FasterRcnnBoxCoder() - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - rel_codes_out, = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - def test_get_correct_relative_codes_after_encoding_with_scaling(self): - boxes = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - anchors = [[15.0, 12.0, 30.0, 18.0], [0.1, 0.0, 0.7, 0.9]] - scale_factors = [2, 3, 4, 5] - expected_rel_codes = [[-1., -1.25, -1.62186, -0.911608], - [-0.166667, -0.666667, -2.772588, -5.493062]] - boxes = box_list.BoxList(tf.constant(boxes)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = faster_rcnn_box_coder.FasterRcnnBoxCoder( - scale_factors=scale_factors) - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - rel_codes_out, = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - def test_get_correct_boxes_after_decoding(self): - anchors = [[15.0, 12.0, 30.0, 18.0], [0.1, 0.0, 0.7, 0.9]] - rel_codes = [[-0.5, -0.416666, -0.405465, -0.182321], - [-0.083333, -0.222222, -0.693147, -1.098612]] - expected_boxes = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - anchors = box_list.BoxList(tf.constant(anchors)) - coder = faster_rcnn_box_coder.FasterRcnnBoxCoder() - boxes = coder.decode(rel_codes, anchors) - with self.test_session() as sess: - boxes_out, = sess.run([boxes.get()]) - self.assertAllClose(boxes_out, expected_boxes) - - def test_get_correct_boxes_after_decoding_with_scaling(self): - anchors = [[15.0, 12.0, 30.0, 18.0], [0.1, 0.0, 0.7, 0.9]] - rel_codes = [[-1., -1.25, -1.62186, -0.911608], - [-0.166667, -0.666667, -2.772588, -5.493062]] - scale_factors = [2, 3, 4, 5] - expected_boxes = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - anchors = box_list.BoxList(tf.constant(anchors)) - coder = faster_rcnn_box_coder.FasterRcnnBoxCoder( - scale_factors=scale_factors) - boxes = coder.decode(rel_codes, anchors) - with self.test_session() as sess: - boxes_out, = sess.run([boxes.get()]) - self.assertAllClose(boxes_out, expected_boxes) - - def test_very_small_Width_nan_after_encoding(self): - boxes = [[10.0, 10.0, 10.0000001, 20.0]] - anchors = [[15.0, 12.0, 30.0, 18.0]] - expected_rel_codes = [[-0.833333, 0., -21.128731, 0.510826]] - boxes = box_list.BoxList(tf.constant(boxes)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = faster_rcnn_box_coder.FasterRcnnBoxCoder() - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - rel_codes_out, = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/keypoint_box_coder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/keypoint_box_coder.py deleted file mode 100644 index 67df3b82e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/keypoint_box_coder.py +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Keypoint box coder. - -The keypoint box coder follows the coding schema described below (this is -similar to the FasterRcnnBoxCoder, except that it encodes keypoints in addition -to box coordinates): - ty = (y - ya) / ha - tx = (x - xa) / wa - th = log(h / ha) - tw = log(w / wa) - tky0 = (ky0 - ya) / ha - tkx0 = (kx0 - xa) / wa - tky1 = (ky1 - ya) / ha - tkx1 = (kx1 - xa) / wa - ... - where x, y, w, h denote the box's center coordinates, width and height - respectively. Similarly, xa, ya, wa, ha denote the anchor's center - coordinates, width and height. tx, ty, tw and th denote the anchor-encoded - center, width and height respectively. ky0, kx0, ky1, kx1, ... denote the - keypoints' coordinates, and tky0, tkx0, tky1, tkx1, ... denote the - anchor-encoded keypoint coordinates. -""" - -import tensorflow as tf - -from object_detection.core import box_coder -from object_detection.core import box_list -from object_detection.core import standard_fields as fields - -EPSILON = 1e-8 - - -class KeypointBoxCoder(box_coder.BoxCoder): - """Keypoint box coder.""" - - def __init__(self, num_keypoints, scale_factors=None): - """Constructor for KeypointBoxCoder. - - Args: - num_keypoints: Number of keypoints to encode/decode. - scale_factors: List of 4 positive scalars to scale ty, tx, th and tw. - In addition to scaling ty and tx, the first 2 scalars are used to scale - the y and x coordinates of the keypoints as well. If set to None, does - not perform scaling. - """ - self._num_keypoints = num_keypoints - - if scale_factors: - assert len(scale_factors) == 4 - for scalar in scale_factors: - assert scalar > 0 - self._scale_factors = scale_factors - self._keypoint_scale_factors = None - if scale_factors is not None: - self._keypoint_scale_factors = tf.expand_dims(tf.tile( - [tf.to_float(scale_factors[0]), tf.to_float(scale_factors[1])], - [num_keypoints]), 1) - - @property - def code_size(self): - return 4 + self._num_keypoints * 2 - - def _encode(self, boxes, anchors): - """Encode a box and keypoint collection with respect to anchor collection. - - Args: - boxes: BoxList holding N boxes and keypoints to be encoded. Boxes are - tensors with the shape [N, 4], and keypoints are tensors with the shape - [N, num_keypoints, 2]. - anchors: BoxList of anchors. - - Returns: - a tensor representing N anchor-encoded boxes of the format - [ty, tx, th, tw, tky0, tkx0, tky1, tkx1, ...] where tky0 and tkx0 - represent the y and x coordinates of the first keypoint, tky1 and tkx1 - represent the y and x coordinates of the second keypoint, and so on. - """ - # Convert anchors to the center coordinate representation. - ycenter_a, xcenter_a, ha, wa = anchors.get_center_coordinates_and_sizes() - ycenter, xcenter, h, w = boxes.get_center_coordinates_and_sizes() - keypoints = boxes.get_field(fields.BoxListFields.keypoints) - keypoints = tf.transpose(tf.reshape(keypoints, - [-1, self._num_keypoints * 2])) - num_boxes = boxes.num_boxes() - - # Avoid NaN in division and log below. - ha += EPSILON - wa += EPSILON - h += EPSILON - w += EPSILON - - tx = (xcenter - xcenter_a) / wa - ty = (ycenter - ycenter_a) / ha - tw = tf.log(w / wa) - th = tf.log(h / ha) - - tiled_anchor_centers = tf.tile( - tf.stack([ycenter_a, xcenter_a]), [self._num_keypoints, 1]) - tiled_anchor_sizes = tf.tile( - tf.stack([ha, wa]), [self._num_keypoints, 1]) - tkeypoints = (keypoints - tiled_anchor_centers) / tiled_anchor_sizes - - # Scales location targets as used in paper for joint training. - if self._scale_factors: - ty *= self._scale_factors[0] - tx *= self._scale_factors[1] - th *= self._scale_factors[2] - tw *= self._scale_factors[3] - tkeypoints *= tf.tile(self._keypoint_scale_factors, [1, num_boxes]) - - tboxes = tf.stack([ty, tx, th, tw]) - return tf.transpose(tf.concat([tboxes, tkeypoints], 0)) - - def _decode(self, rel_codes, anchors): - """Decode relative codes to boxes and keypoints. - - Args: - rel_codes: a tensor with shape [N, 4 + 2 * num_keypoints] representing N - anchor-encoded boxes and keypoints - anchors: BoxList of anchors. - - Returns: - boxes: BoxList holding N bounding boxes and keypoints. - """ - ycenter_a, xcenter_a, ha, wa = anchors.get_center_coordinates_and_sizes() - - num_codes = tf.shape(rel_codes)[0] - result = tf.unstack(tf.transpose(rel_codes)) - ty, tx, th, tw = result[:4] - tkeypoints = result[4:] - if self._scale_factors: - ty /= self._scale_factors[0] - tx /= self._scale_factors[1] - th /= self._scale_factors[2] - tw /= self._scale_factors[3] - tkeypoints /= tf.tile(self._keypoint_scale_factors, [1, num_codes]) - - w = tf.exp(tw) * wa - h = tf.exp(th) * ha - ycenter = ty * ha + ycenter_a - xcenter = tx * wa + xcenter_a - ymin = ycenter - h / 2. - xmin = xcenter - w / 2. - ymax = ycenter + h / 2. - xmax = xcenter + w / 2. - decoded_boxes_keypoints = box_list.BoxList( - tf.transpose(tf.stack([ymin, xmin, ymax, xmax]))) - - tiled_anchor_centers = tf.tile( - tf.stack([ycenter_a, xcenter_a]), [self._num_keypoints, 1]) - tiled_anchor_sizes = tf.tile( - tf.stack([ha, wa]), [self._num_keypoints, 1]) - keypoints = tkeypoints * tiled_anchor_sizes + tiled_anchor_centers - keypoints = tf.reshape(tf.transpose(keypoints), - [-1, self._num_keypoints, 2]) - decoded_boxes_keypoints.add_field(fields.BoxListFields.keypoints, keypoints) - return decoded_boxes_keypoints diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/keypoint_box_coder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/keypoint_box_coder_test.py deleted file mode 100644 index 330641e58..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/keypoint_box_coder_test.py +++ /dev/null @@ -1,140 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.box_coder.keypoint_box_coder.""" - -import tensorflow as tf - -from object_detection.box_coders import keypoint_box_coder -from object_detection.core import box_list -from object_detection.core import standard_fields as fields - - -class KeypointBoxCoderTest(tf.test.TestCase): - - def test_get_correct_relative_codes_after_encoding(self): - boxes = [[10., 10., 20., 15.], - [0.2, 0.1, 0.5, 0.4]] - keypoints = [[[15., 12.], [10., 15.]], - [[0.5, 0.3], [0.2, 0.4]]] - num_keypoints = len(keypoints[0]) - anchors = [[15., 12., 30., 18.], - [0.1, 0.0, 0.7, 0.9]] - expected_rel_codes = [ - [-0.5, -0.416666, -0.405465, -0.182321, - -0.5, -0.5, -0.833333, 0.], - [-0.083333, -0.222222, -0.693147, -1.098612, - 0.166667, -0.166667, -0.333333, -0.055556] - ] - boxes = box_list.BoxList(tf.constant(boxes)) - boxes.add_field(fields.BoxListFields.keypoints, tf.constant(keypoints)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = keypoint_box_coder.KeypointBoxCoder(num_keypoints) - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - rel_codes_out, = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - def test_get_correct_relative_codes_after_encoding_with_scaling(self): - boxes = [[10., 10., 20., 15.], - [0.2, 0.1, 0.5, 0.4]] - keypoints = [[[15., 12.], [10., 15.]], - [[0.5, 0.3], [0.2, 0.4]]] - num_keypoints = len(keypoints[0]) - anchors = [[15., 12., 30., 18.], - [0.1, 0.0, 0.7, 0.9]] - scale_factors = [2, 3, 4, 5] - expected_rel_codes = [ - [-1., -1.25, -1.62186, -0.911608, - -1.0, -1.5, -1.666667, 0.], - [-0.166667, -0.666667, -2.772588, -5.493062, - 0.333333, -0.5, -0.666667, -0.166667] - ] - boxes = box_list.BoxList(tf.constant(boxes)) - boxes.add_field(fields.BoxListFields.keypoints, tf.constant(keypoints)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = keypoint_box_coder.KeypointBoxCoder( - num_keypoints, scale_factors=scale_factors) - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - rel_codes_out, = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - def test_get_correct_boxes_after_decoding(self): - anchors = [[15., 12., 30., 18.], - [0.1, 0.0, 0.7, 0.9]] - rel_codes = [ - [-0.5, -0.416666, -0.405465, -0.182321, - -0.5, -0.5, -0.833333, 0.], - [-0.083333, -0.222222, -0.693147, -1.098612, - 0.166667, -0.166667, -0.333333, -0.055556] - ] - expected_boxes = [[10., 10., 20., 15.], - [0.2, 0.1, 0.5, 0.4]] - expected_keypoints = [[[15., 12.], [10., 15.]], - [[0.5, 0.3], [0.2, 0.4]]] - num_keypoints = len(expected_keypoints[0]) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = keypoint_box_coder.KeypointBoxCoder(num_keypoints) - boxes = coder.decode(rel_codes, anchors) - with self.test_session() as sess: - boxes_out, keypoints_out = sess.run( - [boxes.get(), boxes.get_field(fields.BoxListFields.keypoints)]) - self.assertAllClose(boxes_out, expected_boxes) - self.assertAllClose(keypoints_out, expected_keypoints) - - def test_get_correct_boxes_after_decoding_with_scaling(self): - anchors = [[15., 12., 30., 18.], - [0.1, 0.0, 0.7, 0.9]] - rel_codes = [ - [-1., -1.25, -1.62186, -0.911608, - -1.0, -1.5, -1.666667, 0.], - [-0.166667, -0.666667, -2.772588, -5.493062, - 0.333333, -0.5, -0.666667, -0.166667] - ] - scale_factors = [2, 3, 4, 5] - expected_boxes = [[10., 10., 20., 15.], - [0.2, 0.1, 0.5, 0.4]] - expected_keypoints = [[[15., 12.], [10., 15.]], - [[0.5, 0.3], [0.2, 0.4]]] - num_keypoints = len(expected_keypoints[0]) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = keypoint_box_coder.KeypointBoxCoder( - num_keypoints, scale_factors=scale_factors) - boxes = coder.decode(rel_codes, anchors) - with self.test_session() as sess: - boxes_out, keypoints_out = sess.run( - [boxes.get(), boxes.get_field(fields.BoxListFields.keypoints)]) - self.assertAllClose(boxes_out, expected_boxes) - self.assertAllClose(keypoints_out, expected_keypoints) - - def test_very_small_width_nan_after_encoding(self): - boxes = [[10., 10., 10.0000001, 20.]] - keypoints = [[[10., 10.], [10.0000001, 20.]]] - anchors = [[15., 12., 30., 18.]] - expected_rel_codes = [[-0.833333, 0., -21.128731, 0.510826, - -0.833333, -0.833333, -0.833333, 0.833333]] - boxes = box_list.BoxList(tf.constant(boxes)) - boxes.add_field(fields.BoxListFields.keypoints, tf.constant(keypoints)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = keypoint_box_coder.KeypointBoxCoder(2) - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - rel_codes_out, = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/mean_stddev_box_coder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/mean_stddev_box_coder.py deleted file mode 100644 index 256f53fd0..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/mean_stddev_box_coder.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Mean stddev box coder. - -This box coder use the following coding schema to encode boxes: -rel_code = (box_corner - anchor_corner_mean) / anchor_corner_stddev. -""" -from object_detection.core import box_coder -from object_detection.core import box_list - - -class MeanStddevBoxCoder(box_coder.BoxCoder): - """Mean stddev box coder.""" - - def __init__(self, stddev=0.01): - """Constructor for MeanStddevBoxCoder. - - Args: - stddev: The standard deviation used to encode and decode boxes. - """ - self._stddev = stddev - - @property - def code_size(self): - return 4 - - def _encode(self, boxes, anchors): - """Encode a box collection with respect to anchor collection. - - Args: - boxes: BoxList holding N boxes to be encoded. - anchors: BoxList of N anchors. - - Returns: - a tensor representing N anchor-encoded boxes - - Raises: - ValueError: if the anchors still have deprecated stddev field. - """ - box_corners = boxes.get() - if anchors.has_field('stddev'): - raise ValueError("'stddev' is a parameter of MeanStddevBoxCoder and " - "should not be specified in the box list.") - means = anchors.get() - return (box_corners - means) / self._stddev - - def _decode(self, rel_codes, anchors): - """Decode. - - Args: - rel_codes: a tensor representing N anchor-encoded boxes. - anchors: BoxList of anchors. - - Returns: - boxes: BoxList holding N bounding boxes - - Raises: - ValueError: if the anchors still have deprecated stddev field and expects - the decode method to use stddev value from that field. - """ - means = anchors.get() - if anchors.has_field('stddev'): - raise ValueError("'stddev' is a parameter of MeanStddevBoxCoder and " - "should not be specified in the box list.") - box_corners = rel_codes * self._stddev + means - return box_list.BoxList(box_corners) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/mean_stddev_box_coder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/mean_stddev_box_coder_test.py deleted file mode 100644 index 3e0eba936..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/mean_stddev_box_coder_test.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.box_coder.mean_stddev_boxcoder.""" - -import tensorflow as tf - -from object_detection.box_coders import mean_stddev_box_coder -from object_detection.core import box_list - - -class MeanStddevBoxCoderTest(tf.test.TestCase): - - def testGetCorrectRelativeCodesAfterEncoding(self): - box_corners = [[0.0, 0.0, 0.5, 0.5], [0.0, 0.0, 0.5, 0.5]] - boxes = box_list.BoxList(tf.constant(box_corners)) - expected_rel_codes = [[0.0, 0.0, 0.0, 0.0], [-5.0, -5.0, -5.0, -3.0]] - prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 1.0, 0.8]]) - priors = box_list.BoxList(prior_means) - - coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - rel_codes = coder.encode(boxes, priors) - with self.test_session() as sess: - rel_codes_out = sess.run(rel_codes) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - def testGetCorrectBoxesAfterDecoding(self): - rel_codes = tf.constant([[0.0, 0.0, 0.0, 0.0], [-5.0, -5.0, -5.0, -3.0]]) - expected_box_corners = [[0.0, 0.0, 0.5, 0.5], [0.0, 0.0, 0.5, 0.5]] - prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5], [0.5, 0.5, 1.0, 0.8]]) - priors = box_list.BoxList(prior_means) - - coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - decoded_boxes = coder.decode(rel_codes, priors) - decoded_box_corners = decoded_boxes.get() - with self.test_session() as sess: - decoded_out = sess.run(decoded_box_corners) - self.assertAllClose(decoded_out, expected_box_corners) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/square_box_coder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/square_box_coder.py deleted file mode 100644 index ee46b6895..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/square_box_coder.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Square box coder. - -Square box coder follows the coding schema described below: -l = sqrt(h * w) -la = sqrt(ha * wa) -ty = (y - ya) / la -tx = (x - xa) / la -tl = log(l / la) -where x, y, w, h denote the box's center coordinates, width, and height, -respectively. Similarly, xa, ya, wa, ha denote the anchor's center -coordinates, width and height. tx, ty, tl denote the anchor-encoded -center, and length, respectively. Because the encoded box is a square, only -one length is encoded. - -This has shown to provide performance improvements over the Faster RCNN box -coder when the objects being detected tend to be square (e.g. faces) and when -the input images are not distorted via resizing. -""" - -import tensorflow as tf - -from object_detection.core import box_coder -from object_detection.core import box_list - -EPSILON = 1e-8 - - -class SquareBoxCoder(box_coder.BoxCoder): - """Encodes a 3-scalar representation of a square box.""" - - def __init__(self, scale_factors=None): - """Constructor for SquareBoxCoder. - - Args: - scale_factors: List of 3 positive scalars to scale ty, tx, and tl. - If set to None, does not perform scaling. For faster RCNN, - the open-source implementation recommends using [10.0, 10.0, 5.0]. - - Raises: - ValueError: If scale_factors is not length 3 or contains values less than - or equal to 0. - """ - if scale_factors: - if len(scale_factors) != 3: - raise ValueError('The argument scale_factors must be a list of length ' - '3.') - if any(scalar <= 0 for scalar in scale_factors): - raise ValueError('The values in scale_factors must all be greater ' - 'than 0.') - self._scale_factors = scale_factors - - @property - def code_size(self): - return 3 - - def _encode(self, boxes, anchors): - """Encodes a box collection with respect to an anchor collection. - - Args: - boxes: BoxList holding N boxes to be encoded. - anchors: BoxList of anchors. - - Returns: - a tensor representing N anchor-encoded boxes of the format - [ty, tx, tl]. - """ - # Convert anchors to the center coordinate representation. - ycenter_a, xcenter_a, ha, wa = anchors.get_center_coordinates_and_sizes() - la = tf.sqrt(ha * wa) - ycenter, xcenter, h, w = boxes.get_center_coordinates_and_sizes() - l = tf.sqrt(h * w) - # Avoid NaN in division and log below. - la += EPSILON - l += EPSILON - - tx = (xcenter - xcenter_a) / la - ty = (ycenter - ycenter_a) / la - tl = tf.log(l / la) - # Scales location targets for joint training. - if self._scale_factors: - ty *= self._scale_factors[0] - tx *= self._scale_factors[1] - tl *= self._scale_factors[2] - return tf.transpose(tf.stack([ty, tx, tl])) - - def _decode(self, rel_codes, anchors): - """Decodes relative codes to boxes. - - Args: - rel_codes: a tensor representing N anchor-encoded boxes. - anchors: BoxList of anchors. - - Returns: - boxes: BoxList holding N bounding boxes. - """ - ycenter_a, xcenter_a, ha, wa = anchors.get_center_coordinates_and_sizes() - la = tf.sqrt(ha * wa) - - ty, tx, tl = tf.unstack(tf.transpose(rel_codes)) - if self._scale_factors: - ty /= self._scale_factors[0] - tx /= self._scale_factors[1] - tl /= self._scale_factors[2] - l = tf.exp(tl) * la - ycenter = ty * la + ycenter_a - xcenter = tx * la + xcenter_a - ymin = ycenter - l / 2. - xmin = xcenter - l / 2. - ymax = ycenter + l / 2. - xmax = xcenter + l / 2. - return box_list.BoxList(tf.transpose(tf.stack([ymin, xmin, ymax, xmax]))) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/square_box_coder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/square_box_coder_test.py deleted file mode 100644 index 7f739c6b4..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/box_coders/square_box_coder_test.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.box_coder.square_box_coder.""" - -import tensorflow as tf - -from object_detection.box_coders import square_box_coder -from object_detection.core import box_list - - -class SquareBoxCoderTest(tf.test.TestCase): - - def test_correct_relative_codes_with_default_scale(self): - boxes = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - anchors = [[15.0, 12.0, 30.0, 18.0], [0.1, 0.0, 0.7, 0.9]] - scale_factors = None - expected_rel_codes = [[-0.790569, -0.263523, -0.293893], - [-0.068041, -0.272166, -0.89588]] - - boxes = box_list.BoxList(tf.constant(boxes)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = square_box_coder.SquareBoxCoder(scale_factors=scale_factors) - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - (rel_codes_out,) = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - def test_correct_relative_codes_with_non_default_scale(self): - boxes = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - anchors = [[15.0, 12.0, 30.0, 18.0], [0.1, 0.0, 0.7, 0.9]] - scale_factors = [2, 3, 4] - expected_rel_codes = [[-1.581139, -0.790569, -1.175573], - [-0.136083, -0.816497, -3.583519]] - boxes = box_list.BoxList(tf.constant(boxes)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = square_box_coder.SquareBoxCoder(scale_factors=scale_factors) - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - (rel_codes_out,) = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - def test_correct_relative_codes_with_small_width(self): - boxes = [[10.0, 10.0, 10.0000001, 20.0]] - anchors = [[15.0, 12.0, 30.0, 18.0]] - scale_factors = None - expected_rel_codes = [[-1.317616, 0., -20.670586]] - boxes = box_list.BoxList(tf.constant(boxes)) - anchors = box_list.BoxList(tf.constant(anchors)) - coder = square_box_coder.SquareBoxCoder(scale_factors=scale_factors) - rel_codes = coder.encode(boxes, anchors) - with self.test_session() as sess: - (rel_codes_out,) = sess.run([rel_codes]) - self.assertAllClose(rel_codes_out, expected_rel_codes) - - def test_correct_boxes_with_default_scale(self): - anchors = [[15.0, 12.0, 30.0, 18.0], [0.1, 0.0, 0.7, 0.9]] - rel_codes = [[-0.5, -0.416666, -0.405465], - [-0.083333, -0.222222, -0.693147]] - scale_factors = None - expected_boxes = [[14.594306, 7.884875, 20.918861, 14.209432], - [0.155051, 0.102989, 0.522474, 0.470412]] - anchors = box_list.BoxList(tf.constant(anchors)) - coder = square_box_coder.SquareBoxCoder(scale_factors=scale_factors) - boxes = coder.decode(rel_codes, anchors) - with self.test_session() as sess: - (boxes_out,) = sess.run([boxes.get()]) - self.assertAllClose(boxes_out, expected_boxes) - - def test_correct_boxes_with_non_default_scale(self): - anchors = [[15.0, 12.0, 30.0, 18.0], [0.1, 0.0, 0.7, 0.9]] - rel_codes = [[-1., -1.25, -1.62186], [-0.166667, -0.666667, -2.772588]] - scale_factors = [2, 3, 4] - expected_boxes = [[14.594306, 7.884875, 20.918861, 14.209432], - [0.155051, 0.102989, 0.522474, 0.470412]] - anchors = box_list.BoxList(tf.constant(anchors)) - coder = square_box_coder.SquareBoxCoder(scale_factors=scale_factors) - boxes = coder.decode(rel_codes, anchors) - with self.test_session() as sess: - (boxes_out,) = sess.run([boxes.get()]) - self.assertAllClose(boxes_out, expected_boxes) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/__init__.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/anchor_generator_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/anchor_generator_builder.py deleted file mode 100644 index 54cec3a1d..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/anchor_generator_builder.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""A function to build an object detection anchor generator from config.""" - -from object_detection.anchor_generators import grid_anchor_generator -from object_detection.anchor_generators import multiple_grid_anchor_generator -from object_detection.anchor_generators import multiscale_grid_anchor_generator -from object_detection.protos import anchor_generator_pb2 - - -def build(anchor_generator_config): - """Builds an anchor generator based on the config. - - Args: - anchor_generator_config: An anchor_generator.proto object containing the - config for the desired anchor generator. - - Returns: - Anchor generator based on the config. - - Raises: - ValueError: On empty anchor generator proto. - """ - if not isinstance(anchor_generator_config, - anchor_generator_pb2.AnchorGenerator): - raise ValueError('anchor_generator_config not of type ' - 'anchor_generator_pb2.AnchorGenerator') - if anchor_generator_config.WhichOneof( - 'anchor_generator_oneof') == 'grid_anchor_generator': - grid_anchor_generator_config = anchor_generator_config.grid_anchor_generator - return grid_anchor_generator.GridAnchorGenerator( - scales=[float(scale) for scale in grid_anchor_generator_config.scales], - aspect_ratios=[float(aspect_ratio) - for aspect_ratio - in grid_anchor_generator_config.aspect_ratios], - base_anchor_size=[grid_anchor_generator_config.height, - grid_anchor_generator_config.width], - anchor_stride=[grid_anchor_generator_config.height_stride, - grid_anchor_generator_config.width_stride], - anchor_offset=[grid_anchor_generator_config.height_offset, - grid_anchor_generator_config.width_offset]) - elif anchor_generator_config.WhichOneof( - 'anchor_generator_oneof') == 'ssd_anchor_generator': - ssd_anchor_generator_config = anchor_generator_config.ssd_anchor_generator - anchor_strides = None - if ssd_anchor_generator_config.height_stride: - anchor_strides = zip(ssd_anchor_generator_config.height_stride, - ssd_anchor_generator_config.width_stride) - anchor_offsets = None - if ssd_anchor_generator_config.height_offset: - anchor_offsets = zip(ssd_anchor_generator_config.height_offset, - ssd_anchor_generator_config.width_offset) - return multiple_grid_anchor_generator.create_ssd_anchors( - num_layers=ssd_anchor_generator_config.num_layers, - min_scale=ssd_anchor_generator_config.min_scale, - max_scale=ssd_anchor_generator_config.max_scale, - scales=[float(scale) for scale in ssd_anchor_generator_config.scales], - aspect_ratios=ssd_anchor_generator_config.aspect_ratios, - interpolated_scale_aspect_ratio=( - ssd_anchor_generator_config.interpolated_scale_aspect_ratio), - base_anchor_size=[ - ssd_anchor_generator_config.base_anchor_height, - ssd_anchor_generator_config.base_anchor_width - ], - anchor_strides=anchor_strides, - anchor_offsets=anchor_offsets, - reduce_boxes_in_lowest_layer=( - ssd_anchor_generator_config.reduce_boxes_in_lowest_layer)) - elif anchor_generator_config.WhichOneof( - 'anchor_generator_oneof') == 'multiscale_anchor_generator': - cfg = anchor_generator_config.multiscale_anchor_generator - return multiscale_grid_anchor_generator.MultiscaleGridAnchorGenerator( - cfg.min_level, - cfg.max_level, - cfg.anchor_scale, - [float(aspect_ratio) for aspect_ratio in cfg.aspect_ratios], - cfg.scales_per_octave, - cfg.normalize_coordinates - ) - else: - raise ValueError('Empty anchor generator.') diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/anchor_generator_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/anchor_generator_builder_test.py deleted file mode 100644 index 2a23c2d96..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/anchor_generator_builder_test.py +++ /dev/null @@ -1,300 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for anchor_generator_builder.""" - -import math - -import tensorflow as tf - -from google.protobuf import text_format -from object_detection.anchor_generators import grid_anchor_generator -from object_detection.anchor_generators import multiple_grid_anchor_generator -from object_detection.anchor_generators import multiscale_grid_anchor_generator -from object_detection.builders import anchor_generator_builder -from object_detection.protos import anchor_generator_pb2 - - -class AnchorGeneratorBuilderTest(tf.test.TestCase): - - def assert_almost_list_equal(self, expected_list, actual_list, delta=None): - self.assertEqual(len(expected_list), len(actual_list)) - for expected_item, actual_item in zip(expected_list, actual_list): - self.assertAlmostEqual(expected_item, actual_item, delta=delta) - - def test_build_grid_anchor_generator_with_defaults(self): - anchor_generator_text_proto = """ - grid_anchor_generator { - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - grid_anchor_generator.GridAnchorGenerator)) - self.assertListEqual(anchor_generator_object._scales, []) - self.assertListEqual(anchor_generator_object._aspect_ratios, []) - with self.test_session() as sess: - base_anchor_size, anchor_offset, anchor_stride = sess.run( - [anchor_generator_object._base_anchor_size, - anchor_generator_object._anchor_offset, - anchor_generator_object._anchor_stride]) - self.assertAllEqual(anchor_offset, [0, 0]) - self.assertAllEqual(anchor_stride, [16, 16]) - self.assertAllEqual(base_anchor_size, [256, 256]) - - def test_build_grid_anchor_generator_with_non_default_parameters(self): - anchor_generator_text_proto = """ - grid_anchor_generator { - height: 128 - width: 512 - height_stride: 10 - width_stride: 20 - height_offset: 30 - width_offset: 40 - scales: [0.4, 2.2] - aspect_ratios: [0.3, 4.5] - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - grid_anchor_generator.GridAnchorGenerator)) - self.assert_almost_list_equal(anchor_generator_object._scales, - [0.4, 2.2]) - self.assert_almost_list_equal(anchor_generator_object._aspect_ratios, - [0.3, 4.5]) - with self.test_session() as sess: - base_anchor_size, anchor_offset, anchor_stride = sess.run( - [anchor_generator_object._base_anchor_size, - anchor_generator_object._anchor_offset, - anchor_generator_object._anchor_stride]) - self.assertAllEqual(anchor_offset, [30, 40]) - self.assertAllEqual(anchor_stride, [10, 20]) - self.assertAllEqual(base_anchor_size, [128, 512]) - - def test_build_ssd_anchor_generator_with_defaults(self): - anchor_generator_text_proto = """ - ssd_anchor_generator { - aspect_ratios: [1.0] - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - multiple_grid_anchor_generator. - MultipleGridAnchorGenerator)) - for actual_scales, expected_scales in zip( - list(anchor_generator_object._scales), - [(0.1, 0.2, 0.2), - (0.35, 0.418), - (0.499, 0.570), - (0.649, 0.721), - (0.799, 0.871), - (0.949, 0.974)]): - self.assert_almost_list_equal(expected_scales, actual_scales, delta=1e-2) - for actual_aspect_ratio, expected_aspect_ratio in zip( - list(anchor_generator_object._aspect_ratios), - [(1.0, 2.0, 0.5)] + 5 * [(1.0, 1.0)]): - self.assert_almost_list_equal(expected_aspect_ratio, actual_aspect_ratio) - - with self.test_session() as sess: - base_anchor_size = sess.run(anchor_generator_object._base_anchor_size) - self.assertAllClose(base_anchor_size, [1.0, 1.0]) - - def test_build_ssd_anchor_generator_with_custom_scales(self): - anchor_generator_text_proto = """ - ssd_anchor_generator { - aspect_ratios: [1.0] - scales: [0.1, 0.15, 0.2, 0.4, 0.6, 0.8] - reduce_boxes_in_lowest_layer: false - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - multiple_grid_anchor_generator. - MultipleGridAnchorGenerator)) - for actual_scales, expected_scales in zip( - list(anchor_generator_object._scales), - [(0.1, math.sqrt(0.1 * 0.15)), - (0.15, math.sqrt(0.15 * 0.2)), - (0.2, math.sqrt(0.2 * 0.4)), - (0.4, math.sqrt(0.4 * 0.6)), - (0.6, math.sqrt(0.6 * 0.8)), - (0.8, math.sqrt(0.8 * 1.0))]): - self.assert_almost_list_equal(expected_scales, actual_scales, delta=1e-2) - - def test_build_ssd_anchor_generator_with_custom_interpolated_scale(self): - anchor_generator_text_proto = """ - ssd_anchor_generator { - aspect_ratios: [0.5] - interpolated_scale_aspect_ratio: 0.5 - reduce_boxes_in_lowest_layer: false - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - multiple_grid_anchor_generator. - MultipleGridAnchorGenerator)) - for actual_aspect_ratio, expected_aspect_ratio in zip( - list(anchor_generator_object._aspect_ratios), - 6 * [(0.5, 0.5)]): - self.assert_almost_list_equal(expected_aspect_ratio, actual_aspect_ratio) - - def test_build_ssd_anchor_generator_without_reduced_boxes(self): - anchor_generator_text_proto = """ - ssd_anchor_generator { - aspect_ratios: [1.0] - reduce_boxes_in_lowest_layer: false - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - multiple_grid_anchor_generator. - MultipleGridAnchorGenerator)) - - for actual_scales, expected_scales in zip( - list(anchor_generator_object._scales), - [(0.2, 0.264), - (0.35, 0.418), - (0.499, 0.570), - (0.649, 0.721), - (0.799, 0.871), - (0.949, 0.974)]): - self.assert_almost_list_equal(expected_scales, actual_scales, delta=1e-2) - - for actual_aspect_ratio, expected_aspect_ratio in zip( - list(anchor_generator_object._aspect_ratios), - 6 * [(1.0, 1.0)]): - self.assert_almost_list_equal(expected_aspect_ratio, actual_aspect_ratio) - - with self.test_session() as sess: - base_anchor_size = sess.run(anchor_generator_object._base_anchor_size) - self.assertAllClose(base_anchor_size, [1.0, 1.0]) - - def test_build_ssd_anchor_generator_with_non_default_parameters(self): - anchor_generator_text_proto = """ - ssd_anchor_generator { - num_layers: 2 - min_scale: 0.3 - max_scale: 0.8 - aspect_ratios: [2.0] - height_stride: 16 - height_stride: 32 - width_stride: 20 - width_stride: 30 - height_offset: 8 - height_offset: 16 - width_offset: 0 - width_offset: 10 - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - multiple_grid_anchor_generator. - MultipleGridAnchorGenerator)) - - for actual_scales, expected_scales in zip( - list(anchor_generator_object._scales), - [(0.1, 0.3, 0.3), (0.8, 0.894)]): - self.assert_almost_list_equal(expected_scales, actual_scales, delta=1e-2) - - for actual_aspect_ratio, expected_aspect_ratio in zip( - list(anchor_generator_object._aspect_ratios), - [(1.0, 2.0, 0.5), (2.0, 1.0)]): - self.assert_almost_list_equal(expected_aspect_ratio, actual_aspect_ratio) - - for actual_strides, expected_strides in zip( - list(anchor_generator_object._anchor_strides), [(16, 20), (32, 30)]): - self.assert_almost_list_equal(expected_strides, actual_strides) - - for actual_offsets, expected_offsets in zip( - list(anchor_generator_object._anchor_offsets), [(8, 0), (16, 10)]): - self.assert_almost_list_equal(expected_offsets, actual_offsets) - - with self.test_session() as sess: - base_anchor_size = sess.run(anchor_generator_object._base_anchor_size) - self.assertAllClose(base_anchor_size, [1.0, 1.0]) - - def test_raise_value_error_on_empty_anchor_genertor(self): - anchor_generator_text_proto = """ - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - with self.assertRaises(ValueError): - anchor_generator_builder.build(anchor_generator_proto) - - def test_build_multiscale_anchor_generator_custom_aspect_ratios(self): - anchor_generator_text_proto = """ - multiscale_anchor_generator { - aspect_ratios: [1.0] - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - multiscale_grid_anchor_generator. - MultiscaleGridAnchorGenerator)) - for level, anchor_grid_info in zip( - range(3, 8), anchor_generator_object._anchor_grid_info): - self.assertEqual(set(anchor_grid_info.keys()), set(['level', 'info'])) - self.assertTrue(level, anchor_grid_info['level']) - self.assertEqual(len(anchor_grid_info['info']), 4) - self.assertAllClose(anchor_grid_info['info'][0], [2**0, 2**0.5]) - self.assertTrue(anchor_grid_info['info'][1], 1.0) - self.assertAllClose(anchor_grid_info['info'][2], - [4.0 * 2**level, 4.0 * 2**level]) - self.assertAllClose(anchor_grid_info['info'][3], [2**level, 2**level]) - self.assertTrue(anchor_generator_object._normalize_coordinates) - - def test_build_multiscale_anchor_generator_with_anchors_in_pixel_coordinates( - self): - anchor_generator_text_proto = """ - multiscale_anchor_generator { - aspect_ratios: [1.0] - normalize_coordinates: false - } - """ - anchor_generator_proto = anchor_generator_pb2.AnchorGenerator() - text_format.Merge(anchor_generator_text_proto, anchor_generator_proto) - anchor_generator_object = anchor_generator_builder.build( - anchor_generator_proto) - self.assertTrue(isinstance(anchor_generator_object, - multiscale_grid_anchor_generator. - MultiscaleGridAnchorGenerator)) - self.assertFalse(anchor_generator_object._normalize_coordinates) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_coder_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_coder_builder.py deleted file mode 100644 index cc13d5a2f..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_coder_builder.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""A function to build an object detection box coder from configuration.""" -from object_detection.box_coders import faster_rcnn_box_coder -from object_detection.box_coders import keypoint_box_coder -from object_detection.box_coders import mean_stddev_box_coder -from object_detection.box_coders import square_box_coder -from object_detection.protos import box_coder_pb2 - - -def build(box_coder_config): - """Builds a box coder object based on the box coder config. - - Args: - box_coder_config: A box_coder.proto object containing the config for the - desired box coder. - - Returns: - BoxCoder based on the config. - - Raises: - ValueError: On empty box coder proto. - """ - if not isinstance(box_coder_config, box_coder_pb2.BoxCoder): - raise ValueError('box_coder_config not of type box_coder_pb2.BoxCoder.') - - if box_coder_config.WhichOneof('box_coder_oneof') == 'faster_rcnn_box_coder': - return faster_rcnn_box_coder.FasterRcnnBoxCoder(scale_factors=[ - box_coder_config.faster_rcnn_box_coder.y_scale, - box_coder_config.faster_rcnn_box_coder.x_scale, - box_coder_config.faster_rcnn_box_coder.height_scale, - box_coder_config.faster_rcnn_box_coder.width_scale - ]) - if box_coder_config.WhichOneof('box_coder_oneof') == 'keypoint_box_coder': - return keypoint_box_coder.KeypointBoxCoder( - box_coder_config.keypoint_box_coder.num_keypoints, - scale_factors=[ - box_coder_config.keypoint_box_coder.y_scale, - box_coder_config.keypoint_box_coder.x_scale, - box_coder_config.keypoint_box_coder.height_scale, - box_coder_config.keypoint_box_coder.width_scale - ]) - if (box_coder_config.WhichOneof('box_coder_oneof') == - 'mean_stddev_box_coder'): - return mean_stddev_box_coder.MeanStddevBoxCoder( - stddev=box_coder_config.mean_stddev_box_coder.stddev) - if box_coder_config.WhichOneof('box_coder_oneof') == 'square_box_coder': - return square_box_coder.SquareBoxCoder(scale_factors=[ - box_coder_config.square_box_coder.y_scale, - box_coder_config.square_box_coder.x_scale, - box_coder_config.square_box_coder.length_scale - ]) - raise ValueError('Empty box coder.') diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_coder_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_coder_builder_test.py deleted file mode 100644 index 286012e9d..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_coder_builder_test.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for box_coder_builder.""" - -import tensorflow as tf - -from google.protobuf import text_format -from object_detection.box_coders import faster_rcnn_box_coder -from object_detection.box_coders import keypoint_box_coder -from object_detection.box_coders import mean_stddev_box_coder -from object_detection.box_coders import square_box_coder -from object_detection.builders import box_coder_builder -from object_detection.protos import box_coder_pb2 - - -class BoxCoderBuilderTest(tf.test.TestCase): - - def test_build_faster_rcnn_box_coder_with_defaults(self): - box_coder_text_proto = """ - faster_rcnn_box_coder { - } - """ - box_coder_proto = box_coder_pb2.BoxCoder() - text_format.Merge(box_coder_text_proto, box_coder_proto) - box_coder_object = box_coder_builder.build(box_coder_proto) - self.assertIsInstance(box_coder_object, - faster_rcnn_box_coder.FasterRcnnBoxCoder) - self.assertEqual(box_coder_object._scale_factors, [10.0, 10.0, 5.0, 5.0]) - - def test_build_faster_rcnn_box_coder_with_non_default_parameters(self): - box_coder_text_proto = """ - faster_rcnn_box_coder { - y_scale: 6.0 - x_scale: 3.0 - height_scale: 7.0 - width_scale: 8.0 - } - """ - box_coder_proto = box_coder_pb2.BoxCoder() - text_format.Merge(box_coder_text_proto, box_coder_proto) - box_coder_object = box_coder_builder.build(box_coder_proto) - self.assertIsInstance(box_coder_object, - faster_rcnn_box_coder.FasterRcnnBoxCoder) - self.assertEqual(box_coder_object._scale_factors, [6.0, 3.0, 7.0, 8.0]) - - def test_build_keypoint_box_coder_with_defaults(self): - box_coder_text_proto = """ - keypoint_box_coder { - } - """ - box_coder_proto = box_coder_pb2.BoxCoder() - text_format.Merge(box_coder_text_proto, box_coder_proto) - box_coder_object = box_coder_builder.build(box_coder_proto) - self.assertIsInstance(box_coder_object, keypoint_box_coder.KeypointBoxCoder) - self.assertEqual(box_coder_object._scale_factors, [10.0, 10.0, 5.0, 5.0]) - - def test_build_keypoint_box_coder_with_non_default_parameters(self): - box_coder_text_proto = """ - keypoint_box_coder { - num_keypoints: 6 - y_scale: 6.0 - x_scale: 3.0 - height_scale: 7.0 - width_scale: 8.0 - } - """ - box_coder_proto = box_coder_pb2.BoxCoder() - text_format.Merge(box_coder_text_proto, box_coder_proto) - box_coder_object = box_coder_builder.build(box_coder_proto) - self.assertIsInstance(box_coder_object, keypoint_box_coder.KeypointBoxCoder) - self.assertEqual(box_coder_object._num_keypoints, 6) - self.assertEqual(box_coder_object._scale_factors, [6.0, 3.0, 7.0, 8.0]) - - def test_build_mean_stddev_box_coder(self): - box_coder_text_proto = """ - mean_stddev_box_coder { - } - """ - box_coder_proto = box_coder_pb2.BoxCoder() - text_format.Merge(box_coder_text_proto, box_coder_proto) - box_coder_object = box_coder_builder.build(box_coder_proto) - self.assertTrue( - isinstance(box_coder_object, - mean_stddev_box_coder.MeanStddevBoxCoder)) - - def test_build_square_box_coder_with_defaults(self): - box_coder_text_proto = """ - square_box_coder { - } - """ - box_coder_proto = box_coder_pb2.BoxCoder() - text_format.Merge(box_coder_text_proto, box_coder_proto) - box_coder_object = box_coder_builder.build(box_coder_proto) - self.assertTrue( - isinstance(box_coder_object, square_box_coder.SquareBoxCoder)) - self.assertEqual(box_coder_object._scale_factors, [10.0, 10.0, 5.0]) - - def test_build_square_box_coder_with_non_default_parameters(self): - box_coder_text_proto = """ - square_box_coder { - y_scale: 6.0 - x_scale: 3.0 - length_scale: 7.0 - } - """ - box_coder_proto = box_coder_pb2.BoxCoder() - text_format.Merge(box_coder_text_proto, box_coder_proto) - box_coder_object = box_coder_builder.build(box_coder_proto) - self.assertTrue( - isinstance(box_coder_object, square_box_coder.SquareBoxCoder)) - self.assertEqual(box_coder_object._scale_factors, [6.0, 3.0, 7.0]) - - def test_raise_error_on_empty_box_coder(self): - box_coder_text_proto = """ - """ - box_coder_proto = box_coder_pb2.BoxCoder() - text_format.Merge(box_coder_text_proto, box_coder_proto) - with self.assertRaises(ValueError): - box_coder_builder.build(box_coder_proto) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_predictor_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_predictor_builder.py deleted file mode 100644 index 2f311221c..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_predictor_builder.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Function to build box predictor from configuration.""" - -from object_detection.core import box_predictor -from object_detection.protos import box_predictor_pb2 - - -def build(argscope_fn, box_predictor_config, is_training, num_classes): - """Builds box predictor based on the configuration. - - Builds box predictor based on the configuration. See box_predictor.proto for - configurable options. Also, see box_predictor.py for more details. - - Args: - argscope_fn: A function that takes the following inputs: - * hyperparams_pb2.Hyperparams proto - * a boolean indicating if the model is in training mode. - and returns a tf slim argscope for Conv and FC hyperparameters. - box_predictor_config: box_predictor_pb2.BoxPredictor proto containing - configuration. - is_training: Whether the models is in training mode. - num_classes: Number of classes to predict. - - Returns: - box_predictor: box_predictor.BoxPredictor object. - - Raises: - ValueError: On unknown box predictor. - """ - if not isinstance(box_predictor_config, box_predictor_pb2.BoxPredictor): - raise ValueError('box_predictor_config not of type ' - 'box_predictor_pb2.BoxPredictor.') - - box_predictor_oneof = box_predictor_config.WhichOneof('box_predictor_oneof') - - if box_predictor_oneof == 'convolutional_box_predictor': - conv_box_predictor = box_predictor_config.convolutional_box_predictor - conv_hyperparams_fn = argscope_fn(conv_box_predictor.conv_hyperparams, - is_training) - box_predictor_object = box_predictor.ConvolutionalBoxPredictor( - is_training=is_training, - num_classes=num_classes, - conv_hyperparams_fn=conv_hyperparams_fn, - min_depth=conv_box_predictor.min_depth, - max_depth=conv_box_predictor.max_depth, - num_layers_before_predictor=(conv_box_predictor. - num_layers_before_predictor), - use_dropout=conv_box_predictor.use_dropout, - dropout_keep_prob=conv_box_predictor.dropout_keep_probability, - kernel_size=conv_box_predictor.kernel_size, - box_code_size=conv_box_predictor.box_code_size, - apply_sigmoid_to_scores=conv_box_predictor.apply_sigmoid_to_scores, - class_prediction_bias_init=(conv_box_predictor. - class_prediction_bias_init), - use_depthwise=conv_box_predictor.use_depthwise - ) - return box_predictor_object - - if box_predictor_oneof == 'weight_shared_convolutional_box_predictor': - conv_box_predictor = (box_predictor_config. - weight_shared_convolutional_box_predictor) - conv_hyperparams_fn = argscope_fn(conv_box_predictor.conv_hyperparams, - is_training) - box_predictor_object = box_predictor.WeightSharedConvolutionalBoxPredictor( - is_training=is_training, - num_classes=num_classes, - conv_hyperparams_fn=conv_hyperparams_fn, - depth=conv_box_predictor.depth, - num_layers_before_predictor=( - conv_box_predictor.num_layers_before_predictor), - kernel_size=conv_box_predictor.kernel_size, - box_code_size=conv_box_predictor.box_code_size, - class_prediction_bias_init=conv_box_predictor. - class_prediction_bias_init, - use_dropout=conv_box_predictor.use_dropout, - dropout_keep_prob=conv_box_predictor.dropout_keep_probability) - return box_predictor_object - - if box_predictor_oneof == 'mask_rcnn_box_predictor': - mask_rcnn_box_predictor = box_predictor_config.mask_rcnn_box_predictor - fc_hyperparams_fn = argscope_fn(mask_rcnn_box_predictor.fc_hyperparams, - is_training) - conv_hyperparams_fn = None - if mask_rcnn_box_predictor.HasField('conv_hyperparams'): - conv_hyperparams_fn = argscope_fn( - mask_rcnn_box_predictor.conv_hyperparams, is_training) - box_predictor_object = box_predictor.MaskRCNNBoxPredictor( - is_training=is_training, - num_classes=num_classes, - fc_hyperparams_fn=fc_hyperparams_fn, - use_dropout=mask_rcnn_box_predictor.use_dropout, - dropout_keep_prob=mask_rcnn_box_predictor.dropout_keep_probability, - box_code_size=mask_rcnn_box_predictor.box_code_size, - conv_hyperparams_fn=conv_hyperparams_fn, - predict_instance_masks=mask_rcnn_box_predictor.predict_instance_masks, - mask_height=mask_rcnn_box_predictor.mask_height, - mask_width=mask_rcnn_box_predictor.mask_width, - mask_prediction_num_conv_layers=( - mask_rcnn_box_predictor.mask_prediction_num_conv_layers), - mask_prediction_conv_depth=( - mask_rcnn_box_predictor.mask_prediction_conv_depth), - masks_are_class_agnostic=( - mask_rcnn_box_predictor.masks_are_class_agnostic), - predict_keypoints=mask_rcnn_box_predictor.predict_keypoints, - share_box_across_classes=( - mask_rcnn_box_predictor.share_box_across_classes)) - return box_predictor_object - - if box_predictor_oneof == 'rfcn_box_predictor': - rfcn_box_predictor = box_predictor_config.rfcn_box_predictor - conv_hyperparams_fn = argscope_fn(rfcn_box_predictor.conv_hyperparams, - is_training) - box_predictor_object = box_predictor.RfcnBoxPredictor( - is_training=is_training, - num_classes=num_classes, - conv_hyperparams_fn=conv_hyperparams_fn, - crop_size=[rfcn_box_predictor.crop_height, - rfcn_box_predictor.crop_width], - num_spatial_bins=[rfcn_box_predictor.num_spatial_bins_height, - rfcn_box_predictor.num_spatial_bins_width], - depth=rfcn_box_predictor.depth, - box_code_size=rfcn_box_predictor.box_code_size) - return box_predictor_object - raise ValueError('Unknown box predictor: {}'.format(box_predictor_oneof)) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_predictor_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_predictor_builder_test.py deleted file mode 100644 index 35ad57be9..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/box_predictor_builder_test.py +++ /dev/null @@ -1,514 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for box_predictor_builder.""" -import mock -import tensorflow as tf - -from google.protobuf import text_format -from object_detection.builders import box_predictor_builder -from object_detection.builders import hyperparams_builder -from object_detection.protos import box_predictor_pb2 -from object_detection.protos import hyperparams_pb2 - - -class ConvolutionalBoxPredictorBuilderTest(tf.test.TestCase): - - def test_box_predictor_calls_conv_argscope_fn(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - weight: 0.0003 - } - } - initializer { - truncated_normal_initializer { - mean: 0.0 - stddev: 0.3 - } - } - activation: RELU_6 - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, hyperparams_proto) - def mock_conv_argscope_builder(conv_hyperparams_arg, is_training): - return (conv_hyperparams_arg, is_training) - - box_predictor_proto = box_predictor_pb2.BoxPredictor() - box_predictor_proto.convolutional_box_predictor.conv_hyperparams.CopyFrom( - hyperparams_proto) - box_predictor = box_predictor_builder.build( - argscope_fn=mock_conv_argscope_builder, - box_predictor_config=box_predictor_proto, - is_training=False, - num_classes=10) - (conv_hyperparams_actual, is_training) = box_predictor._conv_hyperparams_fn - self.assertAlmostEqual((hyperparams_proto.regularizer. - l1_regularizer.weight), - (conv_hyperparams_actual.regularizer.l1_regularizer. - weight)) - self.assertAlmostEqual((hyperparams_proto.initializer. - truncated_normal_initializer.stddev), - (conv_hyperparams_actual.initializer. - truncated_normal_initializer.stddev)) - self.assertAlmostEqual((hyperparams_proto.initializer. - truncated_normal_initializer.mean), - (conv_hyperparams_actual.initializer. - truncated_normal_initializer.mean)) - self.assertEqual(hyperparams_proto.activation, - conv_hyperparams_actual.activation) - self.assertFalse(is_training) - - def test_construct_non_default_conv_box_predictor(self): - box_predictor_text_proto = """ - convolutional_box_predictor { - min_depth: 2 - max_depth: 16 - num_layers_before_predictor: 2 - use_dropout: false - dropout_keep_probability: 0.4 - kernel_size: 3 - box_code_size: 3 - apply_sigmoid_to_scores: true - class_prediction_bias_init: 4.0 - use_depthwise: true - } - """ - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, hyperparams_proto) - def mock_conv_argscope_builder(conv_hyperparams_arg, is_training): - return (conv_hyperparams_arg, is_training) - - box_predictor_proto = box_predictor_pb2.BoxPredictor() - text_format.Merge(box_predictor_text_proto, box_predictor_proto) - box_predictor_proto.convolutional_box_predictor.conv_hyperparams.CopyFrom( - hyperparams_proto) - box_predictor = box_predictor_builder.build( - argscope_fn=mock_conv_argscope_builder, - box_predictor_config=box_predictor_proto, - is_training=False, - num_classes=10) - self.assertEqual(box_predictor._min_depth, 2) - self.assertEqual(box_predictor._max_depth, 16) - self.assertEqual(box_predictor._num_layers_before_predictor, 2) - self.assertFalse(box_predictor._use_dropout) - self.assertAlmostEqual(box_predictor._dropout_keep_prob, 0.4) - self.assertTrue(box_predictor._apply_sigmoid_to_scores) - self.assertAlmostEqual(box_predictor._class_prediction_bias_init, 4.0) - self.assertEqual(box_predictor.num_classes, 10) - self.assertFalse(box_predictor._is_training) - self.assertTrue(box_predictor._use_depthwise) - - def test_construct_default_conv_box_predictor(self): - box_predictor_text_proto = """ - convolutional_box_predictor { - conv_hyperparams { - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - }""" - box_predictor_proto = box_predictor_pb2.BoxPredictor() - text_format.Merge(box_predictor_text_proto, box_predictor_proto) - box_predictor = box_predictor_builder.build( - argscope_fn=hyperparams_builder.build, - box_predictor_config=box_predictor_proto, - is_training=True, - num_classes=90) - self.assertEqual(box_predictor._min_depth, 0) - self.assertEqual(box_predictor._max_depth, 0) - self.assertEqual(box_predictor._num_layers_before_predictor, 0) - self.assertTrue(box_predictor._use_dropout) - self.assertAlmostEqual(box_predictor._dropout_keep_prob, 0.8) - self.assertFalse(box_predictor._apply_sigmoid_to_scores) - self.assertEqual(box_predictor.num_classes, 90) - self.assertTrue(box_predictor._is_training) - self.assertFalse(box_predictor._use_depthwise) - - -class WeightSharedConvolutionalBoxPredictorBuilderTest(tf.test.TestCase): - - def test_box_predictor_calls_conv_argscope_fn(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - weight: 0.0003 - } - } - initializer { - truncated_normal_initializer { - mean: 0.0 - stddev: 0.3 - } - } - activation: RELU_6 - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, hyperparams_proto) - def mock_conv_argscope_builder(conv_hyperparams_arg, is_training): - return (conv_hyperparams_arg, is_training) - - box_predictor_proto = box_predictor_pb2.BoxPredictor() - (box_predictor_proto.weight_shared_convolutional_box_predictor - .conv_hyperparams.CopyFrom(hyperparams_proto)) - box_predictor = box_predictor_builder.build( - argscope_fn=mock_conv_argscope_builder, - box_predictor_config=box_predictor_proto, - is_training=False, - num_classes=10) - (conv_hyperparams_actual, is_training) = box_predictor._conv_hyperparams_fn - self.assertAlmostEqual((hyperparams_proto.regularizer. - l1_regularizer.weight), - (conv_hyperparams_actual.regularizer.l1_regularizer. - weight)) - self.assertAlmostEqual((hyperparams_proto.initializer. - truncated_normal_initializer.stddev), - (conv_hyperparams_actual.initializer. - truncated_normal_initializer.stddev)) - self.assertAlmostEqual((hyperparams_proto.initializer. - truncated_normal_initializer.mean), - (conv_hyperparams_actual.initializer. - truncated_normal_initializer.mean)) - self.assertEqual(hyperparams_proto.activation, - conv_hyperparams_actual.activation) - self.assertFalse(is_training) - - def test_construct_non_default_conv_box_predictor(self): - box_predictor_text_proto = """ - weight_shared_convolutional_box_predictor { - depth: 2 - num_layers_before_predictor: 2 - kernel_size: 7 - box_code_size: 3 - class_prediction_bias_init: 4.0 - } - """ - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, hyperparams_proto) - def mock_conv_argscope_builder(conv_hyperparams_arg, is_training): - return (conv_hyperparams_arg, is_training) - - box_predictor_proto = box_predictor_pb2.BoxPredictor() - text_format.Merge(box_predictor_text_proto, box_predictor_proto) - (box_predictor_proto.weight_shared_convolutional_box_predictor. - conv_hyperparams.CopyFrom(hyperparams_proto)) - box_predictor = box_predictor_builder.build( - argscope_fn=mock_conv_argscope_builder, - box_predictor_config=box_predictor_proto, - is_training=False, - num_classes=10) - self.assertEqual(box_predictor._depth, 2) - self.assertEqual(box_predictor._num_layers_before_predictor, 2) - self.assertAlmostEqual(box_predictor._class_prediction_bias_init, 4.0) - self.assertEqual(box_predictor.num_classes, 10) - self.assertFalse(box_predictor._is_training) - - def test_construct_default_conv_box_predictor(self): - box_predictor_text_proto = """ - weight_shared_convolutional_box_predictor { - conv_hyperparams { - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - }""" - box_predictor_proto = box_predictor_pb2.BoxPredictor() - text_format.Merge(box_predictor_text_proto, box_predictor_proto) - box_predictor = box_predictor_builder.build( - argscope_fn=hyperparams_builder.build, - box_predictor_config=box_predictor_proto, - is_training=True, - num_classes=90) - self.assertEqual(box_predictor._depth, 0) - self.assertEqual(box_predictor._num_layers_before_predictor, 0) - self.assertEqual(box_predictor.num_classes, 90) - self.assertTrue(box_predictor._is_training) - - -class MaskRCNNBoxPredictorBuilderTest(tf.test.TestCase): - - def test_box_predictor_builder_calls_fc_argscope_fn(self): - fc_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - weight: 0.0003 - } - } - initializer { - truncated_normal_initializer { - mean: 0.0 - stddev: 0.3 - } - } - activation: RELU_6 - op: FC - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(fc_hyperparams_text_proto, hyperparams_proto) - box_predictor_proto = box_predictor_pb2.BoxPredictor() - box_predictor_proto.mask_rcnn_box_predictor.fc_hyperparams.CopyFrom( - hyperparams_proto) - mock_argscope_fn = mock.Mock(return_value='arg_scope') - box_predictor = box_predictor_builder.build( - argscope_fn=mock_argscope_fn, - box_predictor_config=box_predictor_proto, - is_training=False, - num_classes=10) - mock_argscope_fn.assert_called_with(hyperparams_proto, False) - self.assertEqual(box_predictor._fc_hyperparams_fn, 'arg_scope') - - def test_non_default_mask_rcnn_box_predictor(self): - fc_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - activation: RELU_6 - op: FC - """ - box_predictor_text_proto = """ - mask_rcnn_box_predictor { - use_dropout: true - dropout_keep_probability: 0.8 - box_code_size: 3 - share_box_across_classes: true - } - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(fc_hyperparams_text_proto, hyperparams_proto) - def mock_fc_argscope_builder(fc_hyperparams_arg, is_training): - return (fc_hyperparams_arg, is_training) - - box_predictor_proto = box_predictor_pb2.BoxPredictor() - text_format.Merge(box_predictor_text_proto, box_predictor_proto) - box_predictor_proto.mask_rcnn_box_predictor.fc_hyperparams.CopyFrom( - hyperparams_proto) - box_predictor = box_predictor_builder.build( - argscope_fn=mock_fc_argscope_builder, - box_predictor_config=box_predictor_proto, - is_training=True, - num_classes=90) - self.assertTrue(box_predictor._use_dropout) - self.assertAlmostEqual(box_predictor._dropout_keep_prob, 0.8) - self.assertEqual(box_predictor.num_classes, 90) - self.assertTrue(box_predictor._is_training) - self.assertEqual(box_predictor._box_code_size, 3) - self.assertEqual(box_predictor._share_box_across_classes, True) - - def test_build_default_mask_rcnn_box_predictor(self): - box_predictor_proto = box_predictor_pb2.BoxPredictor() - box_predictor_proto.mask_rcnn_box_predictor.fc_hyperparams.op = ( - hyperparams_pb2.Hyperparams.FC) - box_predictor = box_predictor_builder.build( - argscope_fn=mock.Mock(return_value='arg_scope'), - box_predictor_config=box_predictor_proto, - is_training=True, - num_classes=90) - self.assertFalse(box_predictor._use_dropout) - self.assertAlmostEqual(box_predictor._dropout_keep_prob, 0.5) - self.assertEqual(box_predictor.num_classes, 90) - self.assertTrue(box_predictor._is_training) - self.assertEqual(box_predictor._box_code_size, 4) - self.assertFalse(box_predictor._predict_instance_masks) - self.assertFalse(box_predictor._predict_keypoints) - - def test_build_box_predictor_with_mask_branch(self): - box_predictor_proto = box_predictor_pb2.BoxPredictor() - box_predictor_proto.mask_rcnn_box_predictor.fc_hyperparams.op = ( - hyperparams_pb2.Hyperparams.FC) - box_predictor_proto.mask_rcnn_box_predictor.conv_hyperparams.op = ( - hyperparams_pb2.Hyperparams.CONV) - box_predictor_proto.mask_rcnn_box_predictor.predict_instance_masks = True - box_predictor_proto.mask_rcnn_box_predictor.mask_prediction_conv_depth = 512 - box_predictor_proto.mask_rcnn_box_predictor.mask_height = 16 - box_predictor_proto.mask_rcnn_box_predictor.mask_width = 16 - mock_argscope_fn = mock.Mock(return_value='arg_scope') - box_predictor = box_predictor_builder.build( - argscope_fn=mock_argscope_fn, - box_predictor_config=box_predictor_proto, - is_training=True, - num_classes=90) - mock_argscope_fn.assert_has_calls( - [mock.call(box_predictor_proto.mask_rcnn_box_predictor.fc_hyperparams, - True), - mock.call(box_predictor_proto.mask_rcnn_box_predictor.conv_hyperparams, - True)], any_order=True) - self.assertFalse(box_predictor._use_dropout) - self.assertAlmostEqual(box_predictor._dropout_keep_prob, 0.5) - self.assertEqual(box_predictor.num_classes, 90) - self.assertTrue(box_predictor._is_training) - self.assertEqual(box_predictor._box_code_size, 4) - self.assertTrue(box_predictor._predict_instance_masks) - self.assertEqual(box_predictor._mask_prediction_conv_depth, 512) - self.assertFalse(box_predictor._predict_keypoints) - - -class RfcnBoxPredictorBuilderTest(tf.test.TestCase): - - def test_box_predictor_calls_fc_argscope_fn(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - weight: 0.0003 - } - } - initializer { - truncated_normal_initializer { - mean: 0.0 - stddev: 0.3 - } - } - activation: RELU_6 - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, hyperparams_proto) - def mock_conv_argscope_builder(conv_hyperparams_arg, is_training): - return (conv_hyperparams_arg, is_training) - - box_predictor_proto = box_predictor_pb2.BoxPredictor() - box_predictor_proto.rfcn_box_predictor.conv_hyperparams.CopyFrom( - hyperparams_proto) - box_predictor = box_predictor_builder.build( - argscope_fn=mock_conv_argscope_builder, - box_predictor_config=box_predictor_proto, - is_training=False, - num_classes=10) - (conv_hyperparams_actual, is_training) = box_predictor._conv_hyperparams_fn - self.assertAlmostEqual((hyperparams_proto.regularizer. - l1_regularizer.weight), - (conv_hyperparams_actual.regularizer.l1_regularizer. - weight)) - self.assertAlmostEqual((hyperparams_proto.initializer. - truncated_normal_initializer.stddev), - (conv_hyperparams_actual.initializer. - truncated_normal_initializer.stddev)) - self.assertAlmostEqual((hyperparams_proto.initializer. - truncated_normal_initializer.mean), - (conv_hyperparams_actual.initializer. - truncated_normal_initializer.mean)) - self.assertEqual(hyperparams_proto.activation, - conv_hyperparams_actual.activation) - self.assertFalse(is_training) - - def test_non_default_rfcn_box_predictor(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - activation: RELU_6 - """ - box_predictor_text_proto = """ - rfcn_box_predictor { - num_spatial_bins_height: 4 - num_spatial_bins_width: 4 - depth: 4 - box_code_size: 3 - crop_height: 16 - crop_width: 16 - } - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, hyperparams_proto) - def mock_conv_argscope_builder(conv_hyperparams_arg, is_training): - return (conv_hyperparams_arg, is_training) - - box_predictor_proto = box_predictor_pb2.BoxPredictor() - text_format.Merge(box_predictor_text_proto, box_predictor_proto) - box_predictor_proto.rfcn_box_predictor.conv_hyperparams.CopyFrom( - hyperparams_proto) - box_predictor = box_predictor_builder.build( - argscope_fn=mock_conv_argscope_builder, - box_predictor_config=box_predictor_proto, - is_training=True, - num_classes=90) - self.assertEqual(box_predictor.num_classes, 90) - self.assertTrue(box_predictor._is_training) - self.assertEqual(box_predictor._box_code_size, 3) - self.assertEqual(box_predictor._num_spatial_bins, [4, 4]) - self.assertEqual(box_predictor._crop_size, [16, 16]) - - def test_default_rfcn_box_predictor(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - activation: RELU_6 - """ - hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, hyperparams_proto) - def mock_conv_argscope_builder(conv_hyperparams_arg, is_training): - return (conv_hyperparams_arg, is_training) - - box_predictor_proto = box_predictor_pb2.BoxPredictor() - box_predictor_proto.rfcn_box_predictor.conv_hyperparams.CopyFrom( - hyperparams_proto) - box_predictor = box_predictor_builder.build( - argscope_fn=mock_conv_argscope_builder, - box_predictor_config=box_predictor_proto, - is_training=True, - num_classes=90) - self.assertEqual(box_predictor.num_classes, 90) - self.assertTrue(box_predictor._is_training) - self.assertEqual(box_predictor._box_code_size, 4) - self.assertEqual(box_predictor._num_spatial_bins, [3, 3]) - self.assertEqual(box_predictor._crop_size, [12, 12]) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/dataset_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/dataset_builder.py deleted file mode 100644 index 3628a85ea..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/dataset_builder.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""tf.data.Dataset builder. - -Creates data sources for DetectionModels from an InputReader config. See -input_reader.proto for options. - -Note: If users wishes to also use their own InputReaders with the Object -Detection configuration framework, they should define their own builder function -that wraps the build function. -""" -import functools -import tensorflow as tf - -from object_detection.core import standard_fields as fields -from object_detection.data_decoders import tf_example_decoder -from object_detection.protos import input_reader_pb2 -from object_detection.utils import dataset_util - - -def _get_padding_shapes(dataset, max_num_boxes=None, num_classes=None, - spatial_image_shape=None): - """Returns shapes to pad dataset tensors to before batching. - - Args: - dataset: tf.data.Dataset object. - max_num_boxes: Max number of groundtruth boxes needed to computes shapes for - padding. - num_classes: Number of classes in the dataset needed to compute shapes for - padding. - spatial_image_shape: A list of two integers of the form [height, width] - containing expected spatial shape of the image. - - Returns: - A dictionary keyed by fields.InputDataFields containing padding shapes for - tensors in the dataset. - - Raises: - ValueError: If groundtruth classes is neither rank 1 nor rank 2. - """ - - if not spatial_image_shape or spatial_image_shape == [-1, -1]: - height, width = None, None - else: - height, width = spatial_image_shape # pylint: disable=unpacking-non-sequence - - num_additional_channels = 0 - if fields.InputDataFields.image_additional_channels in dataset.output_shapes: - num_additional_channels = dataset.output_shapes[ - fields.InputDataFields.image_additional_channels].dims[2].value - padding_shapes = { - # Additional channels are merged before batching. - fields.InputDataFields.image: [ - height, width, 3 + num_additional_channels - ], - fields.InputDataFields.image_additional_channels: [ - height, width, num_additional_channels - ], - fields.InputDataFields.source_id: [], - fields.InputDataFields.filename: [], - fields.InputDataFields.key: [], - fields.InputDataFields.groundtruth_difficult: [max_num_boxes], - fields.InputDataFields.groundtruth_boxes: [max_num_boxes, 4], - fields.InputDataFields.groundtruth_instance_masks: [ - max_num_boxes, height, width - ], - fields.InputDataFields.groundtruth_is_crowd: [max_num_boxes], - fields.InputDataFields.groundtruth_group_of: [max_num_boxes], - fields.InputDataFields.groundtruth_area: [max_num_boxes], - fields.InputDataFields.groundtruth_weights: [max_num_boxes], - fields.InputDataFields.num_groundtruth_boxes: [], - fields.InputDataFields.groundtruth_label_types: [max_num_boxes], - fields.InputDataFields.groundtruth_label_scores: [max_num_boxes], - fields.InputDataFields.true_image_shape: [3], - fields.InputDataFields.multiclass_scores: [ - max_num_boxes, num_classes + 1 if num_classes is not None else None - ], - } - # Determine whether groundtruth_classes are integers or one-hot encodings, and - # apply batching appropriately. - classes_shape = dataset.output_shapes[ - fields.InputDataFields.groundtruth_classes] - if len(classes_shape) == 1: # Class integers. - padding_shapes[fields.InputDataFields.groundtruth_classes] = [max_num_boxes] - elif len(classes_shape) == 2: # One-hot or k-hot encoding. - padding_shapes[fields.InputDataFields.groundtruth_classes] = [ - max_num_boxes, num_classes] - else: - raise ValueError('Groundtruth classes must be a rank 1 tensor (classes) or ' - 'rank 2 tensor (one-hot encodings)') - - if fields.InputDataFields.original_image in dataset.output_shapes: - padding_shapes[fields.InputDataFields.original_image] = [ - None, None, 3 + num_additional_channels - ] - if fields.InputDataFields.groundtruth_keypoints in dataset.output_shapes: - tensor_shape = dataset.output_shapes[fields.InputDataFields. - groundtruth_keypoints] - padding_shape = [max_num_boxes, tensor_shape[1].value, - tensor_shape[2].value] - padding_shapes[fields.InputDataFields.groundtruth_keypoints] = padding_shape - if (fields.InputDataFields.groundtruth_keypoint_visibilities - in dataset.output_shapes): - tensor_shape = dataset.output_shapes[fields.InputDataFields. - groundtruth_keypoint_visibilities] - padding_shape = [max_num_boxes, tensor_shape[1].value] - padding_shapes[fields.InputDataFields. - groundtruth_keypoint_visibilities] = padding_shape - return {tensor_key: padding_shapes[tensor_key] - for tensor_key, _ in dataset.output_shapes.items()} - - -def build(input_reader_config, - transform_input_data_fn=None, - batch_size=None, - max_num_boxes=None, - num_classes=None, - spatial_image_shape=None, - num_additional_channels=0): - """Builds a tf.data.Dataset. - - Builds a tf.data.Dataset by applying the `transform_input_data_fn` on all - records. Applies a padded batch to the resulting dataset. - - Args: - input_reader_config: A input_reader_pb2.InputReader object. - transform_input_data_fn: Function to apply to all records, or None if - no extra decoding is required. - batch_size: Batch size. If None, batching is not performed. - max_num_boxes: Max number of groundtruth boxes needed to compute shapes for - padding. If None, will use a dynamic shape. - num_classes: Number of classes in the dataset needed to compute shapes for - padding. If None, will use a dynamic shape. - spatial_image_shape: A list of two integers of the form [height, width] - containing expected spatial shape of the image after applying - transform_input_data_fn. If None, will use dynamic shapes. - num_additional_channels: Number of additional channels to use in the input. - - Returns: - A tf.data.Dataset based on the input_reader_config. - - Raises: - ValueError: On invalid input reader proto. - ValueError: If no input paths are specified. - """ - if not isinstance(input_reader_config, input_reader_pb2.InputReader): - raise ValueError('input_reader_config not of type ' - 'input_reader_pb2.InputReader.') - - if input_reader_config.WhichOneof('input_reader') == 'tf_record_input_reader': - config = input_reader_config.tf_record_input_reader - if not config.input_path: - raise ValueError('At least one input path must be specified in ' - '`input_reader_config`.') - - label_map_proto_file = None - if input_reader_config.HasField('label_map_path'): - label_map_proto_file = input_reader_config.label_map_path - decoder = tf_example_decoder.TfExampleDecoder( - load_instance_masks=input_reader_config.load_instance_masks, - instance_mask_type=input_reader_config.mask_type, - label_map_proto_file=label_map_proto_file, - use_display_name=input_reader_config.use_display_name, - num_additional_channels=num_additional_channels) - - def process_fn(value): - processed = decoder.decode(value) - if transform_input_data_fn is not None: - return transform_input_data_fn(processed) - return processed - - dataset = dataset_util.read_dataset( - functools.partial(tf.data.TFRecordDataset, buffer_size=8 * 1000 * 1000), - process_fn, config.input_path[:], input_reader_config) - - if batch_size: - padding_shapes = _get_padding_shapes(dataset, max_num_boxes, num_classes, - spatial_image_shape) - dataset = dataset.apply( - tf.contrib.data.padded_batch_and_drop_remainder(batch_size, - padding_shapes)) - return dataset - - raise ValueError('Unsupported input_reader_config.') diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/dataset_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/dataset_builder_test.py deleted file mode 100644 index 0f1360f5e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/dataset_builder_test.py +++ /dev/null @@ -1,260 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for dataset_builder.""" - -import os -import numpy as np -import tensorflow as tf - -from google.protobuf import text_format - -from tensorflow.core.example import example_pb2 -from tensorflow.core.example import feature_pb2 -from object_detection.builders import dataset_builder -from object_detection.core import standard_fields as fields -from object_detection.protos import input_reader_pb2 -from object_detection.utils import dataset_util - - -class DatasetBuilderTest(tf.test.TestCase): - - def create_tf_record(self, has_additional_channels=False): - path = os.path.join(self.get_temp_dir(), 'tfrecord') - writer = tf.python_io.TFRecordWriter(path) - - image_tensor = np.random.randint(255, size=(4, 5, 3)).astype(np.uint8) - additional_channels_tensor = np.random.randint( - 255, size=(4, 5, 1)).astype(np.uint8) - flat_mask = (4 * 5) * [1.0] - with self.test_session(): - encoded_jpeg = tf.image.encode_jpeg(tf.constant(image_tensor)).eval() - encoded_additional_channels_jpeg = tf.image.encode_jpeg( - tf.constant(additional_channels_tensor)).eval() - features = { - 'image/encoded': - feature_pb2.Feature( - bytes_list=feature_pb2.BytesList(value=[encoded_jpeg])), - 'image/format': - feature_pb2.Feature( - bytes_list=feature_pb2.BytesList(value=['jpeg'.encode('utf-8')]) - ), - 'image/height': - feature_pb2.Feature(int64_list=feature_pb2.Int64List(value=[4])), - 'image/width': - feature_pb2.Feature(int64_list=feature_pb2.Int64List(value=[5])), - 'image/object/bbox/xmin': - feature_pb2.Feature(float_list=feature_pb2.FloatList(value=[0.0])), - 'image/object/bbox/xmax': - feature_pb2.Feature(float_list=feature_pb2.FloatList(value=[1.0])), - 'image/object/bbox/ymin': - feature_pb2.Feature(float_list=feature_pb2.FloatList(value=[0.0])), - 'image/object/bbox/ymax': - feature_pb2.Feature(float_list=feature_pb2.FloatList(value=[1.0])), - 'image/object/class/label': - feature_pb2.Feature(int64_list=feature_pb2.Int64List(value=[2])), - 'image/object/mask': - feature_pb2.Feature( - float_list=feature_pb2.FloatList(value=flat_mask)), - } - if has_additional_channels: - features['image/additional_channels/encoded'] = feature_pb2.Feature( - bytes_list=feature_pb2.BytesList( - value=[encoded_additional_channels_jpeg] * 2)) - example = example_pb2.Example( - features=feature_pb2.Features(feature=features)) - writer.write(example.SerializeToString()) - writer.close() - - return path - - def test_build_tf_record_input_reader(self): - tf_record_path = self.create_tf_record() - - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - tf_record_input_reader {{ - input_path: '{0}' - }} - """.format(tf_record_path) - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - tensor_dict = dataset_util.make_initializable_iterator( - dataset_builder.build(input_reader_proto, batch_size=1)).get_next() - - sv = tf.train.Supervisor(logdir=self.get_temp_dir()) - with sv.prepare_or_wait_for_session() as sess: - sv.start_queue_runners(sess) - output_dict = sess.run(tensor_dict) - - self.assertTrue( - fields.InputDataFields.groundtruth_instance_masks not in output_dict) - self.assertEquals((1, 4, 5, 3), - output_dict[fields.InputDataFields.image].shape) - self.assertAllEqual([[2]], - output_dict[fields.InputDataFields.groundtruth_classes]) - self.assertEquals( - (1, 1, 4), output_dict[fields.InputDataFields.groundtruth_boxes].shape) - self.assertAllEqual( - [0.0, 0.0, 1.0, 1.0], - output_dict[fields.InputDataFields.groundtruth_boxes][0][0]) - - def test_build_tf_record_input_reader_and_load_instance_masks(self): - tf_record_path = self.create_tf_record() - - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - load_instance_masks: true - tf_record_input_reader {{ - input_path: '{0}' - }} - """.format(tf_record_path) - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - tensor_dict = dataset_util.make_initializable_iterator( - dataset_builder.build(input_reader_proto, batch_size=1)).get_next() - - sv = tf.train.Supervisor(logdir=self.get_temp_dir()) - with sv.prepare_or_wait_for_session() as sess: - sv.start_queue_runners(sess) - output_dict = sess.run(tensor_dict) - self.assertAllEqual( - (1, 1, 4, 5), - output_dict[fields.InputDataFields.groundtruth_instance_masks].shape) - - def test_build_tf_record_input_reader_with_batch_size_two(self): - tf_record_path = self.create_tf_record() - - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - tf_record_input_reader {{ - input_path: '{0}' - }} - """.format(tf_record_path) - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - - def one_hot_class_encoding_fn(tensor_dict): - tensor_dict[fields.InputDataFields.groundtruth_classes] = tf.one_hot( - tensor_dict[fields.InputDataFields.groundtruth_classes] - 1, depth=3) - return tensor_dict - - tensor_dict = dataset_util.make_initializable_iterator( - dataset_builder.build( - input_reader_proto, - transform_input_data_fn=one_hot_class_encoding_fn, - batch_size=2, - max_num_boxes=2, - num_classes=3, - spatial_image_shape=[4, 5])).get_next() - - sv = tf.train.Supervisor(logdir=self.get_temp_dir()) - with sv.prepare_or_wait_for_session() as sess: - sv.start_queue_runners(sess) - output_dict = sess.run(tensor_dict) - - self.assertAllEqual([2, 4, 5, 3], - output_dict[fields.InputDataFields.image].shape) - self.assertAllEqual([2, 2, 3], - output_dict[fields.InputDataFields.groundtruth_classes]. - shape) - self.assertAllEqual([2, 2, 4], - output_dict[fields.InputDataFields.groundtruth_boxes]. - shape) - self.assertAllEqual( - [[[0.0, 0.0, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]], - [[0.0, 0.0, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]], - output_dict[fields.InputDataFields.groundtruth_boxes]) - - def test_build_tf_record_input_reader_with_batch_size_two_and_masks(self): - tf_record_path = self.create_tf_record() - - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - load_instance_masks: true - tf_record_input_reader {{ - input_path: '{0}' - }} - """.format(tf_record_path) - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - - def one_hot_class_encoding_fn(tensor_dict): - tensor_dict[fields.InputDataFields.groundtruth_classes] = tf.one_hot( - tensor_dict[fields.InputDataFields.groundtruth_classes] - 1, depth=3) - return tensor_dict - - tensor_dict = dataset_util.make_initializable_iterator( - dataset_builder.build( - input_reader_proto, - transform_input_data_fn=one_hot_class_encoding_fn, - batch_size=2, - max_num_boxes=2, - num_classes=3, - spatial_image_shape=[4, 5])).get_next() - - sv = tf.train.Supervisor(logdir=self.get_temp_dir()) - with sv.prepare_or_wait_for_session() as sess: - sv.start_queue_runners(sess) - output_dict = sess.run(tensor_dict) - - self.assertAllEqual( - [2, 2, 4, 5], - output_dict[fields.InputDataFields.groundtruth_instance_masks].shape) - - def test_build_tf_record_input_reader_with_additional_channels(self): - tf_record_path = self.create_tf_record(has_additional_channels=True) - - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - tf_record_input_reader {{ - input_path: '{0}' - }} - """.format(tf_record_path) - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - tensor_dict = dataset_util.make_initializable_iterator( - dataset_builder.build( - input_reader_proto, batch_size=2, - num_additional_channels=2)).get_next() - - sv = tf.train.Supervisor(logdir=self.get_temp_dir()) - with sv.prepare_or_wait_for_session() as sess: - sv.start_queue_runners(sess) - output_dict = sess.run(tensor_dict) - - self.assertEquals((2, 4, 5, 5), - output_dict[fields.InputDataFields.image].shape) - - def test_raises_error_with_no_input_paths(self): - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - load_instance_masks: true - """ - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - with self.assertRaises(ValueError): - dataset_builder.build(input_reader_proto) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/graph_rewriter_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/graph_rewriter_builder.py deleted file mode 100644 index 77e60479b..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/graph_rewriter_builder.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2018 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Functions for quantized training and evaluation.""" - -import tensorflow as tf - - -def build(graph_rewriter_config, is_training): - """Returns a function that modifies default graph based on options. - - Args: - graph_rewriter_config: graph_rewriter_pb2.GraphRewriter proto. - is_training: whether in training of eval mode. - """ - def graph_rewrite_fn(): - """Function to quantize weights and activation of the default graph.""" - if (graph_rewriter_config.quantization.weight_bits != 8 or - graph_rewriter_config.quantization.activation_bits != 8): - raise ValueError('Only 8bit quantization is supported') - - # Quantize the graph by inserting quantize ops for weights and activations - if is_training: - tf.contrib.quantize.create_training_graph( - input_graph=tf.get_default_graph(), - quant_delay=graph_rewriter_config.quantization.delay) - else: - tf.contrib.quantize.create_eval_graph(input_graph=tf.get_default_graph()) - - tf.contrib.layers.summarize_collection('quant_vars') - return graph_rewrite_fn diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/graph_rewriter_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/graph_rewriter_builder_test.py deleted file mode 100644 index 5f38d5a27..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/graph_rewriter_builder_test.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2018 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for graph_rewriter_builder.""" -import mock -import tensorflow as tf -from object_detection.builders import graph_rewriter_builder -from object_detection.protos import graph_rewriter_pb2 - - -class QuantizationBuilderTest(tf.test.TestCase): - - def testQuantizationBuilderSetsUpCorrectTrainArguments(self): - with mock.patch.object( - tf.contrib.quantize, 'create_training_graph') as mock_quant_fn: - with mock.patch.object(tf.contrib.layers, - 'summarize_collection') as mock_summarize_col: - graph_rewriter_proto = graph_rewriter_pb2.GraphRewriter() - graph_rewriter_proto.quantization.delay = 10 - graph_rewriter_proto.quantization.weight_bits = 8 - graph_rewriter_proto.quantization.activation_bits = 8 - graph_rewrite_fn = graph_rewriter_builder.build( - graph_rewriter_proto, is_training=True) - graph_rewrite_fn() - _, kwargs = mock_quant_fn.call_args - self.assertEqual(kwargs['input_graph'], tf.get_default_graph()) - self.assertEqual(kwargs['quant_delay'], 10) - mock_summarize_col.assert_called_with('quant_vars') - - def testQuantizationBuilderSetsUpCorrectEvalArguments(self): - with mock.patch.object(tf.contrib.quantize, - 'create_eval_graph') as mock_quant_fn: - with mock.patch.object(tf.contrib.layers, - 'summarize_collection') as mock_summarize_col: - graph_rewriter_proto = graph_rewriter_pb2.GraphRewriter() - graph_rewriter_proto.quantization.delay = 10 - graph_rewrite_fn = graph_rewriter_builder.build( - graph_rewriter_proto, is_training=False) - graph_rewrite_fn() - _, kwargs = mock_quant_fn.call_args - self.assertEqual(kwargs['input_graph'], tf.get_default_graph()) - mock_summarize_col.assert_called_with('quant_vars') - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/hyperparams_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/hyperparams_builder.py deleted file mode 100644 index 05addddaa..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/hyperparams_builder.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Builder function to construct tf-slim arg_scope for convolution, fc ops.""" -import tensorflow as tf - -from object_detection.protos import hyperparams_pb2 -from object_detection.utils import context_manager - -slim = tf.contrib.slim - - -def build(hyperparams_config, is_training): - """Builds tf-slim arg_scope for convolution ops based on the config. - - Returns an arg_scope to use for convolution ops containing weights - initializer, weights regularizer, activation function, batch norm function - and batch norm parameters based on the configuration. - - Note that if the batch_norm parameteres are not specified in the config - (i.e. left to default) then batch norm is excluded from the arg_scope. - - The batch norm parameters are set for updates based on `is_training` argument - and conv_hyperparams_config.batch_norm.train parameter. During training, they - are updated only if batch_norm.train parameter is true. However, during eval, - no updates are made to the batch norm variables. In both cases, their current - values are used during forward pass. - - Args: - hyperparams_config: hyperparams.proto object containing - hyperparameters. - is_training: Whether the network is in training mode. - - Returns: - arg_scope_fn: A function to construct tf-slim arg_scope containing - hyperparameters for ops. - - Raises: - ValueError: if hyperparams_config is not of type hyperparams.Hyperparams. - """ - if not isinstance(hyperparams_config, - hyperparams_pb2.Hyperparams): - raise ValueError('hyperparams_config not of type ' - 'hyperparams_pb.Hyperparams.') - - batch_norm = None - batch_norm_params = None - if hyperparams_config.HasField('batch_norm'): - batch_norm = slim.batch_norm - batch_norm_params = _build_batch_norm_params( - hyperparams_config.batch_norm, is_training) - - affected_ops = [slim.conv2d, slim.separable_conv2d, slim.conv2d_transpose] - if hyperparams_config.HasField('op') and ( - hyperparams_config.op == hyperparams_pb2.Hyperparams.FC): - affected_ops = [slim.fully_connected] - def scope_fn(): - with (slim.arg_scope([slim.batch_norm], **batch_norm_params) - if batch_norm_params is not None else - context_manager.IdentityContextManager()): - with slim.arg_scope( - affected_ops, - weights_regularizer=_build_regularizer( - hyperparams_config.regularizer), - weights_initializer=_build_initializer( - hyperparams_config.initializer), - activation_fn=_build_activation_fn(hyperparams_config.activation), - normalizer_fn=batch_norm) as sc: - return sc - - return scope_fn - - -def _build_activation_fn(activation_fn): - """Builds a callable activation from config. - - Args: - activation_fn: hyperparams_pb2.Hyperparams.activation - - Returns: - Callable activation function. - - Raises: - ValueError: On unknown activation function. - """ - if activation_fn == hyperparams_pb2.Hyperparams.NONE: - return None - if activation_fn == hyperparams_pb2.Hyperparams.RELU: - return tf.nn.relu - if activation_fn == hyperparams_pb2.Hyperparams.RELU_6: - return tf.nn.relu6 - raise ValueError('Unknown activation function: {}'.format(activation_fn)) - - -def _build_regularizer(regularizer): - """Builds a tf-slim regularizer from config. - - Args: - regularizer: hyperparams_pb2.Hyperparams.regularizer proto. - - Returns: - tf-slim regularizer. - - Raises: - ValueError: On unknown regularizer. - """ - regularizer_oneof = regularizer.WhichOneof('regularizer_oneof') - if regularizer_oneof == 'l1_regularizer': - return slim.l1_regularizer(scale=float(regularizer.l1_regularizer.weight)) - if regularizer_oneof == 'l2_regularizer': - return slim.l2_regularizer(scale=float(regularizer.l2_regularizer.weight)) - raise ValueError('Unknown regularizer function: {}'.format(regularizer_oneof)) - - -def _build_initializer(initializer): - """Build a tf initializer from config. - - Args: - initializer: hyperparams_pb2.Hyperparams.regularizer proto. - - Returns: - tf initializer. - - Raises: - ValueError: On unknown initializer. - """ - initializer_oneof = initializer.WhichOneof('initializer_oneof') - if initializer_oneof == 'truncated_normal_initializer': - return tf.truncated_normal_initializer( - mean=initializer.truncated_normal_initializer.mean, - stddev=initializer.truncated_normal_initializer.stddev) - if initializer_oneof == 'random_normal_initializer': - return tf.random_normal_initializer( - mean=initializer.random_normal_initializer.mean, - stddev=initializer.random_normal_initializer.stddev) - if initializer_oneof == 'variance_scaling_initializer': - enum_descriptor = (hyperparams_pb2.VarianceScalingInitializer. - DESCRIPTOR.enum_types_by_name['Mode']) - mode = enum_descriptor.values_by_number[initializer. - variance_scaling_initializer. - mode].name - return slim.variance_scaling_initializer( - factor=initializer.variance_scaling_initializer.factor, - mode=mode, - uniform=initializer.variance_scaling_initializer.uniform) - raise ValueError('Unknown initializer function: {}'.format( - initializer_oneof)) - - -def _build_batch_norm_params(batch_norm, is_training): - """Build a dictionary of batch_norm params from config. - - Args: - batch_norm: hyperparams_pb2.ConvHyperparams.batch_norm proto. - is_training: Whether the models is in training mode. - - Returns: - A dictionary containing batch_norm parameters. - """ - batch_norm_params = { - 'decay': batch_norm.decay, - 'center': batch_norm.center, - 'scale': batch_norm.scale, - 'epsilon': batch_norm.epsilon, - # Remove is_training parameter from here and deprecate it in the proto - # once we refactor Faster RCNN models to set is_training through an outer - # arg_scope in the meta architecture. - 'is_training': is_training and batch_norm.train, - } - return batch_norm_params diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/hyperparams_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/hyperparams_builder_test.py deleted file mode 100644 index 943532fbe..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/hyperparams_builder_test.py +++ /dev/null @@ -1,509 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests object_detection.core.hyperparams_builder.""" - -import numpy as np -import tensorflow as tf - -from google.protobuf import text_format - -from object_detection.builders import hyperparams_builder -from object_detection.protos import hyperparams_pb2 - -slim = tf.contrib.slim - - -def _get_scope_key(op): - return getattr(op, '_key_op', str(op)) - - -class HyperparamsBuilderTest(tf.test.TestCase): - - def test_default_arg_scope_has_conv2d_op(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - self.assertTrue(_get_scope_key(slim.conv2d) in scope) - - def test_default_arg_scope_has_separable_conv2d_op(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - self.assertTrue(_get_scope_key(slim.separable_conv2d) in scope) - - def test_default_arg_scope_has_conv2d_transpose_op(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - self.assertTrue(_get_scope_key(slim.conv2d_transpose) in scope) - - def test_explicit_fc_op_arg_scope_has_fully_connected_op(self): - conv_hyperparams_text_proto = """ - op: FC - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - self.assertTrue(_get_scope_key(slim.fully_connected) in scope) - - def test_separable_conv2d_and_conv2d_and_transpose_have_same_parameters(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - kwargs_1, kwargs_2, kwargs_3 = scope.values() - self.assertDictEqual(kwargs_1, kwargs_2) - self.assertDictEqual(kwargs_1, kwargs_3) - - def test_return_l1_regularized_weights(self): - conv_hyperparams_text_proto = """ - regularizer { - l1_regularizer { - weight: 0.5 - } - } - initializer { - truncated_normal_initializer { - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope.values()[0] - regularizer = conv_scope_arguments['weights_regularizer'] - weights = np.array([1., -1, 4., 2.]) - with self.test_session() as sess: - result = sess.run(regularizer(tf.constant(weights))) - self.assertAllClose(np.abs(weights).sum() * 0.5, result) - - def test_return_l2_regularizer_weights(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - weight: 0.42 - } - } - initializer { - truncated_normal_initializer { - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - - regularizer = conv_scope_arguments['weights_regularizer'] - weights = np.array([1., -1, 4., 2.]) - with self.test_session() as sess: - result = sess.run(regularizer(tf.constant(weights))) - self.assertAllClose(np.power(weights, 2).sum() / 2.0 * 0.42, result) - - def test_return_non_default_batch_norm_params_with_train_during_train(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - batch_norm { - decay: 0.7 - center: false - scale: true - epsilon: 0.03 - train: true - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - self.assertEqual(conv_scope_arguments['normalizer_fn'], slim.batch_norm) - batch_norm_params = scope[_get_scope_key(slim.batch_norm)] - self.assertAlmostEqual(batch_norm_params['decay'], 0.7) - self.assertAlmostEqual(batch_norm_params['epsilon'], 0.03) - self.assertFalse(batch_norm_params['center']) - self.assertTrue(batch_norm_params['scale']) - self.assertTrue(batch_norm_params['is_training']) - - def test_return_batch_norm_params_with_notrain_during_eval(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - batch_norm { - decay: 0.7 - center: false - scale: true - epsilon: 0.03 - train: true - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=False) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - self.assertEqual(conv_scope_arguments['normalizer_fn'], slim.batch_norm) - batch_norm_params = scope[_get_scope_key(slim.batch_norm)] - self.assertAlmostEqual(batch_norm_params['decay'], 0.7) - self.assertAlmostEqual(batch_norm_params['epsilon'], 0.03) - self.assertFalse(batch_norm_params['center']) - self.assertTrue(batch_norm_params['scale']) - self.assertFalse(batch_norm_params['is_training']) - - def test_return_batch_norm_params_with_notrain_when_train_is_false(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - batch_norm { - decay: 0.7 - center: false - scale: true - epsilon: 0.03 - train: false - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - self.assertEqual(conv_scope_arguments['normalizer_fn'], slim.batch_norm) - batch_norm_params = scope[_get_scope_key(slim.batch_norm)] - self.assertAlmostEqual(batch_norm_params['decay'], 0.7) - self.assertAlmostEqual(batch_norm_params['epsilon'], 0.03) - self.assertFalse(batch_norm_params['center']) - self.assertTrue(batch_norm_params['scale']) - self.assertFalse(batch_norm_params['is_training']) - - def test_do_not_use_batch_norm_if_default(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - self.assertEqual(conv_scope_arguments['normalizer_fn'], None) - - def test_use_none_activation(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - activation: NONE - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - self.assertEqual(conv_scope_arguments['activation_fn'], None) - - def test_use_relu_activation(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - activation: RELU - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - self.assertEqual(conv_scope_arguments['activation_fn'], tf.nn.relu) - - def test_use_relu_6_activation(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - activation: RELU_6 - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - self.assertEqual(conv_scope_arguments['activation_fn'], tf.nn.relu6) - - def _assert_variance_in_range(self, initializer, shape, variance, - tol=1e-2): - with tf.Graph().as_default() as g: - with self.test_session(graph=g) as sess: - var = tf.get_variable( - name='test', - shape=shape, - dtype=tf.float32, - initializer=initializer) - sess.run(tf.global_variables_initializer()) - values = sess.run(var) - self.assertAllClose(np.var(values), variance, tol, tol) - - def test_variance_in_range_with_variance_scaling_initializer_fan_in(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - variance_scaling_initializer { - factor: 2.0 - mode: FAN_IN - uniform: false - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - initializer = conv_scope_arguments['weights_initializer'] - self._assert_variance_in_range(initializer, shape=[100, 40], - variance=2. / 100.) - - def test_variance_in_range_with_variance_scaling_initializer_fan_out(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - variance_scaling_initializer { - factor: 2.0 - mode: FAN_OUT - uniform: false - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - initializer = conv_scope_arguments['weights_initializer'] - self._assert_variance_in_range(initializer, shape=[100, 40], - variance=2. / 40.) - - def test_variance_in_range_with_variance_scaling_initializer_fan_avg(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - variance_scaling_initializer { - factor: 2.0 - mode: FAN_AVG - uniform: false - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - initializer = conv_scope_arguments['weights_initializer'] - self._assert_variance_in_range(initializer, shape=[100, 40], - variance=4. / (100. + 40.)) - - def test_variance_in_range_with_variance_scaling_initializer_uniform(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - variance_scaling_initializer { - factor: 2.0 - mode: FAN_IN - uniform: true - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - initializer = conv_scope_arguments['weights_initializer'] - self._assert_variance_in_range(initializer, shape=[100, 40], - variance=2. / 100.) - - def test_variance_in_range_with_truncated_normal_initializer(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - mean: 0.0 - stddev: 0.8 - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - initializer = conv_scope_arguments['weights_initializer'] - self._assert_variance_in_range(initializer, shape=[100, 40], - variance=0.49, tol=1e-1) - - def test_variance_in_range_with_random_normal_initializer(self): - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - random_normal_initializer { - mean: 0.0 - stddev: 0.8 - } - } - """ - conv_hyperparams_proto = hyperparams_pb2.Hyperparams() - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams_proto) - scope_fn = hyperparams_builder.build(conv_hyperparams_proto, - is_training=True) - scope = scope_fn() - conv_scope_arguments = scope[_get_scope_key(slim.conv2d)] - initializer = conv_scope_arguments['weights_initializer'] - self._assert_variance_in_range(initializer, shape=[100, 40], - variance=0.64, tol=1e-1) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/image_resizer_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/image_resizer_builder.py deleted file mode 100644 index 3b3014f72..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/image_resizer_builder.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Builder function for image resizing operations.""" -import functools -import tensorflow as tf - -from object_detection.core import preprocessor -from object_detection.protos import image_resizer_pb2 - - -def _tf_resize_method(resize_method): - """Maps image resize method from enumeration type to TensorFlow. - - Args: - resize_method: The resize_method attribute of keep_aspect_ratio_resizer or - fixed_shape_resizer. - - Returns: - method: The corresponding TensorFlow ResizeMethod. - - Raises: - ValueError: if `resize_method` is of unknown type. - """ - dict_method = { - image_resizer_pb2.BILINEAR: - tf.image.ResizeMethod.BILINEAR, - image_resizer_pb2.NEAREST_NEIGHBOR: - tf.image.ResizeMethod.NEAREST_NEIGHBOR, - image_resizer_pb2.BICUBIC: - tf.image.ResizeMethod.BICUBIC, - image_resizer_pb2.AREA: - tf.image.ResizeMethod.AREA - } - if resize_method in dict_method: - return dict_method[resize_method] - else: - raise ValueError('Unknown resize_method') - - -def build(image_resizer_config): - """Builds callable for image resizing operations. - - Args: - image_resizer_config: image_resizer.proto object containing parameters for - an image resizing operation. - - Returns: - image_resizer_fn: Callable for image resizing. This callable always takes - a rank-3 image tensor (corresponding to a single image) and returns a - rank-3 image tensor, possibly with new spatial dimensions. - - Raises: - ValueError: if `image_resizer_config` is of incorrect type. - ValueError: if `image_resizer_config.image_resizer_oneof` is of expected - type. - ValueError: if min_dimension > max_dimension when keep_aspect_ratio_resizer - is used. - """ - if not isinstance(image_resizer_config, image_resizer_pb2.ImageResizer): - raise ValueError('image_resizer_config not of type ' - 'image_resizer_pb2.ImageResizer.') - - image_resizer_oneof = image_resizer_config.WhichOneof('image_resizer_oneof') - if image_resizer_oneof == 'keep_aspect_ratio_resizer': - keep_aspect_ratio_config = image_resizer_config.keep_aspect_ratio_resizer - if not (keep_aspect_ratio_config.min_dimension <= - keep_aspect_ratio_config.max_dimension): - raise ValueError('min_dimension > max_dimension') - method = _tf_resize_method(keep_aspect_ratio_config.resize_method) - per_channel_pad_value = (0, 0, 0) - if keep_aspect_ratio_config.per_channel_pad_value: - per_channel_pad_value = tuple(keep_aspect_ratio_config. - per_channel_pad_value) - image_resizer_fn = functools.partial( - preprocessor.resize_to_range, - min_dimension=keep_aspect_ratio_config.min_dimension, - max_dimension=keep_aspect_ratio_config.max_dimension, - method=method, - pad_to_max_dimension=keep_aspect_ratio_config.pad_to_max_dimension, - per_channel_pad_value=per_channel_pad_value) - if not keep_aspect_ratio_config.convert_to_grayscale: - return image_resizer_fn - elif image_resizer_oneof == 'fixed_shape_resizer': - fixed_shape_resizer_config = image_resizer_config.fixed_shape_resizer - method = _tf_resize_method(fixed_shape_resizer_config.resize_method) - image_resizer_fn = functools.partial( - preprocessor.resize_image, - new_height=fixed_shape_resizer_config.height, - new_width=fixed_shape_resizer_config.width, - method=method) - if not fixed_shape_resizer_config.convert_to_grayscale: - return image_resizer_fn - else: - raise ValueError( - 'Invalid image resizer option: \'%s\'.' % image_resizer_oneof) - - def grayscale_image_resizer(image): - [resized_image, resized_image_shape] = image_resizer_fn(image) - grayscale_image = preprocessor.rgb_to_gray(resized_image) - grayscale_image_shape = tf.concat([resized_image_shape[:-1], [1]], 0) - return [grayscale_image, grayscale_image_shape] - - return functools.partial(grayscale_image_resizer) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/image_resizer_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/image_resizer_builder_test.py deleted file mode 100644 index 38f620e04..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/image_resizer_builder_test.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for object_detection.builders.image_resizer_builder.""" -import numpy as np -import tensorflow as tf -from google.protobuf import text_format -from object_detection.builders import image_resizer_builder -from object_detection.protos import image_resizer_pb2 - - -class ImageResizerBuilderTest(tf.test.TestCase): - - def _shape_of_resized_random_image_given_text_proto(self, input_shape, - text_proto): - image_resizer_config = image_resizer_pb2.ImageResizer() - text_format.Merge(text_proto, image_resizer_config) - image_resizer_fn = image_resizer_builder.build(image_resizer_config) - images = tf.to_float( - tf.random_uniform(input_shape, minval=0, maxval=255, dtype=tf.int32)) - resized_images, _ = image_resizer_fn(images) - with self.test_session() as sess: - return sess.run(resized_images).shape - - def test_build_keep_aspect_ratio_resizer_returns_expected_shape(self): - image_resizer_text_proto = """ - keep_aspect_ratio_resizer { - min_dimension: 10 - max_dimension: 20 - } - """ - input_shape = (50, 25, 3) - expected_output_shape = (20, 10, 3) - output_shape = self._shape_of_resized_random_image_given_text_proto( - input_shape, image_resizer_text_proto) - self.assertEqual(output_shape, expected_output_shape) - - def test_build_keep_aspect_ratio_resizer_with_padding(self): - image_resizer_text_proto = """ - keep_aspect_ratio_resizer { - min_dimension: 10 - max_dimension: 20 - pad_to_max_dimension: true - per_channel_pad_value: 3 - per_channel_pad_value: 4 - per_channel_pad_value: 5 - } - """ - input_shape = (50, 25, 3) - expected_output_shape = (20, 20, 3) - output_shape = self._shape_of_resized_random_image_given_text_proto( - input_shape, image_resizer_text_proto) - self.assertEqual(output_shape, expected_output_shape) - - def test_built_fixed_shape_resizer_returns_expected_shape(self): - image_resizer_text_proto = """ - fixed_shape_resizer { - height: 10 - width: 20 - } - """ - input_shape = (50, 25, 3) - expected_output_shape = (10, 20, 3) - output_shape = self._shape_of_resized_random_image_given_text_proto( - input_shape, image_resizer_text_proto) - self.assertEqual(output_shape, expected_output_shape) - - def test_raises_error_on_invalid_input(self): - invalid_input = 'invalid_input' - with self.assertRaises(ValueError): - image_resizer_builder.build(invalid_input) - - def _resized_image_given_text_proto(self, image, text_proto): - image_resizer_config = image_resizer_pb2.ImageResizer() - text_format.Merge(text_proto, image_resizer_config) - image_resizer_fn = image_resizer_builder.build(image_resizer_config) - image_placeholder = tf.placeholder(tf.uint8, [1, None, None, 3]) - resized_image, _ = image_resizer_fn(image_placeholder) - with self.test_session() as sess: - return sess.run(resized_image, feed_dict={image_placeholder: image}) - - def test_fixed_shape_resizer_nearest_neighbor_method(self): - image_resizer_text_proto = """ - fixed_shape_resizer { - height: 1 - width: 1 - resize_method: NEAREST_NEIGHBOR - } - """ - image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) - image = np.expand_dims(image, axis=2) - image = np.tile(image, (1, 1, 3)) - image = np.expand_dims(image, axis=0) - resized_image = self._resized_image_given_text_proto( - image, image_resizer_text_proto) - vals = np.unique(resized_image).tolist() - self.assertEqual(len(vals), 1) - self.assertEqual(vals[0], 1) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/input_reader_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/input_reader_builder.py deleted file mode 100644 index 8cb5e2f05..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/input_reader_builder.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Input reader builder. - -Creates data sources for DetectionModels from an InputReader config. See -input_reader.proto for options. - -Note: If users wishes to also use their own InputReaders with the Object -Detection configuration framework, they should define their own builder function -that wraps the build function. -""" - -import tensorflow as tf - -from object_detection.data_decoders import tf_example_decoder -from object_detection.protos import input_reader_pb2 - -parallel_reader = tf.contrib.slim.parallel_reader - - -def build(input_reader_config): - """Builds a tensor dictionary based on the InputReader config. - - Args: - input_reader_config: A input_reader_pb2.InputReader object. - - Returns: - A tensor dict based on the input_reader_config. - - Raises: - ValueError: On invalid input reader proto. - ValueError: If no input paths are specified. - """ - if not isinstance(input_reader_config, input_reader_pb2.InputReader): - raise ValueError('input_reader_config not of type ' - 'input_reader_pb2.InputReader.') - - if input_reader_config.WhichOneof('input_reader') == 'tf_record_input_reader': - config = input_reader_config.tf_record_input_reader - if not config.input_path: - raise ValueError('At least one input path must be specified in ' - '`input_reader_config`.') - _, string_tensor = parallel_reader.parallel_read( - config.input_path[:], # Convert `RepeatedScalarContainer` to list. - reader_class=tf.TFRecordReader, - num_epochs=(input_reader_config.num_epochs - if input_reader_config.num_epochs else None), - num_readers=input_reader_config.num_readers, - shuffle=input_reader_config.shuffle, - dtypes=[tf.string, tf.string], - capacity=input_reader_config.queue_capacity, - min_after_dequeue=input_reader_config.min_after_dequeue) - - label_map_proto_file = None - if input_reader_config.HasField('label_map_path'): - label_map_proto_file = input_reader_config.label_map_path - decoder = tf_example_decoder.TfExampleDecoder( - load_instance_masks=input_reader_config.load_instance_masks, - instance_mask_type=input_reader_config.mask_type, - label_map_proto_file=label_map_proto_file) - return decoder.decode(string_tensor) - - raise ValueError('Unsupported input_reader_config.') diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/input_reader_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/input_reader_builder_test.py deleted file mode 100644 index f09f60e57..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/input_reader_builder_test.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for input_reader_builder.""" - -import os -import numpy as np -import tensorflow as tf - -from google.protobuf import text_format - -from tensorflow.core.example import example_pb2 -from tensorflow.core.example import feature_pb2 -from object_detection.builders import input_reader_builder -from object_detection.core import standard_fields as fields -from object_detection.protos import input_reader_pb2 - - -class InputReaderBuilderTest(tf.test.TestCase): - - def create_tf_record(self): - path = os.path.join(self.get_temp_dir(), 'tfrecord') - writer = tf.python_io.TFRecordWriter(path) - - image_tensor = np.random.randint(255, size=(4, 5, 3)).astype(np.uint8) - flat_mask = (4 * 5) * [1.0] - with self.test_session(): - encoded_jpeg = tf.image.encode_jpeg(tf.constant(image_tensor)).eval() - example = example_pb2.Example(features=feature_pb2.Features(feature={ - 'image/encoded': feature_pb2.Feature( - bytes_list=feature_pb2.BytesList(value=[encoded_jpeg])), - 'image/format': feature_pb2.Feature( - bytes_list=feature_pb2.BytesList(value=['jpeg'.encode('utf-8')])), - 'image/height': feature_pb2.Feature( - int64_list=feature_pb2.Int64List(value=[4])), - 'image/width': feature_pb2.Feature( - int64_list=feature_pb2.Int64List(value=[5])), - 'image/object/bbox/xmin': feature_pb2.Feature( - float_list=feature_pb2.FloatList(value=[0.0])), - 'image/object/bbox/xmax': feature_pb2.Feature( - float_list=feature_pb2.FloatList(value=[1.0])), - 'image/object/bbox/ymin': feature_pb2.Feature( - float_list=feature_pb2.FloatList(value=[0.0])), - 'image/object/bbox/ymax': feature_pb2.Feature( - float_list=feature_pb2.FloatList(value=[1.0])), - 'image/object/class/label': feature_pb2.Feature( - int64_list=feature_pb2.Int64List(value=[2])), - 'image/object/mask': feature_pb2.Feature( - float_list=feature_pb2.FloatList(value=flat_mask)), - })) - writer.write(example.SerializeToString()) - writer.close() - - return path - - def test_build_tf_record_input_reader(self): - tf_record_path = self.create_tf_record() - - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - tf_record_input_reader {{ - input_path: '{0}' - }} - """.format(tf_record_path) - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - tensor_dict = input_reader_builder.build(input_reader_proto) - - sv = tf.train.Supervisor(logdir=self.get_temp_dir()) - with sv.prepare_or_wait_for_session() as sess: - sv.start_queue_runners(sess) - output_dict = sess.run(tensor_dict) - - self.assertTrue(fields.InputDataFields.groundtruth_instance_masks - not in output_dict) - self.assertEquals( - (4, 5, 3), output_dict[fields.InputDataFields.image].shape) - self.assertEquals( - [2], output_dict[fields.InputDataFields.groundtruth_classes]) - self.assertEquals( - (1, 4), output_dict[fields.InputDataFields.groundtruth_boxes].shape) - self.assertAllEqual( - [0.0, 0.0, 1.0, 1.0], - output_dict[fields.InputDataFields.groundtruth_boxes][0]) - - def test_build_tf_record_input_reader_and_load_instance_masks(self): - tf_record_path = self.create_tf_record() - - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - load_instance_masks: true - tf_record_input_reader {{ - input_path: '{0}' - }} - """.format(tf_record_path) - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - tensor_dict = input_reader_builder.build(input_reader_proto) - - sv = tf.train.Supervisor(logdir=self.get_temp_dir()) - with sv.prepare_or_wait_for_session() as sess: - sv.start_queue_runners(sess) - output_dict = sess.run(tensor_dict) - - self.assertEquals( - (4, 5, 3), output_dict[fields.InputDataFields.image].shape) - self.assertEquals( - [2], output_dict[fields.InputDataFields.groundtruth_classes]) - self.assertEquals( - (1, 4), output_dict[fields.InputDataFields.groundtruth_boxes].shape) - self.assertAllEqual( - [0.0, 0.0, 1.0, 1.0], - output_dict[fields.InputDataFields.groundtruth_boxes][0]) - self.assertAllEqual( - (1, 4, 5), - output_dict[fields.InputDataFields.groundtruth_instance_masks].shape) - - def test_raises_error_with_no_input_paths(self): - input_reader_text_proto = """ - shuffle: false - num_readers: 1 - load_instance_masks: true - """ - input_reader_proto = input_reader_pb2.InputReader() - text_format.Merge(input_reader_text_proto, input_reader_proto) - with self.assertRaises(ValueError): - input_reader_builder.build(input_reader_proto) - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder.py deleted file mode 100644 index e4f7a1240..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder.py +++ /dev/null @@ -1,222 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""A function to build localization and classification losses from config.""" - -from object_detection.core import balanced_positive_negative_sampler as sampler -from object_detection.core import losses -from object_detection.protos import losses_pb2 - - -def build(loss_config): - """Build losses based on the config. - - Builds classification, localization losses and optionally a hard example miner - based on the config. - - Args: - loss_config: A losses_pb2.Loss object. - - Returns: - classification_loss: Classification loss object. - localization_loss: Localization loss object. - classification_weight: Classification loss weight. - localization_weight: Localization loss weight. - hard_example_miner: Hard example miner object. - random_example_sampler: BalancedPositiveNegativeSampler object. - - Raises: - ValueError: If hard_example_miner is used with sigmoid_focal_loss. - ValueError: If random_example_sampler is getting non-positive value as - desired positive example fraction. - """ - classification_loss = _build_classification_loss( - loss_config.classification_loss) - localization_loss = _build_localization_loss( - loss_config.localization_loss) - classification_weight = loss_config.classification_weight - localization_weight = loss_config.localization_weight - hard_example_miner = None - if loss_config.HasField('hard_example_miner'): - if (loss_config.classification_loss.WhichOneof('classification_loss') == - 'weighted_sigmoid_focal'): - raise ValueError('HardExampleMiner should not be used with sigmoid focal ' - 'loss') - hard_example_miner = build_hard_example_miner( - loss_config.hard_example_miner, - classification_weight, - localization_weight) - random_example_sampler = None - if loss_config.HasField('random_example_sampler'): - if loss_config.random_example_sampler.positive_sample_fraction <= 0: - raise ValueError('RandomExampleSampler should not use non-positive' - 'value as positive sample fraction.') - random_example_sampler = sampler.BalancedPositiveNegativeSampler( - positive_fraction=loss_config.random_example_sampler. - positive_sample_fraction) - return (classification_loss, localization_loss, classification_weight, - localization_weight, hard_example_miner, random_example_sampler) - - -def build_hard_example_miner(config, - classification_weight, - localization_weight): - """Builds hard example miner based on the config. - - Args: - config: A losses_pb2.HardExampleMiner object. - classification_weight: Classification loss weight. - localization_weight: Localization loss weight. - - Returns: - Hard example miner. - - """ - loss_type = None - if config.loss_type == losses_pb2.HardExampleMiner.BOTH: - loss_type = 'both' - if config.loss_type == losses_pb2.HardExampleMiner.CLASSIFICATION: - loss_type = 'cls' - if config.loss_type == losses_pb2.HardExampleMiner.LOCALIZATION: - loss_type = 'loc' - - max_negatives_per_positive = None - num_hard_examples = None - if config.max_negatives_per_positive > 0: - max_negatives_per_positive = config.max_negatives_per_positive - if config.num_hard_examples > 0: - num_hard_examples = config.num_hard_examples - hard_example_miner = losses.HardExampleMiner( - num_hard_examples=num_hard_examples, - iou_threshold=config.iou_threshold, - loss_type=loss_type, - cls_loss_weight=classification_weight, - loc_loss_weight=localization_weight, - max_negatives_per_positive=max_negatives_per_positive, - min_negatives_per_image=config.min_negatives_per_image) - return hard_example_miner - - -def build_faster_rcnn_classification_loss(loss_config): - """Builds a classification loss for Faster RCNN based on the loss config. - - Args: - loss_config: A losses_pb2.ClassificationLoss object. - - Returns: - Loss based on the config. - - Raises: - ValueError: On invalid loss_config. - """ - if not isinstance(loss_config, losses_pb2.ClassificationLoss): - raise ValueError('loss_config not of type losses_pb2.ClassificationLoss.') - - loss_type = loss_config.WhichOneof('classification_loss') - - if loss_type == 'weighted_sigmoid': - return losses.WeightedSigmoidClassificationLoss() - if loss_type == 'weighted_softmax': - config = loss_config.weighted_softmax - return losses.WeightedSoftmaxClassificationLoss( - logit_scale=config.logit_scale) - if loss_type == 'weighted_logits_softmax': - config = loss_config.weighted_logits_softmax - return losses.WeightedSoftmaxClassificationAgainstLogitsLoss( - logit_scale=config.logit_scale) - - # By default, Faster RCNN second stage classifier uses Softmax loss - # with anchor-wise outputs. - config = loss_config.weighted_softmax - return losses.WeightedSoftmaxClassificationLoss( - logit_scale=config.logit_scale) - - -def _build_localization_loss(loss_config): - """Builds a localization loss based on the loss config. - - Args: - loss_config: A losses_pb2.LocalizationLoss object. - - Returns: - Loss based on the config. - - Raises: - ValueError: On invalid loss_config. - """ - if not isinstance(loss_config, losses_pb2.LocalizationLoss): - raise ValueError('loss_config not of type losses_pb2.LocalizationLoss.') - - loss_type = loss_config.WhichOneof('localization_loss') - - if loss_type == 'weighted_l2': - return losses.WeightedL2LocalizationLoss() - - if loss_type == 'weighted_smooth_l1': - return losses.WeightedSmoothL1LocalizationLoss( - loss_config.weighted_smooth_l1.delta) - - if loss_type == 'weighted_iou': - return losses.WeightedIOULocalizationLoss() - - raise ValueError('Empty loss config.') - - -def _build_classification_loss(loss_config): - """Builds a classification loss based on the loss config. - - Args: - loss_config: A losses_pb2.ClassificationLoss object. - - Returns: - Loss based on the config. - - Raises: - ValueError: On invalid loss_config. - """ - if not isinstance(loss_config, losses_pb2.ClassificationLoss): - raise ValueError('loss_config not of type losses_pb2.ClassificationLoss.') - - loss_type = loss_config.WhichOneof('classification_loss') - - if loss_type == 'weighted_sigmoid': - return losses.WeightedSigmoidClassificationLoss() - - if loss_type == 'weighted_sigmoid_focal': - config = loss_config.weighted_sigmoid_focal - alpha = None - if config.HasField('alpha'): - alpha = config.alpha - return losses.SigmoidFocalClassificationLoss( - gamma=config.gamma, - alpha=alpha) - - if loss_type == 'weighted_softmax': - config = loss_config.weighted_softmax - return losses.WeightedSoftmaxClassificationLoss( - logit_scale=config.logit_scale) - - if loss_type == 'weighted_logits_softmax': - config = loss_config.weighted_logits_softmax - return losses.WeightedSoftmaxClassificationAgainstLogitsLoss( - logit_scale=config.logit_scale) - - if loss_type == 'bootstrapped_sigmoid': - config = loss_config.bootstrapped_sigmoid - return losses.BootstrappedSigmoidClassificationLoss( - alpha=config.alpha, - bootstrap_type=('hard' if config.hard_bootstrap else 'soft')) - - raise ValueError('Empty loss config.') diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder_test.py deleted file mode 100644 index 4dc4a754e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder_test.py +++ /dev/null @@ -1,488 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for losses_builder.""" - -import tensorflow as tf - -from google.protobuf import text_format -from object_detection.builders import losses_builder -from object_detection.core import losses -from object_detection.protos import losses_pb2 - - -class LocalizationLossBuilderTest(tf.test.TestCase): - - def test_build_weighted_l2_localization_loss(self): - losses_text_proto = """ - localization_loss { - weighted_l2 { - } - } - classification_loss { - weighted_softmax { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, localization_loss, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(localization_loss, - losses.WeightedL2LocalizationLoss)) - - def test_build_weighted_smooth_l1_localization_loss_default_delta(self): - losses_text_proto = """ - localization_loss { - weighted_smooth_l1 { - } - } - classification_loss { - weighted_softmax { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, localization_loss, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(localization_loss, - losses.WeightedSmoothL1LocalizationLoss)) - self.assertAlmostEqual(localization_loss._delta, 1.0) - - def test_build_weighted_smooth_l1_localization_loss_non_default_delta(self): - losses_text_proto = """ - localization_loss { - weighted_smooth_l1 { - delta: 0.1 - } - } - classification_loss { - weighted_softmax { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, localization_loss, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(localization_loss, - losses.WeightedSmoothL1LocalizationLoss)) - self.assertAlmostEqual(localization_loss._delta, 0.1) - - def test_build_weighted_iou_localization_loss(self): - losses_text_proto = """ - localization_loss { - weighted_iou { - } - } - classification_loss { - weighted_softmax { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, localization_loss, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(localization_loss, - losses.WeightedIOULocalizationLoss)) - - def test_anchorwise_output(self): - losses_text_proto = """ - localization_loss { - weighted_smooth_l1 { - } - } - classification_loss { - weighted_softmax { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, localization_loss, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(localization_loss, - losses.WeightedSmoothL1LocalizationLoss)) - predictions = tf.constant([[[0.0, 0.0, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0]]]) - targets = tf.constant([[[0.0, 0.0, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0]]]) - weights = tf.constant([[1.0, 1.0]]) - loss = localization_loss(predictions, targets, weights=weights) - self.assertEqual(loss.shape, [1, 2]) - - def test_raise_error_on_empty_localization_config(self): - losses_text_proto = """ - classification_loss { - weighted_softmax { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - with self.assertRaises(ValueError): - losses_builder._build_localization_loss(losses_proto) - - -class ClassificationLossBuilderTest(tf.test.TestCase): - - def test_build_weighted_sigmoid_classification_loss(self): - losses_text_proto = """ - classification_loss { - weighted_sigmoid { - } - } - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss, _, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.WeightedSigmoidClassificationLoss)) - - def test_build_weighted_sigmoid_focal_classification_loss(self): - losses_text_proto = """ - classification_loss { - weighted_sigmoid_focal { - } - } - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss, _, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.SigmoidFocalClassificationLoss)) - self.assertAlmostEqual(classification_loss._alpha, None) - self.assertAlmostEqual(classification_loss._gamma, 2.0) - - def test_build_weighted_sigmoid_focal_loss_non_default(self): - losses_text_proto = """ - classification_loss { - weighted_sigmoid_focal { - alpha: 0.25 - gamma: 3.0 - } - } - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss, _, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.SigmoidFocalClassificationLoss)) - self.assertAlmostEqual(classification_loss._alpha, 0.25) - self.assertAlmostEqual(classification_loss._gamma, 3.0) - - def test_build_weighted_softmax_classification_loss(self): - losses_text_proto = """ - classification_loss { - weighted_softmax { - } - } - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss, _, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.WeightedSoftmaxClassificationLoss)) - - def test_build_weighted_logits_softmax_classification_loss(self): - losses_text_proto = """ - classification_loss { - weighted_logits_softmax { - } - } - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss, _, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue( - isinstance(classification_loss, - losses.WeightedSoftmaxClassificationAgainstLogitsLoss)) - - def test_build_weighted_softmax_classification_loss_with_logit_scale(self): - losses_text_proto = """ - classification_loss { - weighted_softmax { - logit_scale: 2.0 - } - } - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss, _, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.WeightedSoftmaxClassificationLoss)) - - def test_build_bootstrapped_sigmoid_classification_loss(self): - losses_text_proto = """ - classification_loss { - bootstrapped_sigmoid { - alpha: 0.5 - } - } - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss, _, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.BootstrappedSigmoidClassificationLoss)) - - def test_anchorwise_output(self): - losses_text_proto = """ - classification_loss { - weighted_sigmoid { - anchorwise_output: true - } - } - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss, _, _, _, _, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.WeightedSigmoidClassificationLoss)) - predictions = tf.constant([[[0.0, 1.0, 0.0], [0.0, 0.5, 0.5]]]) - targets = tf.constant([[[0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]]) - weights = tf.constant([[1.0, 1.0]]) - loss = classification_loss(predictions, targets, weights=weights) - self.assertEqual(loss.shape, [1, 2, 3]) - - def test_raise_error_on_empty_config(self): - losses_text_proto = """ - localization_loss { - weighted_l2 { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - with self.assertRaises(ValueError): - losses_builder.build(losses_proto) - - -class HardExampleMinerBuilderTest(tf.test.TestCase): - - def test_do_not_build_hard_example_miner_by_default(self): - losses_text_proto = """ - localization_loss { - weighted_l2 { - } - } - classification_loss { - weighted_softmax { - } - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, _, _, _, hard_example_miner, _ = losses_builder.build(losses_proto) - self.assertEqual(hard_example_miner, None) - - def test_build_hard_example_miner_for_classification_loss(self): - losses_text_proto = """ - localization_loss { - weighted_l2 { - } - } - classification_loss { - weighted_softmax { - } - } - hard_example_miner { - loss_type: CLASSIFICATION - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, _, _, _, hard_example_miner, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(hard_example_miner, losses.HardExampleMiner)) - self.assertEqual(hard_example_miner._loss_type, 'cls') - - def test_build_hard_example_miner_for_localization_loss(self): - losses_text_proto = """ - localization_loss { - weighted_l2 { - } - } - classification_loss { - weighted_softmax { - } - } - hard_example_miner { - loss_type: LOCALIZATION - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, _, _, _, hard_example_miner, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(hard_example_miner, losses.HardExampleMiner)) - self.assertEqual(hard_example_miner._loss_type, 'loc') - - def test_build_hard_example_miner_with_non_default_values(self): - losses_text_proto = """ - localization_loss { - weighted_l2 { - } - } - classification_loss { - weighted_softmax { - } - } - hard_example_miner { - num_hard_examples: 32 - iou_threshold: 0.5 - loss_type: LOCALIZATION - max_negatives_per_positive: 10 - min_negatives_per_image: 3 - } - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - _, _, _, _, hard_example_miner, _ = losses_builder.build(losses_proto) - self.assertTrue(isinstance(hard_example_miner, losses.HardExampleMiner)) - self.assertEqual(hard_example_miner._num_hard_examples, 32) - self.assertAlmostEqual(hard_example_miner._iou_threshold, 0.5) - self.assertEqual(hard_example_miner._max_negatives_per_positive, 10) - self.assertEqual(hard_example_miner._min_negatives_per_image, 3) - - -class LossBuilderTest(tf.test.TestCase): - - def test_build_all_loss_parameters(self): - losses_text_proto = """ - localization_loss { - weighted_l2 { - } - } - classification_loss { - weighted_softmax { - } - } - hard_example_miner { - } - classification_weight: 0.8 - localization_weight: 0.2 - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - (classification_loss, localization_loss, - classification_weight, localization_weight, - hard_example_miner, _) = losses_builder.build(losses_proto) - self.assertTrue(isinstance(hard_example_miner, losses.HardExampleMiner)) - self.assertTrue(isinstance(classification_loss, - losses.WeightedSoftmaxClassificationLoss)) - self.assertTrue(isinstance(localization_loss, - losses.WeightedL2LocalizationLoss)) - self.assertAlmostEqual(classification_weight, 0.8) - self.assertAlmostEqual(localization_weight, 0.2) - - def test_raise_error_when_both_focal_loss_and_hard_example_miner(self): - losses_text_proto = """ - localization_loss { - weighted_l2 { - } - } - classification_loss { - weighted_sigmoid_focal { - } - } - hard_example_miner { - } - classification_weight: 0.8 - localization_weight: 0.2 - """ - losses_proto = losses_pb2.Loss() - text_format.Merge(losses_text_proto, losses_proto) - with self.assertRaises(ValueError): - losses_builder.build(losses_proto) - - -class FasterRcnnClassificationLossBuilderTest(tf.test.TestCase): - - def test_build_sigmoid_loss(self): - losses_text_proto = """ - weighted_sigmoid { - } - """ - losses_proto = losses_pb2.ClassificationLoss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss = losses_builder.build_faster_rcnn_classification_loss( - losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.WeightedSigmoidClassificationLoss)) - - def test_build_softmax_loss(self): - losses_text_proto = """ - weighted_softmax { - } - """ - losses_proto = losses_pb2.ClassificationLoss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss = losses_builder.build_faster_rcnn_classification_loss( - losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.WeightedSoftmaxClassificationLoss)) - - def test_build_logits_softmax_loss(self): - losses_text_proto = """ - weighted_logits_softmax { - } - """ - losses_proto = losses_pb2.ClassificationLoss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss = losses_builder.build_faster_rcnn_classification_loss( - losses_proto) - self.assertTrue( - isinstance(classification_loss, - losses.WeightedSoftmaxClassificationAgainstLogitsLoss)) - - def test_build_softmax_loss_by_default(self): - losses_text_proto = """ - """ - losses_proto = losses_pb2.ClassificationLoss() - text_format.Merge(losses_text_proto, losses_proto) - classification_loss = losses_builder.build_faster_rcnn_classification_loss( - losses_proto) - self.assertTrue(isinstance(classification_loss, - losses.WeightedSoftmaxClassificationLoss)) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder.py deleted file mode 100644 index d334f4353..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""A function to build an object detection matcher from configuration.""" - -from object_detection.matchers import argmax_matcher -from object_detection.matchers import bipartite_matcher -from object_detection.protos import matcher_pb2 - - -def build(matcher_config): - """Builds a matcher object based on the matcher config. - - Args: - matcher_config: A matcher.proto object containing the config for the desired - Matcher. - - Returns: - Matcher based on the config. - - Raises: - ValueError: On empty matcher proto. - """ - if not isinstance(matcher_config, matcher_pb2.Matcher): - raise ValueError('matcher_config not of type matcher_pb2.Matcher.') - if matcher_config.WhichOneof('matcher_oneof') == 'argmax_matcher': - matcher = matcher_config.argmax_matcher - matched_threshold = unmatched_threshold = None - if not matcher.ignore_thresholds: - matched_threshold = matcher.matched_threshold - unmatched_threshold = matcher.unmatched_threshold - return argmax_matcher.ArgMaxMatcher( - matched_threshold=matched_threshold, - unmatched_threshold=unmatched_threshold, - negatives_lower_than_unmatched=matcher.negatives_lower_than_unmatched, - force_match_for_each_row=matcher.force_match_for_each_row, - use_matmul_gather=matcher.use_matmul_gather) - if matcher_config.WhichOneof('matcher_oneof') == 'bipartite_matcher': - matcher = matcher_config.bipartite_matcher - return bipartite_matcher.GreedyBipartiteMatcher(matcher.use_matmul_gather) - raise ValueError('Empty matcher.') diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder_test.py deleted file mode 100644 index 668544911..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder_test.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for matcher_builder.""" - -import tensorflow as tf - -from google.protobuf import text_format -from object_detection.builders import matcher_builder -from object_detection.matchers import argmax_matcher -from object_detection.matchers import bipartite_matcher -from object_detection.protos import matcher_pb2 - - -class MatcherBuilderTest(tf.test.TestCase): - - def test_build_arg_max_matcher_with_defaults(self): - matcher_text_proto = """ - argmax_matcher { - } - """ - matcher_proto = matcher_pb2.Matcher() - text_format.Merge(matcher_text_proto, matcher_proto) - matcher_object = matcher_builder.build(matcher_proto) - self.assertTrue(isinstance(matcher_object, argmax_matcher.ArgMaxMatcher)) - self.assertAlmostEqual(matcher_object._matched_threshold, 0.5) - self.assertAlmostEqual(matcher_object._unmatched_threshold, 0.5) - self.assertTrue(matcher_object._negatives_lower_than_unmatched) - self.assertFalse(matcher_object._force_match_for_each_row) - - def test_build_arg_max_matcher_without_thresholds(self): - matcher_text_proto = """ - argmax_matcher { - ignore_thresholds: true - } - """ - matcher_proto = matcher_pb2.Matcher() - text_format.Merge(matcher_text_proto, matcher_proto) - matcher_object = matcher_builder.build(matcher_proto) - self.assertTrue(isinstance(matcher_object, argmax_matcher.ArgMaxMatcher)) - self.assertEqual(matcher_object._matched_threshold, None) - self.assertEqual(matcher_object._unmatched_threshold, None) - self.assertTrue(matcher_object._negatives_lower_than_unmatched) - self.assertFalse(matcher_object._force_match_for_each_row) - - def test_build_arg_max_matcher_with_non_default_parameters(self): - matcher_text_proto = """ - argmax_matcher { - matched_threshold: 0.7 - unmatched_threshold: 0.3 - negatives_lower_than_unmatched: false - force_match_for_each_row: true - use_matmul_gather: true - } - """ - matcher_proto = matcher_pb2.Matcher() - text_format.Merge(matcher_text_proto, matcher_proto) - matcher_object = matcher_builder.build(matcher_proto) - self.assertTrue(isinstance(matcher_object, argmax_matcher.ArgMaxMatcher)) - self.assertAlmostEqual(matcher_object._matched_threshold, 0.7) - self.assertAlmostEqual(matcher_object._unmatched_threshold, 0.3) - self.assertFalse(matcher_object._negatives_lower_than_unmatched) - self.assertTrue(matcher_object._force_match_for_each_row) - self.assertTrue(matcher_object._use_matmul_gather) - - def test_build_bipartite_matcher(self): - matcher_text_proto = """ - bipartite_matcher { - } - """ - matcher_proto = matcher_pb2.Matcher() - text_format.Merge(matcher_text_proto, matcher_proto) - matcher_object = matcher_builder.build(matcher_proto) - self.assertTrue( - isinstance(matcher_object, bipartite_matcher.GreedyBipartiteMatcher)) - - def test_raise_error_on_empty_matcher(self): - matcher_text_proto = """ - """ - matcher_proto = matcher_pb2.Matcher() - text_format.Merge(matcher_text_proto, matcher_proto) - with self.assertRaises(ValueError): - matcher_builder.build(matcher_proto) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder.py deleted file mode 100644 index 1ebdcb79f..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder.py +++ /dev/null @@ -1,377 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""A function to build a DetectionModel from configuration.""" -from object_detection.builders import anchor_generator_builder -from object_detection.builders import box_coder_builder -from object_detection.builders import box_predictor_builder -from object_detection.builders import hyperparams_builder -from object_detection.builders import image_resizer_builder -from object_detection.builders import losses_builder -from object_detection.builders import matcher_builder -from object_detection.builders import post_processing_builder -from object_detection.builders import region_similarity_calculator_builder as sim_calc -from object_detection.core import box_predictor -from object_detection.meta_architectures import faster_rcnn_meta_arch -from object_detection.meta_architectures import rfcn_meta_arch -from object_detection.meta_architectures import ssd_meta_arch -from object_detection.models import faster_rcnn_inception_resnet_v2_feature_extractor as frcnn_inc_res -from object_detection.models import faster_rcnn_inception_v2_feature_extractor as frcnn_inc_v2 -from object_detection.models import faster_rcnn_nas_feature_extractor as frcnn_nas -from object_detection.models import faster_rcnn_pnas_feature_extractor as frcnn_pnas -from object_detection.models import faster_rcnn_resnet_v1_feature_extractor as frcnn_resnet_v1 -from object_detection.models import ssd_resnet_v1_fpn_feature_extractor as ssd_resnet_v1_fpn -from object_detection.models.embedded_ssd_mobilenet_v1_feature_extractor import EmbeddedSSDMobileNetV1FeatureExtractor -from object_detection.models.ssd_inception_v2_feature_extractor import SSDInceptionV2FeatureExtractor -from object_detection.models.ssd_inception_v3_feature_extractor import SSDInceptionV3FeatureExtractor -from object_detection.models.ssd_mobilenet_v1_feature_extractor import SSDMobileNetV1FeatureExtractor -from object_detection.models.ssd_mobilenet_v2_feature_extractor import SSDMobileNetV2FeatureExtractor -from object_detection.protos import model_pb2 - -# A map of names to SSD feature extractors. -SSD_FEATURE_EXTRACTOR_CLASS_MAP = { - 'ssd_inception_v2': SSDInceptionV2FeatureExtractor, - 'ssd_inception_v3': SSDInceptionV3FeatureExtractor, - 'ssd_mobilenet_v1': SSDMobileNetV1FeatureExtractor, - 'ssd_mobilenet_v2': SSDMobileNetV2FeatureExtractor, - 'ssd_resnet50_v1_fpn': ssd_resnet_v1_fpn.SSDResnet50V1FpnFeatureExtractor, - 'ssd_resnet101_v1_fpn': ssd_resnet_v1_fpn.SSDResnet101V1FpnFeatureExtractor, - 'ssd_resnet152_v1_fpn': ssd_resnet_v1_fpn.SSDResnet152V1FpnFeatureExtractor, - 'embedded_ssd_mobilenet_v1': EmbeddedSSDMobileNetV1FeatureExtractor, -} - -# A map of names to Faster R-CNN feature extractors. -FASTER_RCNN_FEATURE_EXTRACTOR_CLASS_MAP = { - 'faster_rcnn_nas': - frcnn_nas.FasterRCNNNASFeatureExtractor, - 'faster_rcnn_pnas': - frcnn_pnas.FasterRCNNPNASFeatureExtractor, - 'faster_rcnn_inception_resnet_v2': - frcnn_inc_res.FasterRCNNInceptionResnetV2FeatureExtractor, - 'faster_rcnn_inception_v2': - frcnn_inc_v2.FasterRCNNInceptionV2FeatureExtractor, - 'faster_rcnn_resnet50': - frcnn_resnet_v1.FasterRCNNResnet50FeatureExtractor, - 'faster_rcnn_resnet101': - frcnn_resnet_v1.FasterRCNNResnet101FeatureExtractor, - 'faster_rcnn_resnet152': - frcnn_resnet_v1.FasterRCNNResnet152FeatureExtractor, -} - - -def build(model_config, is_training, add_summaries=True, - add_background_class=True): - """Builds a DetectionModel based on the model config. - - Args: - model_config: A model.proto object containing the config for the desired - DetectionModel. - is_training: True if this model is being built for training purposes. - add_summaries: Whether to add tensorflow summaries in the model graph. - add_background_class: Whether to add an implicit background class to one-hot - encodings of groundtruth labels. Set to false if using groundtruth labels - with an explicit background class or using multiclass scores instead of - truth in the case of distillation. Ignored in the case of faster_rcnn. - Returns: - DetectionModel based on the config. - - Raises: - ValueError: On invalid meta architecture or model. - """ - if not isinstance(model_config, model_pb2.DetectionModel): - raise ValueError('model_config not of type model_pb2.DetectionModel.') - meta_architecture = model_config.WhichOneof('model') - if meta_architecture == 'ssd': - return _build_ssd_model(model_config.ssd, is_training, add_summaries, - add_background_class) - if meta_architecture == 'faster_rcnn': - return _build_faster_rcnn_model(model_config.faster_rcnn, is_training, - add_summaries) - raise ValueError('Unknown meta architecture: {}'.format(meta_architecture)) - - -def _build_ssd_feature_extractor(feature_extractor_config, is_training, - reuse_weights=None): - """Builds a ssd_meta_arch.SSDFeatureExtractor based on config. - - Args: - feature_extractor_config: A SSDFeatureExtractor proto config from ssd.proto. - is_training: True if this feature extractor is being built for training. - reuse_weights: if the feature extractor should reuse weights. - - Returns: - ssd_meta_arch.SSDFeatureExtractor based on config. - - Raises: - ValueError: On invalid feature extractor type. - """ - feature_type = feature_extractor_config.type - depth_multiplier = feature_extractor_config.depth_multiplier - min_depth = feature_extractor_config.min_depth - pad_to_multiple = feature_extractor_config.pad_to_multiple - use_explicit_padding = feature_extractor_config.use_explicit_padding - use_depthwise = feature_extractor_config.use_depthwise - conv_hyperparams = hyperparams_builder.build( - feature_extractor_config.conv_hyperparams, is_training) - override_base_feature_extractor_hyperparams = ( - feature_extractor_config.override_base_feature_extractor_hyperparams) - - if feature_type not in SSD_FEATURE_EXTRACTOR_CLASS_MAP: - raise ValueError('Unknown ssd feature_extractor: {}'.format(feature_type)) - - feature_extractor_class = SSD_FEATURE_EXTRACTOR_CLASS_MAP[feature_type] - return feature_extractor_class( - is_training, depth_multiplier, min_depth, pad_to_multiple, - conv_hyperparams, reuse_weights, use_explicit_padding, use_depthwise, - override_base_feature_extractor_hyperparams) - - -def _build_ssd_model(ssd_config, is_training, add_summaries, - add_background_class=True): - """Builds an SSD detection model based on the model config. - - Args: - ssd_config: A ssd.proto object containing the config for the desired - SSDMetaArch. - is_training: True if this model is being built for training purposes. - add_summaries: Whether to add tf summaries in the model. - add_background_class: Whether to add an implicit background class to one-hot - encodings of groundtruth labels. Set to false if using groundtruth labels - with an explicit background class or using multiclass scores instead of - truth in the case of distillation. - Returns: - SSDMetaArch based on the config. - - Raises: - ValueError: If ssd_config.type is not recognized (i.e. not registered in - model_class_map). - """ - num_classes = ssd_config.num_classes - - # Feature extractor - feature_extractor = _build_ssd_feature_extractor( - feature_extractor_config=ssd_config.feature_extractor, - is_training=is_training) - - box_coder = box_coder_builder.build(ssd_config.box_coder) - matcher = matcher_builder.build(ssd_config.matcher) - region_similarity_calculator = sim_calc.build( - ssd_config.similarity_calculator) - encode_background_as_zeros = ssd_config.encode_background_as_zeros - negative_class_weight = ssd_config.negative_class_weight - ssd_box_predictor = box_predictor_builder.build(hyperparams_builder.build, - ssd_config.box_predictor, - is_training, num_classes) - anchor_generator = anchor_generator_builder.build( - ssd_config.anchor_generator) - image_resizer_fn = image_resizer_builder.build(ssd_config.image_resizer) - non_max_suppression_fn, score_conversion_fn = post_processing_builder.build( - ssd_config.post_processing) - (classification_loss, localization_loss, classification_weight, - localization_weight, hard_example_miner, - random_example_sampler) = losses_builder.build(ssd_config.loss) - normalize_loss_by_num_matches = ssd_config.normalize_loss_by_num_matches - normalize_loc_loss_by_codesize = ssd_config.normalize_loc_loss_by_codesize - - return ssd_meta_arch.SSDMetaArch( - is_training, - anchor_generator, - ssd_box_predictor, - box_coder, - feature_extractor, - matcher, - region_similarity_calculator, - encode_background_as_zeros, - negative_class_weight, - image_resizer_fn, - non_max_suppression_fn, - score_conversion_fn, - classification_loss, - localization_loss, - classification_weight, - localization_weight, - normalize_loss_by_num_matches, - hard_example_miner, - add_summaries=add_summaries, - normalize_loc_loss_by_codesize=normalize_loc_loss_by_codesize, - freeze_batchnorm=ssd_config.freeze_batchnorm, - inplace_batchnorm_update=ssd_config.inplace_batchnorm_update, - add_background_class=add_background_class, - random_example_sampler=random_example_sampler) - - -def _build_faster_rcnn_feature_extractor( - feature_extractor_config, is_training, reuse_weights=None, - inplace_batchnorm_update=False): - """Builds a faster_rcnn_meta_arch.FasterRCNNFeatureExtractor based on config. - - Args: - feature_extractor_config: A FasterRcnnFeatureExtractor proto config from - faster_rcnn.proto. - is_training: True if this feature extractor is being built for training. - reuse_weights: if the feature extractor should reuse weights. - inplace_batchnorm_update: Whether to update batch_norm inplace during - training. This is required for batch norm to work correctly on TPUs. When - this is false, user must add a control dependency on - tf.GraphKeys.UPDATE_OPS for train/loss op in order to update the batch - norm moving average parameters. - - Returns: - faster_rcnn_meta_arch.FasterRCNNFeatureExtractor based on config. - - Raises: - ValueError: On invalid feature extractor type. - """ - if inplace_batchnorm_update: - raise ValueError('inplace batchnorm updates not supported.') - feature_type = feature_extractor_config.type - first_stage_features_stride = ( - feature_extractor_config.first_stage_features_stride) - batch_norm_trainable = feature_extractor_config.batch_norm_trainable - - if feature_type not in FASTER_RCNN_FEATURE_EXTRACTOR_CLASS_MAP: - raise ValueError('Unknown Faster R-CNN feature_extractor: {}'.format( - feature_type)) - feature_extractor_class = FASTER_RCNN_FEATURE_EXTRACTOR_CLASS_MAP[ - feature_type] - return feature_extractor_class( - is_training, first_stage_features_stride, - batch_norm_trainable, reuse_weights) - - -def _build_faster_rcnn_model(frcnn_config, is_training, add_summaries): - """Builds a Faster R-CNN or R-FCN detection model based on the model config. - - Builds R-FCN model if the second_stage_box_predictor in the config is of type - `rfcn_box_predictor` else builds a Faster R-CNN model. - - Args: - frcnn_config: A faster_rcnn.proto object containing the config for the - desired FasterRCNNMetaArch or RFCNMetaArch. - is_training: True if this model is being built for training purposes. - add_summaries: Whether to add tf summaries in the model. - - Returns: - FasterRCNNMetaArch based on the config. - - Raises: - ValueError: If frcnn_config.type is not recognized (i.e. not registered in - model_class_map). - """ - num_classes = frcnn_config.num_classes - image_resizer_fn = image_resizer_builder.build(frcnn_config.image_resizer) - - feature_extractor = _build_faster_rcnn_feature_extractor( - frcnn_config.feature_extractor, is_training, - frcnn_config.inplace_batchnorm_update) - - number_of_stages = frcnn_config.number_of_stages - first_stage_anchor_generator = anchor_generator_builder.build( - frcnn_config.first_stage_anchor_generator) - - first_stage_atrous_rate = frcnn_config.first_stage_atrous_rate - first_stage_box_predictor_arg_scope_fn = hyperparams_builder.build( - frcnn_config.first_stage_box_predictor_conv_hyperparams, is_training) - first_stage_box_predictor_kernel_size = ( - frcnn_config.first_stage_box_predictor_kernel_size) - first_stage_box_predictor_depth = frcnn_config.first_stage_box_predictor_depth - first_stage_minibatch_size = frcnn_config.first_stage_minibatch_size - first_stage_positive_balance_fraction = ( - frcnn_config.first_stage_positive_balance_fraction) - first_stage_nms_score_threshold = frcnn_config.first_stage_nms_score_threshold - first_stage_nms_iou_threshold = frcnn_config.first_stage_nms_iou_threshold - first_stage_max_proposals = frcnn_config.first_stage_max_proposals - first_stage_loc_loss_weight = ( - frcnn_config.first_stage_localization_loss_weight) - first_stage_obj_loss_weight = frcnn_config.first_stage_objectness_loss_weight - - initial_crop_size = frcnn_config.initial_crop_size - maxpool_kernel_size = frcnn_config.maxpool_kernel_size - maxpool_stride = frcnn_config.maxpool_stride - - second_stage_box_predictor = box_predictor_builder.build( - hyperparams_builder.build, - frcnn_config.second_stage_box_predictor, - is_training=is_training, - num_classes=num_classes) - second_stage_batch_size = frcnn_config.second_stage_batch_size - second_stage_balance_fraction = frcnn_config.second_stage_balance_fraction - (second_stage_non_max_suppression_fn, second_stage_score_conversion_fn - ) = post_processing_builder.build(frcnn_config.second_stage_post_processing) - second_stage_localization_loss_weight = ( - frcnn_config.second_stage_localization_loss_weight) - second_stage_classification_loss = ( - losses_builder.build_faster_rcnn_classification_loss( - frcnn_config.second_stage_classification_loss)) - second_stage_classification_loss_weight = ( - frcnn_config.second_stage_classification_loss_weight) - second_stage_mask_prediction_loss_weight = ( - frcnn_config.second_stage_mask_prediction_loss_weight) - - hard_example_miner = None - if frcnn_config.HasField('hard_example_miner'): - hard_example_miner = losses_builder.build_hard_example_miner( - frcnn_config.hard_example_miner, - second_stage_classification_loss_weight, - second_stage_localization_loss_weight) - - common_kwargs = { - 'is_training': is_training, - 'num_classes': num_classes, - 'image_resizer_fn': image_resizer_fn, - 'feature_extractor': feature_extractor, - 'number_of_stages': number_of_stages, - 'first_stage_anchor_generator': first_stage_anchor_generator, - 'first_stage_atrous_rate': first_stage_atrous_rate, - 'first_stage_box_predictor_arg_scope_fn': - first_stage_box_predictor_arg_scope_fn, - 'first_stage_box_predictor_kernel_size': - first_stage_box_predictor_kernel_size, - 'first_stage_box_predictor_depth': first_stage_box_predictor_depth, - 'first_stage_minibatch_size': first_stage_minibatch_size, - 'first_stage_positive_balance_fraction': - first_stage_positive_balance_fraction, - 'first_stage_nms_score_threshold': first_stage_nms_score_threshold, - 'first_stage_nms_iou_threshold': first_stage_nms_iou_threshold, - 'first_stage_max_proposals': first_stage_max_proposals, - 'first_stage_localization_loss_weight': first_stage_loc_loss_weight, - 'first_stage_objectness_loss_weight': first_stage_obj_loss_weight, - 'second_stage_batch_size': second_stage_batch_size, - 'second_stage_balance_fraction': second_stage_balance_fraction, - 'second_stage_non_max_suppression_fn': - second_stage_non_max_suppression_fn, - 'second_stage_score_conversion_fn': second_stage_score_conversion_fn, - 'second_stage_localization_loss_weight': - second_stage_localization_loss_weight, - 'second_stage_classification_loss': - second_stage_classification_loss, - 'second_stage_classification_loss_weight': - second_stage_classification_loss_weight, - 'hard_example_miner': hard_example_miner, - 'add_summaries': add_summaries} - - if isinstance(second_stage_box_predictor, box_predictor.RfcnBoxPredictor): - return rfcn_meta_arch.RFCNMetaArch( - second_stage_rfcn_box_predictor=second_stage_box_predictor, - **common_kwargs) - else: - return faster_rcnn_meta_arch.FasterRCNNMetaArch( - initial_crop_size=initial_crop_size, - maxpool_kernel_size=maxpool_kernel_size, - maxpool_stride=maxpool_stride, - second_stage_mask_rcnn_box_predictor=second_stage_box_predictor, - second_stage_mask_prediction_loss_weight=( - second_stage_mask_prediction_loss_weight), - **common_kwargs) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder_test.py deleted file mode 100644 index 225e1d50b..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder_test.py +++ /dev/null @@ -1,1056 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.models.model_builder.""" - -import tensorflow as tf - -from google.protobuf import text_format -from object_detection.builders import model_builder -from object_detection.meta_architectures import faster_rcnn_meta_arch -from object_detection.meta_architectures import rfcn_meta_arch -from object_detection.meta_architectures import ssd_meta_arch -from object_detection.models import faster_rcnn_inception_resnet_v2_feature_extractor as frcnn_inc_res -from object_detection.models import faster_rcnn_inception_v2_feature_extractor as frcnn_inc_v2 -from object_detection.models import faster_rcnn_nas_feature_extractor as frcnn_nas -from object_detection.models import faster_rcnn_pnas_feature_extractor as frcnn_pnas -from object_detection.models import faster_rcnn_resnet_v1_feature_extractor as frcnn_resnet_v1 -from object_detection.models import ssd_resnet_v1_fpn_feature_extractor as ssd_resnet_v1_fpn -from object_detection.models.embedded_ssd_mobilenet_v1_feature_extractor import EmbeddedSSDMobileNetV1FeatureExtractor -from object_detection.models.ssd_inception_v2_feature_extractor import SSDInceptionV2FeatureExtractor -from object_detection.models.ssd_inception_v3_feature_extractor import SSDInceptionV3FeatureExtractor -from object_detection.models.ssd_mobilenet_v1_feature_extractor import SSDMobileNetV1FeatureExtractor -from object_detection.models.ssd_mobilenet_v2_feature_extractor import SSDMobileNetV2FeatureExtractor -from object_detection.protos import model_pb2 - -FRCNN_RESNET_FEAT_MAPS = { - 'faster_rcnn_resnet50': - frcnn_resnet_v1.FasterRCNNResnet50FeatureExtractor, - 'faster_rcnn_resnet101': - frcnn_resnet_v1.FasterRCNNResnet101FeatureExtractor, - 'faster_rcnn_resnet152': - frcnn_resnet_v1.FasterRCNNResnet152FeatureExtractor -} - -SSD_RESNET_V1_FPN_FEAT_MAPS = { - 'ssd_resnet50_v1_fpn': - ssd_resnet_v1_fpn.SSDResnet50V1FpnFeatureExtractor, - 'ssd_resnet101_v1_fpn': - ssd_resnet_v1_fpn.SSDResnet101V1FpnFeatureExtractor, - 'ssd_resnet152_v1_fpn': - ssd_resnet_v1_fpn.SSDResnet152V1FpnFeatureExtractor -} - - -class ModelBuilderTest(tf.test.TestCase): - - def create_model(self, model_config): - """Builds a DetectionModel based on the model config. - - Args: - model_config: A model.proto object containing the config for the desired - DetectionModel. - - Returns: - DetectionModel based on the config. - """ - return model_builder.build(model_config, is_training=True) - - def test_create_ssd_inception_v2_model_from_config(self): - model_text_proto = """ - ssd { - feature_extractor { - type: 'ssd_inception_v2' - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - override_base_feature_extractor_hyperparams: true - } - box_coder { - faster_rcnn_box_coder { - } - } - matcher { - argmax_matcher { - } - } - similarity_calculator { - iou_similarity { - } - } - anchor_generator { - ssd_anchor_generator { - aspect_ratios: 1.0 - } - } - image_resizer { - fixed_shape_resizer { - height: 320 - width: 320 - } - } - box_predictor { - convolutional_box_predictor { - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - loss { - classification_loss { - weighted_softmax { - } - } - localization_loss { - weighted_smooth_l1 { - } - } - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = self.create_model(model_proto) - self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch) - self.assertIsInstance(model._feature_extractor, - SSDInceptionV2FeatureExtractor) - - def test_create_ssd_inception_v3_model_from_config(self): - model_text_proto = """ - ssd { - feature_extractor { - type: 'ssd_inception_v3' - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - override_base_feature_extractor_hyperparams: true - } - box_coder { - faster_rcnn_box_coder { - } - } - matcher { - argmax_matcher { - } - } - similarity_calculator { - iou_similarity { - } - } - anchor_generator { - ssd_anchor_generator { - aspect_ratios: 1.0 - } - } - image_resizer { - fixed_shape_resizer { - height: 320 - width: 320 - } - } - box_predictor { - convolutional_box_predictor { - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - loss { - classification_loss { - weighted_softmax { - } - } - localization_loss { - weighted_smooth_l1 { - } - } - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = self.create_model(model_proto) - self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch) - self.assertIsInstance(model._feature_extractor, - SSDInceptionV3FeatureExtractor) - - def test_create_ssd_resnet_v1_fpn_model_from_config(self): - model_text_proto = """ - ssd { - feature_extractor { - type: 'ssd_resnet50_v1_fpn' - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - box_coder { - faster_rcnn_box_coder { - } - } - matcher { - argmax_matcher { - } - } - similarity_calculator { - iou_similarity { - } - } - encode_background_as_zeros: true - anchor_generator { - multiscale_anchor_generator { - aspect_ratios: [1.0, 2.0, 0.5] - scales_per_octave: 2 - } - } - image_resizer { - fixed_shape_resizer { - height: 320 - width: 320 - } - } - box_predictor { - weight_shared_convolutional_box_predictor { - depth: 32 - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - random_normal_initializer { - } - } - } - num_layers_before_predictor: 1 - } - } - normalize_loss_by_num_matches: true - normalize_loc_loss_by_codesize: true - loss { - classification_loss { - weighted_sigmoid_focal { - alpha: 0.25 - gamma: 2.0 - } - } - localization_loss { - weighted_smooth_l1 { - delta: 0.1 - } - } - classification_weight: 1.0 - localization_weight: 1.0 - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - - for extractor_type, extractor_class in SSD_RESNET_V1_FPN_FEAT_MAPS.items(): - model_proto.ssd.feature_extractor.type = extractor_type - model = model_builder.build(model_proto, is_training=True) - self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch) - self.assertIsInstance(model._feature_extractor, extractor_class) - - def test_create_ssd_mobilenet_v1_model_from_config(self): - model_text_proto = """ - ssd { - freeze_batchnorm: true - inplace_batchnorm_update: true - feature_extractor { - type: 'ssd_mobilenet_v1' - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - box_coder { - faster_rcnn_box_coder { - } - } - matcher { - argmax_matcher { - } - } - similarity_calculator { - iou_similarity { - } - } - anchor_generator { - ssd_anchor_generator { - aspect_ratios: 1.0 - } - } - image_resizer { - fixed_shape_resizer { - height: 320 - width: 320 - } - } - box_predictor { - convolutional_box_predictor { - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - normalize_loc_loss_by_codesize: true - loss { - classification_loss { - weighted_softmax { - } - } - localization_loss { - weighted_smooth_l1 { - } - } - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = self.create_model(model_proto) - self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch) - self.assertIsInstance(model._feature_extractor, - SSDMobileNetV1FeatureExtractor) - self.assertTrue(model._normalize_loc_loss_by_codesize) - self.assertTrue(model._freeze_batchnorm) - self.assertTrue(model._inplace_batchnorm_update) - - def test_create_ssd_mobilenet_v2_model_from_config(self): - model_text_proto = """ - ssd { - feature_extractor { - type: 'ssd_mobilenet_v2' - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - box_coder { - faster_rcnn_box_coder { - } - } - matcher { - argmax_matcher { - } - } - similarity_calculator { - iou_similarity { - } - } - anchor_generator { - ssd_anchor_generator { - aspect_ratios: 1.0 - } - } - image_resizer { - fixed_shape_resizer { - height: 320 - width: 320 - } - } - box_predictor { - convolutional_box_predictor { - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - normalize_loc_loss_by_codesize: true - loss { - classification_loss { - weighted_softmax { - } - } - localization_loss { - weighted_smooth_l1 { - } - } - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = self.create_model(model_proto) - self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch) - self.assertIsInstance(model._feature_extractor, - SSDMobileNetV2FeatureExtractor) - self.assertTrue(model._normalize_loc_loss_by_codesize) - - def test_create_embedded_ssd_mobilenet_v1_model_from_config(self): - model_text_proto = """ - ssd { - feature_extractor { - type: 'embedded_ssd_mobilenet_v1' - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - box_coder { - faster_rcnn_box_coder { - } - } - matcher { - argmax_matcher { - } - } - similarity_calculator { - iou_similarity { - } - } - anchor_generator { - ssd_anchor_generator { - aspect_ratios: 1.0 - } - } - image_resizer { - fixed_shape_resizer { - height: 256 - width: 256 - } - } - box_predictor { - convolutional_box_predictor { - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - loss { - classification_loss { - weighted_softmax { - } - } - localization_loss { - weighted_smooth_l1 { - } - } - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = self.create_model(model_proto) - self.assertIsInstance(model, ssd_meta_arch.SSDMetaArch) - self.assertIsInstance(model._feature_extractor, - EmbeddedSSDMobileNetV1FeatureExtractor) - - def test_create_faster_rcnn_resnet_v1_models_from_config(self): - model_text_proto = """ - faster_rcnn { - inplace_batchnorm_update: true - num_classes: 3 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 600 - max_dimension: 1024 - } - } - feature_extractor { - type: 'faster_rcnn_resnet101' - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 16 - width_stride: 16 - } - } - first_stage_box_predictor_conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - initial_crop_size: 14 - maxpool_kernel_size: 2 - maxpool_stride: 2 - second_stage_box_predictor { - mask_rcnn_box_predictor { - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.01 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - score_converter: SOFTMAX - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - for extractor_type, extractor_class in FRCNN_RESNET_FEAT_MAPS.items(): - model_proto.faster_rcnn.feature_extractor.type = extractor_type - model = model_builder.build(model_proto, is_training=True) - self.assertIsInstance(model, faster_rcnn_meta_arch.FasterRCNNMetaArch) - self.assertIsInstance(model._feature_extractor, extractor_class) - - def test_create_faster_rcnn_resnet101_with_mask_prediction_enabled(self): - model_text_proto = """ - faster_rcnn { - num_classes: 3 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 600 - max_dimension: 1024 - } - } - feature_extractor { - type: 'faster_rcnn_resnet101' - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 16 - width_stride: 16 - } - } - first_stage_box_predictor_conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - initial_crop_size: 14 - maxpool_kernel_size: 2 - maxpool_stride: 2 - second_stage_box_predictor { - mask_rcnn_box_predictor { - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - predict_instance_masks: true - } - } - second_stage_mask_prediction_loss_weight: 3.0 - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.01 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - score_converter: SOFTMAX - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = model_builder.build(model_proto, is_training=True) - self.assertAlmostEqual(model._second_stage_mask_loss_weight, 3.0) - - def test_create_faster_rcnn_nas_model_from_config(self): - model_text_proto = """ - faster_rcnn { - num_classes: 3 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 600 - max_dimension: 1024 - } - } - feature_extractor { - type: 'faster_rcnn_nas' - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 16 - width_stride: 16 - } - } - first_stage_box_predictor_conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - initial_crop_size: 17 - maxpool_kernel_size: 1 - maxpool_stride: 1 - second_stage_box_predictor { - mask_rcnn_box_predictor { - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.01 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - score_converter: SOFTMAX - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = model_builder.build(model_proto, is_training=True) - self.assertIsInstance(model, faster_rcnn_meta_arch.FasterRCNNMetaArch) - self.assertIsInstance( - model._feature_extractor, - frcnn_nas.FasterRCNNNASFeatureExtractor) - - def test_create_faster_rcnn_pnas_model_from_config(self): - model_text_proto = """ - faster_rcnn { - num_classes: 3 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 600 - max_dimension: 1024 - } - } - feature_extractor { - type: 'faster_rcnn_pnas' - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 16 - width_stride: 16 - } - } - first_stage_box_predictor_conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - initial_crop_size: 17 - maxpool_kernel_size: 1 - maxpool_stride: 1 - second_stage_box_predictor { - mask_rcnn_box_predictor { - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.01 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - score_converter: SOFTMAX - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = model_builder.build(model_proto, is_training=True) - self.assertIsInstance(model, faster_rcnn_meta_arch.FasterRCNNMetaArch) - self.assertIsInstance( - model._feature_extractor, - frcnn_pnas.FasterRCNNPNASFeatureExtractor) - - def test_create_faster_rcnn_inception_resnet_v2_model_from_config(self): - model_text_proto = """ - faster_rcnn { - num_classes: 3 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 600 - max_dimension: 1024 - } - } - feature_extractor { - type: 'faster_rcnn_inception_resnet_v2' - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 16 - width_stride: 16 - } - } - first_stage_box_predictor_conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - initial_crop_size: 17 - maxpool_kernel_size: 1 - maxpool_stride: 1 - second_stage_box_predictor { - mask_rcnn_box_predictor { - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.01 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - score_converter: SOFTMAX - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = model_builder.build(model_proto, is_training=True) - self.assertIsInstance(model, faster_rcnn_meta_arch.FasterRCNNMetaArch) - self.assertIsInstance( - model._feature_extractor, - frcnn_inc_res.FasterRCNNInceptionResnetV2FeatureExtractor) - - def test_create_faster_rcnn_inception_v2_model_from_config(self): - model_text_proto = """ - faster_rcnn { - num_classes: 3 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 600 - max_dimension: 1024 - } - } - feature_extractor { - type: 'faster_rcnn_inception_v2' - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 16 - width_stride: 16 - } - } - first_stage_box_predictor_conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - initial_crop_size: 14 - maxpool_kernel_size: 2 - maxpool_stride: 2 - second_stage_box_predictor { - mask_rcnn_box_predictor { - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.01 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - score_converter: SOFTMAX - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = model_builder.build(model_proto, is_training=True) - self.assertIsInstance(model, faster_rcnn_meta_arch.FasterRCNNMetaArch) - self.assertIsInstance(model._feature_extractor, - frcnn_inc_v2.FasterRCNNInceptionV2FeatureExtractor) - - def test_create_faster_rcnn_model_from_config_with_example_miner(self): - model_text_proto = """ - faster_rcnn { - num_classes: 3 - feature_extractor { - type: 'faster_rcnn_inception_resnet_v2' - } - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 600 - max_dimension: 1024 - } - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 16 - width_stride: 16 - } - } - first_stage_box_predictor_conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - second_stage_box_predictor { - mask_rcnn_box_predictor { - fc_hyperparams { - op: FC - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - hard_example_miner { - num_hard_examples: 10 - iou_threshold: 0.99 - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - model = model_builder.build(model_proto, is_training=True) - self.assertIsNotNone(model._hard_example_miner) - - def test_create_rfcn_resnet_v1_model_from_config(self): - model_text_proto = """ - faster_rcnn { - num_classes: 3 - image_resizer { - keep_aspect_ratio_resizer { - min_dimension: 600 - max_dimension: 1024 - } - } - feature_extractor { - type: 'faster_rcnn_resnet101' - } - first_stage_anchor_generator { - grid_anchor_generator { - scales: [0.25, 0.5, 1.0, 2.0] - aspect_ratios: [0.5, 1.0, 2.0] - height_stride: 16 - width_stride: 16 - } - } - first_stage_box_predictor_conv_hyperparams { - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - initial_crop_size: 14 - maxpool_kernel_size: 2 - maxpool_stride: 2 - second_stage_box_predictor { - rfcn_box_predictor { - conv_hyperparams { - op: CONV - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - } - } - } - second_stage_post_processing { - batch_non_max_suppression { - score_threshold: 0.01 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - score_converter: SOFTMAX - } - }""" - model_proto = model_pb2.DetectionModel() - text_format.Merge(model_text_proto, model_proto) - for extractor_type, extractor_class in FRCNN_RESNET_FEAT_MAPS.items(): - model_proto.faster_rcnn.feature_extractor.type = extractor_type - model = model_builder.build(model_proto, is_training=True) - self.assertIsInstance(model, rfcn_meta_arch.RFCNMetaArch) - self.assertIsInstance(model._feature_extractor, extractor_class) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder.py deleted file mode 100644 index e3a437f0d..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Functions to build DetectionModel training optimizers.""" - -import tensorflow as tf -from object_detection.utils import learning_schedules - - -def build(optimizer_config): - """Create optimizer based on config. - - Args: - optimizer_config: A Optimizer proto message. - - Returns: - An optimizer and a list of variables for summary. - - Raises: - ValueError: when using an unsupported input data type. - """ - optimizer_type = optimizer_config.WhichOneof('optimizer') - optimizer = None - - summary_vars = [] - if optimizer_type == 'rms_prop_optimizer': - config = optimizer_config.rms_prop_optimizer - learning_rate = _create_learning_rate(config.learning_rate) - summary_vars.append(learning_rate) - optimizer = tf.train.RMSPropOptimizer( - learning_rate, - decay=config.decay, - momentum=config.momentum_optimizer_value, - epsilon=config.epsilon) - - if optimizer_type == 'momentum_optimizer': - config = optimizer_config.momentum_optimizer - learning_rate = _create_learning_rate(config.learning_rate) - summary_vars.append(learning_rate) - optimizer = tf.train.MomentumOptimizer( - learning_rate, - momentum=config.momentum_optimizer_value) - - if optimizer_type == 'adam_optimizer': - config = optimizer_config.adam_optimizer - learning_rate = _create_learning_rate(config.learning_rate) - summary_vars.append(learning_rate) - optimizer = tf.train.AdamOptimizer(learning_rate) - - if optimizer is None: - raise ValueError('Optimizer %s not supported.' % optimizer_type) - - if optimizer_config.use_moving_average: - optimizer = tf.contrib.opt.MovingAverageOptimizer( - optimizer, average_decay=optimizer_config.moving_average_decay) - - return optimizer, summary_vars - - -def _create_learning_rate(learning_rate_config): - """Create optimizer learning rate based on config. - - Args: - learning_rate_config: A LearningRate proto message. - - Returns: - A learning rate. - - Raises: - ValueError: when using an unsupported input data type. - """ - learning_rate = None - learning_rate_type = learning_rate_config.WhichOneof('learning_rate') - if learning_rate_type == 'constant_learning_rate': - config = learning_rate_config.constant_learning_rate - learning_rate = tf.constant(config.learning_rate, dtype=tf.float32, - name='learning_rate') - - if learning_rate_type == 'exponential_decay_learning_rate': - config = learning_rate_config.exponential_decay_learning_rate - learning_rate = tf.train.exponential_decay( - config.initial_learning_rate, - tf.train.get_or_create_global_step(), - config.decay_steps, - config.decay_factor, - staircase=config.staircase, name='learning_rate') - - if learning_rate_type == 'manual_step_learning_rate': - config = learning_rate_config.manual_step_learning_rate - if not config.schedule: - raise ValueError('Empty learning rate schedule.') - learning_rate_step_boundaries = [x.step for x in config.schedule] - learning_rate_sequence = [config.initial_learning_rate] - learning_rate_sequence += [x.learning_rate for x in config.schedule] - learning_rate = learning_schedules.manual_stepping( - tf.train.get_or_create_global_step(), learning_rate_step_boundaries, - learning_rate_sequence, config.warmup) - - if learning_rate_type == 'cosine_decay_learning_rate': - config = learning_rate_config.cosine_decay_learning_rate - learning_rate = learning_schedules.cosine_decay_with_warmup( - tf.train.get_or_create_global_step(), - config.learning_rate_base, - config.total_steps, - config.warmup_learning_rate, - config.warmup_steps, - config.hold_base_rate_steps) - - if learning_rate is None: - raise ValueError('Learning_rate %s not supported.' % learning_rate_type) - - return learning_rate diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder_test.py deleted file mode 100644 index 343a858fb..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder_test.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for optimizer_builder.""" - -import tensorflow as tf - -from google.protobuf import text_format - -from object_detection.builders import optimizer_builder -from object_detection.protos import optimizer_pb2 - - -class LearningRateBuilderTest(tf.test.TestCase): - - def testBuildConstantLearningRate(self): - learning_rate_text_proto = """ - constant_learning_rate { - learning_rate: 0.004 - } - """ - learning_rate_proto = optimizer_pb2.LearningRate() - text_format.Merge(learning_rate_text_proto, learning_rate_proto) - learning_rate = optimizer_builder._create_learning_rate( - learning_rate_proto) - self.assertTrue(learning_rate.op.name.endswith('learning_rate')) - with self.test_session(): - learning_rate_out = learning_rate.eval() - self.assertAlmostEqual(learning_rate_out, 0.004) - - def testBuildExponentialDecayLearningRate(self): - learning_rate_text_proto = """ - exponential_decay_learning_rate { - initial_learning_rate: 0.004 - decay_steps: 99999 - decay_factor: 0.85 - staircase: false - } - """ - learning_rate_proto = optimizer_pb2.LearningRate() - text_format.Merge(learning_rate_text_proto, learning_rate_proto) - learning_rate = optimizer_builder._create_learning_rate( - learning_rate_proto) - self.assertTrue(learning_rate.op.name.endswith('learning_rate')) - self.assertTrue(isinstance(learning_rate, tf.Tensor)) - - def testBuildManualStepLearningRate(self): - learning_rate_text_proto = """ - manual_step_learning_rate { - initial_learning_rate: 0.002 - schedule { - step: 100 - learning_rate: 0.006 - } - schedule { - step: 90000 - learning_rate: 0.00006 - } - warmup: true - } - """ - learning_rate_proto = optimizer_pb2.LearningRate() - text_format.Merge(learning_rate_text_proto, learning_rate_proto) - learning_rate = optimizer_builder._create_learning_rate( - learning_rate_proto) - self.assertTrue(isinstance(learning_rate, tf.Tensor)) - - def testBuildCosineDecayLearningRate(self): - learning_rate_text_proto = """ - cosine_decay_learning_rate { - learning_rate_base: 0.002 - total_steps: 20000 - warmup_learning_rate: 0.0001 - warmup_steps: 1000 - hold_base_rate_steps: 20000 - } - """ - learning_rate_proto = optimizer_pb2.LearningRate() - text_format.Merge(learning_rate_text_proto, learning_rate_proto) - learning_rate = optimizer_builder._create_learning_rate( - learning_rate_proto) - self.assertTrue(isinstance(learning_rate, tf.Tensor)) - - def testRaiseErrorOnEmptyLearningRate(self): - learning_rate_text_proto = """ - """ - learning_rate_proto = optimizer_pb2.LearningRate() - text_format.Merge(learning_rate_text_proto, learning_rate_proto) - with self.assertRaises(ValueError): - optimizer_builder._create_learning_rate(learning_rate_proto) - - -class OptimizerBuilderTest(tf.test.TestCase): - - def testBuildRMSPropOptimizer(self): - optimizer_text_proto = """ - rms_prop_optimizer: { - learning_rate: { - exponential_decay_learning_rate { - initial_learning_rate: 0.004 - decay_steps: 800720 - decay_factor: 0.95 - } - } - momentum_optimizer_value: 0.9 - decay: 0.9 - epsilon: 1.0 - } - use_moving_average: false - """ - optimizer_proto = optimizer_pb2.Optimizer() - text_format.Merge(optimizer_text_proto, optimizer_proto) - optimizer, _ = optimizer_builder.build(optimizer_proto) - self.assertTrue(isinstance(optimizer, tf.train.RMSPropOptimizer)) - - def testBuildMomentumOptimizer(self): - optimizer_text_proto = """ - momentum_optimizer: { - learning_rate: { - constant_learning_rate { - learning_rate: 0.001 - } - } - momentum_optimizer_value: 0.99 - } - use_moving_average: false - """ - optimizer_proto = optimizer_pb2.Optimizer() - text_format.Merge(optimizer_text_proto, optimizer_proto) - optimizer, _ = optimizer_builder.build(optimizer_proto) - self.assertTrue(isinstance(optimizer, tf.train.MomentumOptimizer)) - - def testBuildAdamOptimizer(self): - optimizer_text_proto = """ - adam_optimizer: { - learning_rate: { - constant_learning_rate { - learning_rate: 0.002 - } - } - } - use_moving_average: false - """ - optimizer_proto = optimizer_pb2.Optimizer() - text_format.Merge(optimizer_text_proto, optimizer_proto) - optimizer, _ = optimizer_builder.build(optimizer_proto) - self.assertTrue(isinstance(optimizer, tf.train.AdamOptimizer)) - - def testBuildMovingAverageOptimizer(self): - optimizer_text_proto = """ - adam_optimizer: { - learning_rate: { - constant_learning_rate { - learning_rate: 0.002 - } - } - } - use_moving_average: True - """ - optimizer_proto = optimizer_pb2.Optimizer() - text_format.Merge(optimizer_text_proto, optimizer_proto) - optimizer, _ = optimizer_builder.build(optimizer_proto) - self.assertTrue( - isinstance(optimizer, tf.contrib.opt.MovingAverageOptimizer)) - - def testBuildMovingAverageOptimizerWithNonDefaultDecay(self): - optimizer_text_proto = """ - adam_optimizer: { - learning_rate: { - constant_learning_rate { - learning_rate: 0.002 - } - } - } - use_moving_average: True - moving_average_decay: 0.2 - """ - optimizer_proto = optimizer_pb2.Optimizer() - text_format.Merge(optimizer_text_proto, optimizer_proto) - optimizer, _ = optimizer_builder.build(optimizer_proto) - self.assertTrue( - isinstance(optimizer, tf.contrib.opt.MovingAverageOptimizer)) - # TODO(rathodv): Find a way to not depend on the private members. - self.assertAlmostEqual(optimizer._ema._decay, 0.2) - - def testBuildEmptyOptimizer(self): - optimizer_text_proto = """ - """ - optimizer_proto = optimizer_pb2.Optimizer() - text_format.Merge(optimizer_text_proto, optimizer_proto) - with self.assertRaises(ValueError): - optimizer_builder.build(optimizer_proto) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder.py deleted file mode 100644 index fa3a77289..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Builder function for post processing operations.""" -import functools - -import tensorflow as tf -from object_detection.core import post_processing -from object_detection.protos import post_processing_pb2 - - -def build(post_processing_config): - """Builds callables for post-processing operations. - - Builds callables for non-max suppression and score conversion based on the - configuration. - - Non-max suppression callable takes `boxes`, `scores`, and optionally - `clip_window`, `parallel_iterations` `masks, and `scope` as inputs. It returns - `nms_boxes`, `nms_scores`, `nms_classes` `nms_masks` and `num_detections`. See - post_processing.batch_multiclass_non_max_suppression for the type and shape - of these tensors. - - Score converter callable should be called with `input` tensor. The callable - returns the output from one of 3 tf operations based on the configuration - - tf.identity, tf.sigmoid or tf.nn.softmax. See tensorflow documentation for - argument and return value descriptions. - - Args: - post_processing_config: post_processing.proto object containing the - parameters for the post-processing operations. - - Returns: - non_max_suppressor_fn: Callable for non-max suppression. - score_converter_fn: Callable for score conversion. - - Raises: - ValueError: if the post_processing_config is of incorrect type. - """ - if not isinstance(post_processing_config, post_processing_pb2.PostProcessing): - raise ValueError('post_processing_config not of type ' - 'post_processing_pb2.Postprocessing.') - non_max_suppressor_fn = _build_non_max_suppressor( - post_processing_config.batch_non_max_suppression) - score_converter_fn = _build_score_converter( - post_processing_config.score_converter, - post_processing_config.logit_scale) - return non_max_suppressor_fn, score_converter_fn - - -def _build_non_max_suppressor(nms_config): - """Builds non-max suppresson based on the nms config. - - Args: - nms_config: post_processing_pb2.PostProcessing.BatchNonMaxSuppression proto. - - Returns: - non_max_suppressor_fn: Callable non-max suppressor. - - Raises: - ValueError: On incorrect iou_threshold or on incompatible values of - max_total_detections and max_detections_per_class. - """ - if nms_config.iou_threshold < 0 or nms_config.iou_threshold > 1.0: - raise ValueError('iou_threshold not in [0, 1.0].') - if nms_config.max_detections_per_class > nms_config.max_total_detections: - raise ValueError('max_detections_per_class should be no greater than ' - 'max_total_detections.') - - non_max_suppressor_fn = functools.partial( - post_processing.batch_multiclass_non_max_suppression, - score_thresh=nms_config.score_threshold, - iou_thresh=nms_config.iou_threshold, - max_size_per_class=nms_config.max_detections_per_class, - max_total_size=nms_config.max_total_detections) - return non_max_suppressor_fn - - -def _score_converter_fn_with_logit_scale(tf_score_converter_fn, logit_scale): - """Create a function to scale logits then apply a Tensorflow function.""" - def score_converter_fn(logits): - scaled_logits = tf.divide(logits, logit_scale, name='scale_logits') - return tf_score_converter_fn(scaled_logits, name='convert_scores') - score_converter_fn.__name__ = '%s_with_logit_scale' % ( - tf_score_converter_fn.__name__) - return score_converter_fn - - -def _build_score_converter(score_converter_config, logit_scale): - """Builds score converter based on the config. - - Builds one of [tf.identity, tf.sigmoid, tf.softmax] score converters based on - the config. - - Args: - score_converter_config: post_processing_pb2.PostProcessing.score_converter. - logit_scale: temperature to use for SOFTMAX score_converter. - - Returns: - Callable score converter op. - - Raises: - ValueError: On unknown score converter. - """ - if score_converter_config == post_processing_pb2.PostProcessing.IDENTITY: - return _score_converter_fn_with_logit_scale(tf.identity, logit_scale) - if score_converter_config == post_processing_pb2.PostProcessing.SIGMOID: - return _score_converter_fn_with_logit_scale(tf.sigmoid, logit_scale) - if score_converter_config == post_processing_pb2.PostProcessing.SOFTMAX: - return _score_converter_fn_with_logit_scale(tf.nn.softmax, logit_scale) - raise ValueError('Unknown score converter.') diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder_test.py deleted file mode 100644 index c39fbfb41..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder_test.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for post_processing_builder.""" - -import tensorflow as tf -from google.protobuf import text_format -from object_detection.builders import post_processing_builder -from object_detection.protos import post_processing_pb2 - - -class PostProcessingBuilderTest(tf.test.TestCase): - - def test_build_non_max_suppressor_with_correct_parameters(self): - post_processing_text_proto = """ - batch_non_max_suppression { - score_threshold: 0.7 - iou_threshold: 0.6 - max_detections_per_class: 100 - max_total_detections: 300 - } - """ - post_processing_config = post_processing_pb2.PostProcessing() - text_format.Merge(post_processing_text_proto, post_processing_config) - non_max_suppressor, _ = post_processing_builder.build( - post_processing_config) - self.assertEqual(non_max_suppressor.keywords['max_size_per_class'], 100) - self.assertEqual(non_max_suppressor.keywords['max_total_size'], 300) - self.assertAlmostEqual(non_max_suppressor.keywords['score_thresh'], 0.7) - self.assertAlmostEqual(non_max_suppressor.keywords['iou_thresh'], 0.6) - - def test_build_identity_score_converter(self): - post_processing_text_proto = """ - score_converter: IDENTITY - """ - post_processing_config = post_processing_pb2.PostProcessing() - text_format.Merge(post_processing_text_proto, post_processing_config) - _, score_converter = post_processing_builder.build(post_processing_config) - self.assertEqual(score_converter.__name__, 'identity_with_logit_scale') - - inputs = tf.constant([1, 1], tf.float32) - outputs = score_converter(inputs) - with self.test_session() as sess: - converted_scores = sess.run(outputs) - expected_converted_scores = sess.run(inputs) - self.assertAllClose(converted_scores, expected_converted_scores) - - def test_build_identity_score_converter_with_logit_scale(self): - post_processing_text_proto = """ - score_converter: IDENTITY - logit_scale: 2.0 - """ - post_processing_config = post_processing_pb2.PostProcessing() - text_format.Merge(post_processing_text_proto, post_processing_config) - _, score_converter = post_processing_builder.build(post_processing_config) - self.assertEqual(score_converter.__name__, 'identity_with_logit_scale') - - inputs = tf.constant([1, 1], tf.float32) - outputs = score_converter(inputs) - with self.test_session() as sess: - converted_scores = sess.run(outputs) - expected_converted_scores = sess.run(tf.constant([.5, .5], tf.float32)) - self.assertAllClose(converted_scores, expected_converted_scores) - - def test_build_sigmoid_score_converter(self): - post_processing_text_proto = """ - score_converter: SIGMOID - """ - post_processing_config = post_processing_pb2.PostProcessing() - text_format.Merge(post_processing_text_proto, post_processing_config) - _, score_converter = post_processing_builder.build(post_processing_config) - self.assertEqual(score_converter.__name__, 'sigmoid_with_logit_scale') - - def test_build_softmax_score_converter(self): - post_processing_text_proto = """ - score_converter: SOFTMAX - """ - post_processing_config = post_processing_pb2.PostProcessing() - text_format.Merge(post_processing_text_proto, post_processing_config) - _, score_converter = post_processing_builder.build(post_processing_config) - self.assertEqual(score_converter.__name__, 'softmax_with_logit_scale') - - def test_build_softmax_score_converter_with_temperature(self): - post_processing_text_proto = """ - score_converter: SOFTMAX - logit_scale: 2.0 - """ - post_processing_config = post_processing_pb2.PostProcessing() - text_format.Merge(post_processing_text_proto, post_processing_config) - _, score_converter = post_processing_builder.build(post_processing_config) - self.assertEqual(score_converter.__name__, 'softmax_with_logit_scale') - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder.py deleted file mode 100644 index 10b92532f..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder.py +++ /dev/null @@ -1,322 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Builder for preprocessing steps.""" - -import tensorflow as tf - -from object_detection.core import preprocessor -from object_detection.protos import preprocessor_pb2 - - -def _get_step_config_from_proto(preprocessor_step_config, step_name): - """Returns the value of a field named step_name from proto. - - Args: - preprocessor_step_config: A preprocessor_pb2.PreprocessingStep object. - step_name: Name of the field to get value from. - - Returns: - result_dict: a sub proto message from preprocessor_step_config which will be - later converted to a dictionary. - - Raises: - ValueError: If field does not exist in proto. - """ - for field, value in preprocessor_step_config.ListFields(): - if field.name == step_name: - return value - - raise ValueError('Could not get field %s from proto!', step_name) - - -def _get_dict_from_proto(config): - """Helper function to put all proto fields into a dictionary. - - For many preprocessing steps, there's an trivial 1-1 mapping from proto fields - to function arguments. This function automatically populates a dictionary with - the arguments from the proto. - - Protos that CANNOT be trivially populated include: - * nested messages. - * steps that check if an optional field is set (ie. where None != 0). - * protos that don't map 1-1 to arguments (ie. list should be reshaped). - * fields requiring additional validation (ie. repeated field has n elements). - - Args: - config: A protobuf object that does not violate the conditions above. - - Returns: - result_dict: |config| converted into a python dictionary. - """ - result_dict = {} - for field, value in config.ListFields(): - result_dict[field.name] = value - return result_dict - - -# A map from a PreprocessingStep proto config field name to the preprocessing -# function that should be used. The PreprocessingStep proto should be parsable -# with _get_dict_from_proto. -PREPROCESSING_FUNCTION_MAP = { - 'normalize_image': preprocessor.normalize_image, - 'random_pixel_value_scale': preprocessor.random_pixel_value_scale, - 'random_image_scale': preprocessor.random_image_scale, - 'random_rgb_to_gray': preprocessor.random_rgb_to_gray, - 'random_adjust_brightness': preprocessor.random_adjust_brightness, - 'random_adjust_contrast': preprocessor.random_adjust_contrast, - 'random_adjust_hue': preprocessor.random_adjust_hue, - 'random_adjust_saturation': preprocessor.random_adjust_saturation, - 'random_distort_color': preprocessor.random_distort_color, - 'random_jitter_boxes': preprocessor.random_jitter_boxes, - 'random_crop_to_aspect_ratio': preprocessor.random_crop_to_aspect_ratio, - 'random_black_patches': preprocessor.random_black_patches, - 'rgb_to_gray': preprocessor.rgb_to_gray, - 'scale_boxes_to_pixel_coordinates': ( - preprocessor.scale_boxes_to_pixel_coordinates), - 'subtract_channel_mean': preprocessor.subtract_channel_mean, -} - - -# A map to convert from preprocessor_pb2.ResizeImage.Method enum to -# tf.image.ResizeMethod. -RESIZE_METHOD_MAP = { - preprocessor_pb2.ResizeImage.AREA: tf.image.ResizeMethod.AREA, - preprocessor_pb2.ResizeImage.BICUBIC: tf.image.ResizeMethod.BICUBIC, - preprocessor_pb2.ResizeImage.BILINEAR: tf.image.ResizeMethod.BILINEAR, - preprocessor_pb2.ResizeImage.NEAREST_NEIGHBOR: ( - tf.image.ResizeMethod.NEAREST_NEIGHBOR), -} - - -def build(preprocessor_step_config): - """Builds preprocessing step based on the configuration. - - Args: - preprocessor_step_config: PreprocessingStep configuration proto. - - Returns: - function, argmap: A callable function and an argument map to call function - with. - - Raises: - ValueError: On invalid configuration. - """ - step_type = preprocessor_step_config.WhichOneof('preprocessing_step') - - if step_type in PREPROCESSING_FUNCTION_MAP: - preprocessing_function = PREPROCESSING_FUNCTION_MAP[step_type] - step_config = _get_step_config_from_proto(preprocessor_step_config, - step_type) - function_args = _get_dict_from_proto(step_config) - return (preprocessing_function, function_args) - - if step_type == 'random_horizontal_flip': - config = preprocessor_step_config.random_horizontal_flip - return (preprocessor.random_horizontal_flip, - { - 'keypoint_flip_permutation': tuple( - config.keypoint_flip_permutation), - }) - - if step_type == 'random_vertical_flip': - config = preprocessor_step_config.random_vertical_flip - return (preprocessor.random_vertical_flip, - { - 'keypoint_flip_permutation': tuple( - config.keypoint_flip_permutation), - }) - - if step_type == 'random_rotation90': - return (preprocessor.random_rotation90, {}) - - if step_type == 'random_crop_image': - config = preprocessor_step_config.random_crop_image - return (preprocessor.random_crop_image, - { - 'min_object_covered': config.min_object_covered, - 'aspect_ratio_range': (config.min_aspect_ratio, - config.max_aspect_ratio), - 'area_range': (config.min_area, config.max_area), - 'overlap_thresh': config.overlap_thresh, - 'random_coef': config.random_coef, - }) - - if step_type == 'random_pad_image': - config = preprocessor_step_config.random_pad_image - min_image_size = None - if (config.HasField('min_image_height') != - config.HasField('min_image_width')): - raise ValueError('min_image_height and min_image_width should be either ' - 'both set or both unset.') - if config.HasField('min_image_height'): - min_image_size = (config.min_image_height, config.min_image_width) - - max_image_size = None - if (config.HasField('max_image_height') != - config.HasField('max_image_width')): - raise ValueError('max_image_height and max_image_width should be either ' - 'both set or both unset.') - if config.HasField('max_image_height'): - max_image_size = (config.max_image_height, config.max_image_width) - - pad_color = config.pad_color - if pad_color and len(pad_color) != 3: - raise ValueError('pad_color should have 3 elements (RGB) if set!') - if not pad_color: - pad_color = None - return (preprocessor.random_pad_image, - { - 'min_image_size': min_image_size, - 'max_image_size': max_image_size, - 'pad_color': pad_color, - }) - - if step_type == 'random_crop_pad_image': - config = preprocessor_step_config.random_crop_pad_image - min_padded_size_ratio = config.min_padded_size_ratio - if min_padded_size_ratio and len(min_padded_size_ratio) != 2: - raise ValueError('min_padded_size_ratio should have 2 elements if set!') - max_padded_size_ratio = config.max_padded_size_ratio - if max_padded_size_ratio and len(max_padded_size_ratio) != 2: - raise ValueError('max_padded_size_ratio should have 2 elements if set!') - pad_color = config.pad_color - if pad_color and len(pad_color) != 3: - raise ValueError('pad_color should have 3 elements if set!') - kwargs = { - 'min_object_covered': config.min_object_covered, - 'aspect_ratio_range': (config.min_aspect_ratio, - config.max_aspect_ratio), - 'area_range': (config.min_area, config.max_area), - 'overlap_thresh': config.overlap_thresh, - 'random_coef': config.random_coef, - } - if min_padded_size_ratio: - kwargs['min_padded_size_ratio'] = tuple(min_padded_size_ratio) - if max_padded_size_ratio: - kwargs['max_padded_size_ratio'] = tuple(max_padded_size_ratio) - if pad_color: - kwargs['pad_color'] = tuple(pad_color) - return (preprocessor.random_crop_pad_image, kwargs) - - if step_type == 'random_resize_method': - config = preprocessor_step_config.random_resize_method - return (preprocessor.random_resize_method, - { - 'target_size': [config.target_height, config.target_width], - }) - - if step_type == 'resize_image': - config = preprocessor_step_config.resize_image - method = RESIZE_METHOD_MAP[config.method] - return (preprocessor.resize_image, - { - 'new_height': config.new_height, - 'new_width': config.new_width, - 'method': method - }) - - if step_type == 'ssd_random_crop': - config = preprocessor_step_config.ssd_random_crop - if config.operations: - min_object_covered = [op.min_object_covered for op in config.operations] - aspect_ratio_range = [(op.min_aspect_ratio, op.max_aspect_ratio) - for op in config.operations] - area_range = [(op.min_area, op.max_area) for op in config.operations] - overlap_thresh = [op.overlap_thresh for op in config.operations] - random_coef = [op.random_coef for op in config.operations] - return (preprocessor.ssd_random_crop, - { - 'min_object_covered': min_object_covered, - 'aspect_ratio_range': aspect_ratio_range, - 'area_range': area_range, - 'overlap_thresh': overlap_thresh, - 'random_coef': random_coef, - }) - return (preprocessor.ssd_random_crop, {}) - - if step_type == 'ssd_random_crop_pad': - config = preprocessor_step_config.ssd_random_crop_pad - if config.operations: - min_object_covered = [op.min_object_covered for op in config.operations] - aspect_ratio_range = [(op.min_aspect_ratio, op.max_aspect_ratio) - for op in config.operations] - area_range = [(op.min_area, op.max_area) for op in config.operations] - overlap_thresh = [op.overlap_thresh for op in config.operations] - random_coef = [op.random_coef for op in config.operations] - min_padded_size_ratio = [tuple(op.min_padded_size_ratio) - for op in config.operations] - max_padded_size_ratio = [tuple(op.max_padded_size_ratio) - for op in config.operations] - pad_color = [(op.pad_color_r, op.pad_color_g, op.pad_color_b) - for op in config.operations] - return (preprocessor.ssd_random_crop_pad, - { - 'min_object_covered': min_object_covered, - 'aspect_ratio_range': aspect_ratio_range, - 'area_range': area_range, - 'overlap_thresh': overlap_thresh, - 'random_coef': random_coef, - 'min_padded_size_ratio': min_padded_size_ratio, - 'max_padded_size_ratio': max_padded_size_ratio, - 'pad_color': pad_color, - }) - return (preprocessor.ssd_random_crop_pad, {}) - - if step_type == 'ssd_random_crop_fixed_aspect_ratio': - config = preprocessor_step_config.ssd_random_crop_fixed_aspect_ratio - if config.operations: - min_object_covered = [op.min_object_covered for op in config.operations] - area_range = [(op.min_area, op.max_area) for op in config.operations] - overlap_thresh = [op.overlap_thresh for op in config.operations] - random_coef = [op.random_coef for op in config.operations] - return (preprocessor.ssd_random_crop_fixed_aspect_ratio, - { - 'min_object_covered': min_object_covered, - 'aspect_ratio': config.aspect_ratio, - 'area_range': area_range, - 'overlap_thresh': overlap_thresh, - 'random_coef': random_coef, - }) - return (preprocessor.ssd_random_crop_fixed_aspect_ratio, {}) - - if step_type == 'ssd_random_crop_pad_fixed_aspect_ratio': - config = preprocessor_step_config.ssd_random_crop_pad_fixed_aspect_ratio - kwargs = {} - aspect_ratio = config.aspect_ratio - if aspect_ratio: - kwargs['aspect_ratio'] = aspect_ratio - min_padded_size_ratio = config.min_padded_size_ratio - if min_padded_size_ratio: - if len(min_padded_size_ratio) != 2: - raise ValueError('min_padded_size_ratio should have 2 elements if set!') - kwargs['min_padded_size_ratio'] = tuple(min_padded_size_ratio) - max_padded_size_ratio = config.max_padded_size_ratio - if max_padded_size_ratio: - if len(max_padded_size_ratio) != 2: - raise ValueError('max_padded_size_ratio should have 2 elements if set!') - kwargs['max_padded_size_ratio'] = tuple(max_padded_size_ratio) - if config.operations: - kwargs['min_object_covered'] = [op.min_object_covered - for op in config.operations] - kwargs['aspect_ratio_range'] = [(op.min_aspect_ratio, op.max_aspect_ratio) - for op in config.operations] - kwargs['area_range'] = [(op.min_area, op.max_area) - for op in config.operations] - kwargs['overlap_thresh'] = [op.overlap_thresh for op in config.operations] - kwargs['random_coef'] = [op.random_coef for op in config.operations] - return (preprocessor.ssd_random_crop_pad_fixed_aspect_ratio, kwargs) - - raise ValueError('Unknown preprocessing step.') diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder_test.py deleted file mode 100644 index 9e5d8de8e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder_test.py +++ /dev/null @@ -1,566 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for preprocessor_builder.""" - -import tensorflow as tf - -from google.protobuf import text_format - -from object_detection.builders import preprocessor_builder -from object_detection.core import preprocessor -from object_detection.protos import preprocessor_pb2 - - -class PreprocessorBuilderTest(tf.test.TestCase): - - def assert_dictionary_close(self, dict1, dict2): - """Helper to check if two dicts with floatst or integers are close.""" - self.assertEqual(sorted(dict1.keys()), sorted(dict2.keys())) - for key in dict1: - value = dict1[key] - if isinstance(value, float): - self.assertAlmostEqual(value, dict2[key]) - else: - self.assertEqual(value, dict2[key]) - - def test_build_normalize_image(self): - preprocessor_text_proto = """ - normalize_image { - original_minval: 0.0 - original_maxval: 255.0 - target_minval: -1.0 - target_maxval: 1.0 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.normalize_image) - self.assertEqual(args, { - 'original_minval': 0.0, - 'original_maxval': 255.0, - 'target_minval': -1.0, - 'target_maxval': 1.0, - }) - - def test_build_random_horizontal_flip(self): - preprocessor_text_proto = """ - random_horizontal_flip { - keypoint_flip_permutation: 1 - keypoint_flip_permutation: 0 - keypoint_flip_permutation: 2 - keypoint_flip_permutation: 3 - keypoint_flip_permutation: 5 - keypoint_flip_permutation: 4 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_horizontal_flip) - self.assertEqual(args, {'keypoint_flip_permutation': (1, 0, 2, 3, 5, 4)}) - - def test_build_random_vertical_flip(self): - preprocessor_text_proto = """ - random_vertical_flip { - keypoint_flip_permutation: 1 - keypoint_flip_permutation: 0 - keypoint_flip_permutation: 2 - keypoint_flip_permutation: 3 - keypoint_flip_permutation: 5 - keypoint_flip_permutation: 4 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_vertical_flip) - self.assertEqual(args, {'keypoint_flip_permutation': (1, 0, 2, 3, 5, 4)}) - - def test_build_random_rotation90(self): - preprocessor_text_proto = """ - random_rotation90 {} - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_rotation90) - self.assertEqual(args, {}) - - def test_build_random_pixel_value_scale(self): - preprocessor_text_proto = """ - random_pixel_value_scale { - minval: 0.8 - maxval: 1.2 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_pixel_value_scale) - self.assert_dictionary_close(args, {'minval': 0.8, 'maxval': 1.2}) - - def test_build_random_image_scale(self): - preprocessor_text_proto = """ - random_image_scale { - min_scale_ratio: 0.8 - max_scale_ratio: 2.2 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_image_scale) - self.assert_dictionary_close(args, {'min_scale_ratio': 0.8, - 'max_scale_ratio': 2.2}) - - def test_build_random_rgb_to_gray(self): - preprocessor_text_proto = """ - random_rgb_to_gray { - probability: 0.8 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_rgb_to_gray) - self.assert_dictionary_close(args, {'probability': 0.8}) - - def test_build_random_adjust_brightness(self): - preprocessor_text_proto = """ - random_adjust_brightness { - max_delta: 0.2 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_adjust_brightness) - self.assert_dictionary_close(args, {'max_delta': 0.2}) - - def test_build_random_adjust_contrast(self): - preprocessor_text_proto = """ - random_adjust_contrast { - min_delta: 0.7 - max_delta: 1.1 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_adjust_contrast) - self.assert_dictionary_close(args, {'min_delta': 0.7, 'max_delta': 1.1}) - - def test_build_random_adjust_hue(self): - preprocessor_text_proto = """ - random_adjust_hue { - max_delta: 0.01 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_adjust_hue) - self.assert_dictionary_close(args, {'max_delta': 0.01}) - - def test_build_random_adjust_saturation(self): - preprocessor_text_proto = """ - random_adjust_saturation { - min_delta: 0.75 - max_delta: 1.15 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_adjust_saturation) - self.assert_dictionary_close(args, {'min_delta': 0.75, 'max_delta': 1.15}) - - def test_build_random_distort_color(self): - preprocessor_text_proto = """ - random_distort_color { - color_ordering: 1 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_distort_color) - self.assertEqual(args, {'color_ordering': 1}) - - def test_build_random_jitter_boxes(self): - preprocessor_text_proto = """ - random_jitter_boxes { - ratio: 0.1 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_jitter_boxes) - self.assert_dictionary_close(args, {'ratio': 0.1}) - - def test_build_random_crop_image(self): - preprocessor_text_proto = """ - random_crop_image { - min_object_covered: 0.75 - min_aspect_ratio: 0.75 - max_aspect_ratio: 1.5 - min_area: 0.25 - max_area: 0.875 - overlap_thresh: 0.5 - random_coef: 0.125 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_crop_image) - self.assertEqual(args, { - 'min_object_covered': 0.75, - 'aspect_ratio_range': (0.75, 1.5), - 'area_range': (0.25, 0.875), - 'overlap_thresh': 0.5, - 'random_coef': 0.125, - }) - - def test_build_random_pad_image(self): - preprocessor_text_proto = """ - random_pad_image { - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_pad_image) - self.assertEqual(args, { - 'min_image_size': None, - 'max_image_size': None, - 'pad_color': None, - }) - - def test_build_random_crop_pad_image(self): - preprocessor_text_proto = """ - random_crop_pad_image { - min_object_covered: 0.75 - min_aspect_ratio: 0.75 - max_aspect_ratio: 1.5 - min_area: 0.25 - max_area: 0.875 - overlap_thresh: 0.5 - random_coef: 0.125 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_crop_pad_image) - self.assertEqual(args, { - 'min_object_covered': 0.75, - 'aspect_ratio_range': (0.75, 1.5), - 'area_range': (0.25, 0.875), - 'overlap_thresh': 0.5, - 'random_coef': 0.125, - }) - - def test_build_random_crop_pad_image_with_optional_parameters(self): - preprocessor_text_proto = """ - random_crop_pad_image { - min_object_covered: 0.75 - min_aspect_ratio: 0.75 - max_aspect_ratio: 1.5 - min_area: 0.25 - max_area: 0.875 - overlap_thresh: 0.5 - random_coef: 0.125 - min_padded_size_ratio: 0.5 - min_padded_size_ratio: 0.75 - max_padded_size_ratio: 0.5 - max_padded_size_ratio: 0.75 - pad_color: 0.5 - pad_color: 0.5 - pad_color: 1.0 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_crop_pad_image) - self.assertEqual(args, { - 'min_object_covered': 0.75, - 'aspect_ratio_range': (0.75, 1.5), - 'area_range': (0.25, 0.875), - 'overlap_thresh': 0.5, - 'random_coef': 0.125, - 'min_padded_size_ratio': (0.5, 0.75), - 'max_padded_size_ratio': (0.5, 0.75), - 'pad_color': (0.5, 0.5, 1.0) - }) - - def test_build_random_crop_to_aspect_ratio(self): - preprocessor_text_proto = """ - random_crop_to_aspect_ratio { - aspect_ratio: 0.85 - overlap_thresh: 0.35 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_crop_to_aspect_ratio) - self.assert_dictionary_close(args, {'aspect_ratio': 0.85, - 'overlap_thresh': 0.35}) - - def test_build_random_black_patches(self): - preprocessor_text_proto = """ - random_black_patches { - max_black_patches: 20 - probability: 0.95 - size_to_image_ratio: 0.12 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_black_patches) - self.assert_dictionary_close(args, {'max_black_patches': 20, - 'probability': 0.95, - 'size_to_image_ratio': 0.12}) - - def test_build_random_resize_method(self): - preprocessor_text_proto = """ - random_resize_method { - target_height: 75 - target_width: 100 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.random_resize_method) - self.assert_dictionary_close(args, {'target_size': [75, 100]}) - - def test_build_scale_boxes_to_pixel_coordinates(self): - preprocessor_text_proto = """ - scale_boxes_to_pixel_coordinates {} - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.scale_boxes_to_pixel_coordinates) - self.assertEqual(args, {}) - - def test_build_resize_image(self): - preprocessor_text_proto = """ - resize_image { - new_height: 75 - new_width: 100 - method: BICUBIC - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.resize_image) - self.assertEqual(args, {'new_height': 75, - 'new_width': 100, - 'method': tf.image.ResizeMethod.BICUBIC}) - - def test_build_rgb_to_gray(self): - preprocessor_text_proto = """ - rgb_to_gray {} - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.rgb_to_gray) - self.assertEqual(args, {}) - - def test_build_subtract_channel_mean(self): - preprocessor_text_proto = """ - subtract_channel_mean { - means: [1.0, 2.0, 3.0] - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.subtract_channel_mean) - self.assertEqual(args, {'means': [1.0, 2.0, 3.0]}) - - def test_build_ssd_random_crop(self): - preprocessor_text_proto = """ - ssd_random_crop { - operations { - min_object_covered: 0.0 - min_aspect_ratio: 0.875 - max_aspect_ratio: 1.125 - min_area: 0.5 - max_area: 1.0 - overlap_thresh: 0.0 - random_coef: 0.375 - } - operations { - min_object_covered: 0.25 - min_aspect_ratio: 0.75 - max_aspect_ratio: 1.5 - min_area: 0.5 - max_area: 1.0 - overlap_thresh: 0.25 - random_coef: 0.375 - } - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.ssd_random_crop) - self.assertEqual(args, {'min_object_covered': [0.0, 0.25], - 'aspect_ratio_range': [(0.875, 1.125), (0.75, 1.5)], - 'area_range': [(0.5, 1.0), (0.5, 1.0)], - 'overlap_thresh': [0.0, 0.25], - 'random_coef': [0.375, 0.375]}) - - def test_build_ssd_random_crop_empty_operations(self): - preprocessor_text_proto = """ - ssd_random_crop { - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.ssd_random_crop) - self.assertEqual(args, {}) - - def test_build_ssd_random_crop_pad(self): - preprocessor_text_proto = """ - ssd_random_crop_pad { - operations { - min_object_covered: 0.0 - min_aspect_ratio: 0.875 - max_aspect_ratio: 1.125 - min_area: 0.5 - max_area: 1.0 - overlap_thresh: 0.0 - random_coef: 0.375 - min_padded_size_ratio: [1.0, 1.0] - max_padded_size_ratio: [2.0, 2.0] - pad_color_r: 0.5 - pad_color_g: 0.5 - pad_color_b: 0.5 - } - operations { - min_object_covered: 0.25 - min_aspect_ratio: 0.75 - max_aspect_ratio: 1.5 - min_area: 0.5 - max_area: 1.0 - overlap_thresh: 0.25 - random_coef: 0.375 - min_padded_size_ratio: [1.0, 1.0] - max_padded_size_ratio: [2.0, 2.0] - pad_color_r: 0.5 - pad_color_g: 0.5 - pad_color_b: 0.5 - } - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.ssd_random_crop_pad) - self.assertEqual(args, {'min_object_covered': [0.0, 0.25], - 'aspect_ratio_range': [(0.875, 1.125), (0.75, 1.5)], - 'area_range': [(0.5, 1.0), (0.5, 1.0)], - 'overlap_thresh': [0.0, 0.25], - 'random_coef': [0.375, 0.375], - 'min_padded_size_ratio': [(1.0, 1.0), (1.0, 1.0)], - 'max_padded_size_ratio': [(2.0, 2.0), (2.0, 2.0)], - 'pad_color': [(0.5, 0.5, 0.5), (0.5, 0.5, 0.5)]}) - - def test_build_ssd_random_crop_fixed_aspect_ratio(self): - preprocessor_text_proto = """ - ssd_random_crop_fixed_aspect_ratio { - operations { - min_object_covered: 0.0 - min_area: 0.5 - max_area: 1.0 - overlap_thresh: 0.0 - random_coef: 0.375 - } - operations { - min_object_covered: 0.25 - min_area: 0.5 - max_area: 1.0 - overlap_thresh: 0.25 - random_coef: 0.375 - } - aspect_ratio: 0.875 - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, preprocessor.ssd_random_crop_fixed_aspect_ratio) - self.assertEqual(args, {'min_object_covered': [0.0, 0.25], - 'aspect_ratio': 0.875, - 'area_range': [(0.5, 1.0), (0.5, 1.0)], - 'overlap_thresh': [0.0, 0.25], - 'random_coef': [0.375, 0.375]}) - - def test_build_ssd_random_crop_pad_fixed_aspect_ratio(self): - preprocessor_text_proto = """ - ssd_random_crop_pad_fixed_aspect_ratio { - operations { - min_object_covered: 0.0 - min_aspect_ratio: 0.875 - max_aspect_ratio: 1.125 - min_area: 0.5 - max_area: 1.0 - overlap_thresh: 0.0 - random_coef: 0.375 - } - operations { - min_object_covered: 0.25 - min_aspect_ratio: 0.75 - max_aspect_ratio: 1.5 - min_area: 0.5 - max_area: 1.0 - overlap_thresh: 0.25 - random_coef: 0.375 - } - aspect_ratio: 0.875 - min_padded_size_ratio: [1.0, 1.0] - max_padded_size_ratio: [2.0, 2.0] - } - """ - preprocessor_proto = preprocessor_pb2.PreprocessingStep() - text_format.Merge(preprocessor_text_proto, preprocessor_proto) - function, args = preprocessor_builder.build(preprocessor_proto) - self.assertEqual(function, - preprocessor.ssd_random_crop_pad_fixed_aspect_ratio) - self.assertEqual(args, {'min_object_covered': [0.0, 0.25], - 'aspect_ratio': 0.875, - 'aspect_ratio_range': [(0.875, 1.125), (0.75, 1.5)], - 'area_range': [(0.5, 1.0), (0.5, 1.0)], - 'overlap_thresh': [0.0, 0.25], - 'random_coef': [0.375, 0.375], - 'min_padded_size_ratio': (1.0, 1.0), - 'max_padded_size_ratio': (2.0, 2.0)}) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder.py deleted file mode 100644 index fa1d67175..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Builder for region similarity calculators.""" - -from object_detection.core import region_similarity_calculator -from object_detection.protos import region_similarity_calculator_pb2 - - -def build(region_similarity_calculator_config): - """Builds region similarity calculator based on the configuration. - - Builds one of [IouSimilarity, IoaSimilarity, NegSqDistSimilarity] objects. See - core/region_similarity_calculator.proto for details. - - Args: - region_similarity_calculator_config: RegionSimilarityCalculator - configuration proto. - - Returns: - region_similarity_calculator: RegionSimilarityCalculator object. - - Raises: - ValueError: On unknown region similarity calculator. - """ - - if not isinstance( - region_similarity_calculator_config, - region_similarity_calculator_pb2.RegionSimilarityCalculator): - raise ValueError( - 'region_similarity_calculator_config not of type ' - 'region_similarity_calculator_pb2.RegionsSimilarityCalculator') - - similarity_calculator = region_similarity_calculator_config.WhichOneof( - 'region_similarity') - if similarity_calculator == 'iou_similarity': - return region_similarity_calculator.IouSimilarity() - if similarity_calculator == 'ioa_similarity': - return region_similarity_calculator.IoaSimilarity() - if similarity_calculator == 'neg_sq_dist_similarity': - return region_similarity_calculator.NegSqDistSimilarity() - - raise ValueError('Unknown region similarity calculator.') - diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder_test.py deleted file mode 100644 index ca3a5512e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder_test.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for region_similarity_calculator_builder.""" - -import tensorflow as tf - -from google.protobuf import text_format -from object_detection.builders import region_similarity_calculator_builder -from object_detection.core import region_similarity_calculator -from object_detection.protos import region_similarity_calculator_pb2 as sim_calc_pb2 - - -class RegionSimilarityCalculatorBuilderTest(tf.test.TestCase): - - def testBuildIoaSimilarityCalculator(self): - similarity_calc_text_proto = """ - ioa_similarity { - } - """ - similarity_calc_proto = sim_calc_pb2.RegionSimilarityCalculator() - text_format.Merge(similarity_calc_text_proto, similarity_calc_proto) - similarity_calc = region_similarity_calculator_builder.build( - similarity_calc_proto) - self.assertTrue(isinstance(similarity_calc, - region_similarity_calculator.IoaSimilarity)) - - def testBuildIouSimilarityCalculator(self): - similarity_calc_text_proto = """ - iou_similarity { - } - """ - similarity_calc_proto = sim_calc_pb2.RegionSimilarityCalculator() - text_format.Merge(similarity_calc_text_proto, similarity_calc_proto) - similarity_calc = region_similarity_calculator_builder.build( - similarity_calc_proto) - self.assertTrue(isinstance(similarity_calc, - region_similarity_calculator.IouSimilarity)) - - def testBuildNegSqDistSimilarityCalculator(self): - similarity_calc_text_proto = """ - neg_sq_dist_similarity { - } - """ - similarity_calc_proto = sim_calc_pb2.RegionSimilarityCalculator() - text_format.Merge(similarity_calc_text_proto, similarity_calc_proto) - similarity_calc = region_similarity_calculator_builder.build( - similarity_calc_proto) - self.assertTrue(isinstance(similarity_calc, - region_similarity_calculator. - NegSqDistSimilarity)) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/__init__.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/__init__.py deleted file mode 100644 index 8b1378917..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/anchor_generator.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/anchor_generator.py deleted file mode 100644 index f2797ef77..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/anchor_generator.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Base anchor generator. - -The job of the anchor generator is to create (or load) a collection -of bounding boxes to be used as anchors. - -Generated anchors are assumed to match some convolutional grid or list of grid -shapes. For example, we might want to generate anchors matching an 8x8 -feature map and a 4x4 feature map. If we place 3 anchors per grid location -on the first feature map and 6 anchors per grid location on the second feature -map, then 3*8*8 + 6*4*4 = 288 anchors are generated in total. - -To support fully convolutional settings, feature map shapes are passed -dynamically at generation time. The number of anchors to place at each location -is static --- implementations of AnchorGenerator must always be able return -the number of anchors that it uses per location for each feature map. -""" -from abc import ABCMeta -from abc import abstractmethod - -import tensorflow as tf - - -class AnchorGenerator(object): - """Abstract base class for anchor generators.""" - __metaclass__ = ABCMeta - - @abstractmethod - def name_scope(self): - """Name scope. - - Must be defined by implementations. - - Returns: - a string representing the name scope of the anchor generation operation. - """ - pass - - @property - def check_num_anchors(self): - """Whether to dynamically check the number of anchors generated. - - Can be overridden by implementations that would like to disable this - behavior. - - Returns: - a boolean controlling whether the Generate function should dynamically - check the number of anchors generated against the mathematically - expected number of anchors. - """ - return True - - @abstractmethod - def num_anchors_per_location(self): - """Returns the number of anchors per spatial location. - - Returns: - a list of integers, one for each expected feature map to be passed to - the `generate` function. - """ - pass - - def generate(self, feature_map_shape_list, **params): - """Generates a collection of bounding boxes to be used as anchors. - - TODO(rathodv): remove **params from argument list and make stride and - offsets (for multiple_grid_anchor_generator) constructor arguments. - - Args: - feature_map_shape_list: list of (height, width) pairs in the format - [(height_0, width_0), (height_1, width_1), ...] that the generated - anchors must align with. Pairs can be provided as 1-dimensional - integer tensors of length 2 or simply as tuples of integers. - **params: parameters for anchor generation op - - Returns: - boxes_list: a list of BoxLists each holding anchor boxes corresponding to - the input feature map shapes. - - Raises: - ValueError: if the number of feature map shapes does not match the length - of NumAnchorsPerLocation. - """ - if self.check_num_anchors and ( - len(feature_map_shape_list) != len(self.num_anchors_per_location())): - raise ValueError('Number of feature maps is expected to equal the length ' - 'of `num_anchors_per_location`.') - with tf.name_scope(self.name_scope()): - anchors_list = self._generate(feature_map_shape_list, **params) - if self.check_num_anchors: - with tf.control_dependencies([ - self._assert_correct_number_of_anchors( - anchors_list, feature_map_shape_list)]): - for item in anchors_list: - item.set(tf.identity(item.get())) - return anchors_list - - @abstractmethod - def _generate(self, feature_map_shape_list, **params): - """To be overridden by implementations. - - Args: - feature_map_shape_list: list of (height, width) pairs in the format - [(height_0, width_0), (height_1, width_1), ...] that the generated - anchors must align with. - **params: parameters for anchor generation op - - Returns: - boxes_list: a list of BoxList, each holding a collection of N anchor - boxes. - """ - pass - - def _assert_correct_number_of_anchors(self, anchors_list, - feature_map_shape_list): - """Assert that correct number of anchors was generated. - - Args: - anchors_list: A list of box_list.BoxList object holding anchors generated. - feature_map_shape_list: list of (height, width) pairs in the format - [(height_0, width_0), (height_1, width_1), ...] that the generated - anchors must align with. - Returns: - Op that raises InvalidArgumentError if the number of anchors does not - match the number of expected anchors. - """ - expected_num_anchors = 0 - actual_num_anchors = 0 - for num_anchors_per_location, feature_map_shape, anchors in zip( - self.num_anchors_per_location(), feature_map_shape_list, anchors_list): - expected_num_anchors += (num_anchors_per_location - * feature_map_shape[0] - * feature_map_shape[1]) - actual_num_anchors += anchors.num_boxes() - return tf.assert_equal(expected_num_anchors, actual_num_anchors) - diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler.py deleted file mode 100644 index 7042c40ff..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Class to subsample minibatches by balancing positives and negatives. - -Subsamples minibatches based on a pre-specified positive fraction in range -[0,1]. The class presumes there are many more negatives than positive examples: -if the desired batch_size cannot be achieved with the pre-specified positive -fraction, it fills the rest with negative examples. If this is not sufficient -for obtaining the desired batch_size, it returns fewer examples. - -The main function to call is Subsample(self, indicator, labels). For convenience -one can also call SubsampleWeights(self, weights, labels) which is defined in -the minibatch_sampler base class. -""" - -import tensorflow as tf - -from object_detection.core import minibatch_sampler - - -class BalancedPositiveNegativeSampler(minibatch_sampler.MinibatchSampler): - """Subsamples minibatches to a desired balance of positives and negatives.""" - - def __init__(self, positive_fraction=0.5): - """Constructs a minibatch sampler. - - Args: - positive_fraction: desired fraction of positive examples (scalar in [0,1]) - in the batch. - - Raises: - ValueError: if positive_fraction < 0, or positive_fraction > 1 - """ - if positive_fraction < 0 or positive_fraction > 1: - raise ValueError('positive_fraction should be in range [0,1]. ' - 'Received: %s.' % positive_fraction) - self._positive_fraction = positive_fraction - - def subsample(self, indicator, batch_size, labels): - """Returns subsampled minibatch. - - Args: - indicator: boolean tensor of shape [N] whose True entries can be sampled. - batch_size: desired batch size. If None, keeps all positive samples and - randomly selects negative samples so that the positive sample fraction - matches self._positive_fraction. - labels: boolean tensor of shape [N] denoting positive(=True) and negative - (=False) examples. - - Returns: - is_sampled: boolean tensor of shape [N], True for entries which are - sampled. - - Raises: - ValueError: if labels and indicator are not 1D boolean tensors. - """ - if len(indicator.get_shape().as_list()) != 1: - raise ValueError('indicator must be 1 dimensional, got a tensor of ' - 'shape %s' % indicator.get_shape()) - if len(labels.get_shape().as_list()) != 1: - raise ValueError('labels must be 1 dimensional, got a tensor of ' - 'shape %s' % labels.get_shape()) - if labels.dtype != tf.bool: - raise ValueError('labels should be of type bool. Received: %s' % - labels.dtype) - if indicator.dtype != tf.bool: - raise ValueError('indicator should be of type bool. Received: %s' % - indicator.dtype) - - # Only sample from indicated samples - negative_idx = tf.logical_not(labels) - positive_idx = tf.logical_and(labels, indicator) - negative_idx = tf.logical_and(negative_idx, indicator) - - # Sample positive and negative samples separately - if batch_size is None: - max_num_pos = tf.reduce_sum(tf.to_int32(positive_idx)) - else: - max_num_pos = int(self._positive_fraction * batch_size) - sampled_pos_idx = self.subsample_indicator(positive_idx, max_num_pos) - num_sampled_pos = tf.reduce_sum(tf.cast(sampled_pos_idx, tf.int32)) - if batch_size is None: - negative_positive_ratio = ( - 1 - self._positive_fraction) / self._positive_fraction - max_num_neg = tf.to_int32( - negative_positive_ratio * tf.to_float(num_sampled_pos)) - else: - max_num_neg = batch_size - num_sampled_pos - sampled_neg_idx = self.subsample_indicator(negative_idx, max_num_neg) - - sampled_idx = tf.logical_or(sampled_pos_idx, sampled_neg_idx) - return sampled_idx diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler_test.py deleted file mode 100644 index e39de5342..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler_test.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.balanced_positive_negative_sampler.""" - -import numpy as np -import tensorflow as tf - -from object_detection.core import balanced_positive_negative_sampler -from object_detection.utils import test_case - - -class BalancedPositiveNegativeSamplerTest(test_case.TestCase): - - def test_subsample_all_examples(self): - numpy_labels = np.random.permutation(300) - indicator = tf.constant(np.ones(300) == 1) - numpy_labels = (numpy_labels - 200) > 0 - - labels = tf.constant(numpy_labels) - - sampler = (balanced_positive_negative_sampler. - BalancedPositiveNegativeSampler()) - is_sampled = sampler.subsample(indicator, 64, labels) - with self.test_session() as sess: - is_sampled = sess.run(is_sampled) - self.assertTrue(sum(is_sampled) == 64) - self.assertTrue(sum(np.logical_and(numpy_labels, is_sampled)) == 32) - self.assertTrue(sum(np.logical_and( - np.logical_not(numpy_labels), is_sampled)) == 32) - - def test_subsample_selection(self): - # Test random sampling when only some examples can be sampled: - # 100 samples, 20 positives, 10 positives cannot be sampled - numpy_labels = np.arange(100) - numpy_indicator = numpy_labels < 90 - indicator = tf.constant(numpy_indicator) - numpy_labels = (numpy_labels - 80) >= 0 - - labels = tf.constant(numpy_labels) - - sampler = (balanced_positive_negative_sampler. - BalancedPositiveNegativeSampler()) - is_sampled = sampler.subsample(indicator, 64, labels) - with self.test_session() as sess: - is_sampled = sess.run(is_sampled) - self.assertTrue(sum(is_sampled) == 64) - self.assertTrue(sum(np.logical_and(numpy_labels, is_sampled)) == 10) - self.assertTrue(sum(np.logical_and( - np.logical_not(numpy_labels), is_sampled)) == 54) - self.assertAllEqual(is_sampled, np.logical_and(is_sampled, - numpy_indicator)) - - def test_subsample_selection_no_batch_size(self): - # Test random sampling when only some examples can be sampled: - # 1000 samples, 6 positives (5 can be sampled). - numpy_labels = np.arange(1000) - numpy_indicator = numpy_labels < 999 - indicator = tf.constant(numpy_indicator) - numpy_labels = (numpy_labels - 994) >= 0 - - labels = tf.constant(numpy_labels) - - sampler = (balanced_positive_negative_sampler. - BalancedPositiveNegativeSampler(0.01)) - is_sampled = sampler.subsample(indicator, None, labels) - with self.test_session() as sess: - is_sampled = sess.run(is_sampled) - self.assertTrue(sum(is_sampled) == 500) - self.assertTrue(sum(np.logical_and(numpy_labels, is_sampled)) == 5) - self.assertTrue(sum(np.logical_and( - np.logical_not(numpy_labels), is_sampled)) == 495) - self.assertAllEqual(is_sampled, np.logical_and(is_sampled, - numpy_indicator)) - - def test_raises_error_with_incorrect_label_shape(self): - labels = tf.constant([[True, False, False]]) - indicator = tf.constant([True, False, True]) - sampler = (balanced_positive_negative_sampler. - BalancedPositiveNegativeSampler()) - with self.assertRaises(ValueError): - sampler.subsample(indicator, 64, labels) - - def test_raises_error_with_incorrect_indicator_shape(self): - labels = tf.constant([True, False, False]) - indicator = tf.constant([[True, False, True]]) - sampler = (balanced_positive_negative_sampler. - BalancedPositiveNegativeSampler()) - with self.assertRaises(ValueError): - sampler.subsample(indicator, 64, labels) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher.py deleted file mode 100644 index c5dfb7121..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Provides functions to batch a dictionary of input tensors.""" -import collections - -import tensorflow as tf - -from object_detection.core import prefetcher - -rt_shape_str = '_runtime_shapes' - - -class BatchQueue(object): - """BatchQueue class. - - This class creates a batch queue to asynchronously enqueue tensors_dict. - It also adds a FIFO prefetcher so that the batches are readily available - for the consumers. Dequeue ops for a BatchQueue object can be created via - the Dequeue method which evaluates to a batch of tensor_dict. - - Example input pipeline with batching: - ------------------------------------ - key, string_tensor = slim.parallel_reader.parallel_read(...) - tensor_dict = decoder.decode(string_tensor) - tensor_dict = preprocessor.preprocess(tensor_dict, ...) - batch_queue = batcher.BatchQueue(tensor_dict, - batch_size=32, - batch_queue_capacity=2000, - num_batch_queue_threads=8, - prefetch_queue_capacity=20) - tensor_dict = batch_queue.dequeue() - outputs = Model(tensor_dict) - ... - ----------------------------------- - - Notes: - ----- - This class batches tensors of unequal sizes by zero padding and unpadding - them after generating a batch. This can be computationally expensive when - batching tensors (such as images) that are of vastly different sizes. So it is - recommended that the shapes of such tensors be fully defined in tensor_dict - while other lightweight tensors such as bounding box corners and class labels - can be of varying sizes. Use either crop or resize operations to fully define - the shape of an image in tensor_dict. - - It is also recommended to perform any preprocessing operations on tensors - before passing to BatchQueue and subsequently calling the Dequeue method. - - Another caveat is that this class does not read the last batch if it is not - full. The current implementation makes it hard to support that use case. So, - for evaluation, when it is critical to run all the examples through your - network use the input pipeline example mentioned in core/prefetcher.py. - """ - - def __init__(self, tensor_dict, batch_size, batch_queue_capacity, - num_batch_queue_threads, prefetch_queue_capacity): - """Constructs a batch queue holding tensor_dict. - - Args: - tensor_dict: dictionary of tensors to batch. - batch_size: batch size. - batch_queue_capacity: max capacity of the queue from which the tensors are - batched. - num_batch_queue_threads: number of threads to use for batching. - prefetch_queue_capacity: max capacity of the queue used to prefetch - assembled batches. - """ - # Remember static shapes to set shapes of batched tensors. - static_shapes = collections.OrderedDict( - {key: tensor.get_shape() for key, tensor in tensor_dict.items()}) - # Remember runtime shapes to unpad tensors after batching. - runtime_shapes = collections.OrderedDict( - {(key + rt_shape_str): tf.shape(tensor) - for key, tensor in tensor_dict.items()}) - - all_tensors = tensor_dict - all_tensors.update(runtime_shapes) - batched_tensors = tf.train.batch( - all_tensors, - capacity=batch_queue_capacity, - batch_size=batch_size, - dynamic_pad=True, - num_threads=num_batch_queue_threads) - - self._queue = prefetcher.prefetch(batched_tensors, - prefetch_queue_capacity) - self._static_shapes = static_shapes - self._batch_size = batch_size - - def dequeue(self): - """Dequeues a batch of tensor_dict from the BatchQueue. - - TODO: use allow_smaller_final_batch to allow running over the whole eval set - - Returns: - A list of tensor_dicts of the requested batch_size. - """ - batched_tensors = self._queue.dequeue() - # Separate input tensors from tensors containing their runtime shapes. - tensors = {} - shapes = {} - for key, batched_tensor in batched_tensors.items(): - unbatched_tensor_list = tf.unstack(batched_tensor) - for i, unbatched_tensor in enumerate(unbatched_tensor_list): - if rt_shape_str in key: - shapes[(key[:-len(rt_shape_str)], i)] = unbatched_tensor - else: - tensors[(key, i)] = unbatched_tensor - - # Undo that padding using shapes and create a list of size `batch_size` that - # contains tensor dictionaries. - tensor_dict_list = [] - batch_size = self._batch_size - for batch_id in range(batch_size): - tensor_dict = {} - for key in self._static_shapes: - tensor_dict[key] = tf.slice(tensors[(key, batch_id)], - tf.zeros_like(shapes[(key, batch_id)]), - shapes[(key, batch_id)]) - tensor_dict[key].set_shape(self._static_shapes[key]) - tensor_dict_list.append(tensor_dict) - - return tensor_dict_list diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher_test.py deleted file mode 100644 index 61b4390b4..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher_test.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.batcher.""" - -import numpy as np -import tensorflow as tf - -from object_detection.core import batcher - -slim = tf.contrib.slim - - -class BatcherTest(tf.test.TestCase): - - def test_batch_and_unpad_2d_tensors_of_different_sizes_in_1st_dimension(self): - with self.test_session() as sess: - batch_size = 3 - num_batches = 2 - examples = tf.Variable(tf.constant(2, dtype=tf.int32)) - counter = examples.count_up_to(num_batches * batch_size + 2) - boxes = tf.tile( - tf.reshape(tf.range(4), [1, 4]), tf.stack([counter, tf.constant(1)])) - batch_queue = batcher.BatchQueue( - tensor_dict={'boxes': boxes}, - batch_size=batch_size, - batch_queue_capacity=100, - num_batch_queue_threads=1, - prefetch_queue_capacity=100) - batch = batch_queue.dequeue() - - for tensor_dict in batch: - for tensor in tensor_dict.values(): - self.assertAllEqual([None, 4], tensor.get_shape().as_list()) - - tf.initialize_all_variables().run() - with slim.queues.QueueRunners(sess): - i = 2 - for _ in range(num_batches): - batch_np = sess.run(batch) - for tensor_dict in batch_np: - for tensor in tensor_dict.values(): - self.assertAllEqual(tensor, np.tile(np.arange(4), (i, 1))) - i += 1 - with self.assertRaises(tf.errors.OutOfRangeError): - sess.run(batch) - - def test_batch_and_unpad_2d_tensors_of_different_sizes_in_all_dimensions( - self): - with self.test_session() as sess: - batch_size = 3 - num_batches = 2 - examples = tf.Variable(tf.constant(2, dtype=tf.int32)) - counter = examples.count_up_to(num_batches * batch_size + 2) - image = tf.reshape( - tf.range(counter * counter), tf.stack([counter, counter])) - batch_queue = batcher.BatchQueue( - tensor_dict={'image': image}, - batch_size=batch_size, - batch_queue_capacity=100, - num_batch_queue_threads=1, - prefetch_queue_capacity=100) - batch = batch_queue.dequeue() - - for tensor_dict in batch: - for tensor in tensor_dict.values(): - self.assertAllEqual([None, None], tensor.get_shape().as_list()) - - tf.initialize_all_variables().run() - with slim.queues.QueueRunners(sess): - i = 2 - for _ in range(num_batches): - batch_np = sess.run(batch) - for tensor_dict in batch_np: - for tensor in tensor_dict.values(): - self.assertAllEqual(tensor, np.arange(i * i).reshape((i, i))) - i += 1 - with self.assertRaises(tf.errors.OutOfRangeError): - sess.run(batch) - - def test_batch_and_unpad_2d_tensors_of_same_size_in_all_dimensions(self): - with self.test_session() as sess: - batch_size = 3 - num_batches = 2 - examples = tf.Variable(tf.constant(1, dtype=tf.int32)) - counter = examples.count_up_to(num_batches * batch_size + 1) - image = tf.reshape(tf.range(1, 13), [4, 3]) * counter - batch_queue = batcher.BatchQueue( - tensor_dict={'image': image}, - batch_size=batch_size, - batch_queue_capacity=100, - num_batch_queue_threads=1, - prefetch_queue_capacity=100) - batch = batch_queue.dequeue() - - for tensor_dict in batch: - for tensor in tensor_dict.values(): - self.assertAllEqual([4, 3], tensor.get_shape().as_list()) - - tf.initialize_all_variables().run() - with slim.queues.QueueRunners(sess): - i = 1 - for _ in range(num_batches): - batch_np = sess.run(batch) - for tensor_dict in batch_np: - for tensor in tensor_dict.values(): - self.assertAllEqual(tensor, np.arange(1, 13).reshape((4, 3)) * i) - i += 1 - with self.assertRaises(tf.errors.OutOfRangeError): - sess.run(batch) - - def test_batcher_when_batch_size_is_one(self): - with self.test_session() as sess: - batch_size = 1 - num_batches = 2 - examples = tf.Variable(tf.constant(2, dtype=tf.int32)) - counter = examples.count_up_to(num_batches * batch_size + 2) - image = tf.reshape( - tf.range(counter * counter), tf.stack([counter, counter])) - batch_queue = batcher.BatchQueue( - tensor_dict={'image': image}, - batch_size=batch_size, - batch_queue_capacity=100, - num_batch_queue_threads=1, - prefetch_queue_capacity=100) - batch = batch_queue.dequeue() - - for tensor_dict in batch: - for tensor in tensor_dict.values(): - self.assertAllEqual([None, None], tensor.get_shape().as_list()) - - tf.initialize_all_variables().run() - with slim.queues.QueueRunners(sess): - i = 2 - for _ in range(num_batches): - batch_np = sess.run(batch) - for tensor_dict in batch_np: - for tensor in tensor_dict.values(): - self.assertAllEqual(tensor, np.arange(i * i).reshape((i, i))) - i += 1 - with self.assertRaises(tf.errors.OutOfRangeError): - sess.run(batch) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_coder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_coder.py deleted file mode 100644 index f20ac956d..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_coder.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Base box coder. - -Box coders convert between coordinate frames, namely image-centric -(with (0,0) on the top left of image) and anchor-centric (with (0,0) being -defined by a specific anchor). - -Users of a BoxCoder can call two methods: - encode: which encodes a box with respect to a given anchor - (or rather, a tensor of boxes wrt a corresponding tensor of anchors) and - decode: which inverts this encoding with a decode operation. -In both cases, the arguments are assumed to be in 1-1 correspondence already; -it is not the job of a BoxCoder to perform matching. -""" -from abc import ABCMeta -from abc import abstractmethod -from abc import abstractproperty - -import tensorflow as tf - - -# Box coder types. -FASTER_RCNN = 'faster_rcnn' -KEYPOINT = 'keypoint' -MEAN_STDDEV = 'mean_stddev' -SQUARE = 'square' - - -class BoxCoder(object): - """Abstract base class for box coder.""" - __metaclass__ = ABCMeta - - @abstractproperty - def code_size(self): - """Return the size of each code. - - This number is a constant and should agree with the output of the `encode` - op (e.g. if rel_codes is the output of self.encode(...), then it should have - shape [N, code_size()]). This abstractproperty should be overridden by - implementations. - - Returns: - an integer constant - """ - pass - - def encode(self, boxes, anchors): - """Encode a box list relative to an anchor collection. - - Args: - boxes: BoxList holding N boxes to be encoded - anchors: BoxList of N anchors - - Returns: - a tensor representing N relative-encoded boxes - """ - with tf.name_scope('Encode'): - return self._encode(boxes, anchors) - - def decode(self, rel_codes, anchors): - """Decode boxes that are encoded relative to an anchor collection. - - Args: - rel_codes: a tensor representing N relative-encoded boxes - anchors: BoxList of anchors - - Returns: - boxlist: BoxList holding N boxes encoded in the ordinary way (i.e., - with corners y_min, x_min, y_max, x_max) - """ - with tf.name_scope('Decode'): - return self._decode(rel_codes, anchors) - - @abstractmethod - def _encode(self, boxes, anchors): - """Method to be overriden by implementations. - - Args: - boxes: BoxList holding N boxes to be encoded - anchors: BoxList of N anchors - - Returns: - a tensor representing N relative-encoded boxes - """ - pass - - @abstractmethod - def _decode(self, rel_codes, anchors): - """Method to be overriden by implementations. - - Args: - rel_codes: a tensor representing N relative-encoded boxes - anchors: BoxList of anchors - - Returns: - boxlist: BoxList holding N boxes encoded in the ordinary way (i.e., - with corners y_min, x_min, y_max, x_max) - """ - pass - - -def batch_decode(encoded_boxes, box_coder, anchors): - """Decode a batch of encoded boxes. - - This op takes a batch of encoded bounding boxes and transforms - them to a batch of bounding boxes specified by their corners in - the order of [y_min, x_min, y_max, x_max]. - - Args: - encoded_boxes: a float32 tensor of shape [batch_size, num_anchors, - code_size] representing the location of the objects. - box_coder: a BoxCoder object. - anchors: a BoxList of anchors used to encode `encoded_boxes`. - - Returns: - decoded_boxes: a float32 tensor of shape [batch_size, num_anchors, - coder_size] representing the corners of the objects in the order - of [y_min, x_min, y_max, x_max]. - - Raises: - ValueError: if batch sizes of the inputs are inconsistent, or if - the number of anchors inferred from encoded_boxes and anchors are - inconsistent. - """ - encoded_boxes.get_shape().assert_has_rank(3) - if encoded_boxes.get_shape()[1].value != anchors.num_boxes_static(): - raise ValueError('The number of anchors inferred from encoded_boxes' - ' and anchors are inconsistent: shape[1] of encoded_boxes' - ' %s should be equal to the number of anchors: %s.' % - (encoded_boxes.get_shape()[1].value, - anchors.num_boxes_static())) - - decoded_boxes = tf.stack([ - box_coder.decode(boxes, anchors).get() - for boxes in tf.unstack(encoded_boxes) - ]) - return decoded_boxes diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_coder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_coder_test.py deleted file mode 100644 index c087a3252..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_coder_test.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.box_coder.""" - -import tensorflow as tf - -from object_detection.core import box_coder -from object_detection.core import box_list - - -class MockBoxCoder(box_coder.BoxCoder): - """Test BoxCoder that encodes/decodes using the multiply-by-two function.""" - - def code_size(self): - return 4 - - def _encode(self, boxes, anchors): - return 2.0 * boxes.get() - - def _decode(self, rel_codes, anchors): - return box_list.BoxList(rel_codes / 2.0) - - -class BoxCoderTest(tf.test.TestCase): - - def test_batch_decode(self): - mock_anchor_corners = tf.constant( - [[0, 0.1, 0.2, 0.3], [0.2, 0.4, 0.4, 0.6]], tf.float32) - mock_anchors = box_list.BoxList(mock_anchor_corners) - mock_box_coder = MockBoxCoder() - - expected_boxes = [[[0.0, 0.1, 0.5, 0.6], [0.5, 0.6, 0.7, 0.8]], - [[0.1, 0.2, 0.3, 0.4], [0.7, 0.8, 0.9, 1.0]]] - - encoded_boxes_list = [mock_box_coder.encode( - box_list.BoxList(tf.constant(boxes)), mock_anchors) - for boxes in expected_boxes] - encoded_boxes = tf.stack(encoded_boxes_list) - decoded_boxes = box_coder.batch_decode( - encoded_boxes, mock_box_coder, mock_anchors) - - with self.test_session() as sess: - decoded_boxes_result = sess.run(decoded_boxes) - self.assertAllClose(expected_boxes, decoded_boxes_result) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list.py deleted file mode 100644 index c0196f053..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list.py +++ /dev/null @@ -1,207 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Bounding Box List definition. - -BoxList represents a list of bounding boxes as tensorflow -tensors, where each bounding box is represented as a row of 4 numbers, -[y_min, x_min, y_max, x_max]. It is assumed that all bounding boxes -within a given list correspond to a single image. See also -box_list_ops.py for common box related operations (such as area, iou, etc). - -Optionally, users can add additional related fields (such as weights). -We assume the following things to be true about fields: -* they correspond to boxes in the box_list along the 0th dimension -* they have inferrable rank at graph construction time -* all dimensions except for possibly the 0th can be inferred - (i.e., not None) at graph construction time. - -Some other notes: - * Following tensorflow conventions, we use height, width ordering, - and correspondingly, y,x (or ymin, xmin, ymax, xmax) ordering - * Tensors are always provided as (flat) [N, 4] tensors. -""" - -import tensorflow as tf - - -class BoxList(object): - """Box collection.""" - - def __init__(self, boxes): - """Constructs box collection. - - Args: - boxes: a tensor of shape [N, 4] representing box corners - - Raises: - ValueError: if invalid dimensions for bbox data or if bbox data is not in - float32 format. - """ - if len(boxes.get_shape()) != 2 or boxes.get_shape()[-1] != 4: - raise ValueError('Invalid dimensions for box data.') - if boxes.dtype != tf.float32: - raise ValueError('Invalid tensor type: should be tf.float32') - self.data = {'boxes': boxes} - - def num_boxes(self): - """Returns number of boxes held in collection. - - Returns: - a tensor representing the number of boxes held in the collection. - """ - return tf.shape(self.data['boxes'])[0] - - def num_boxes_static(self): - """Returns number of boxes held in collection. - - This number is inferred at graph construction time rather than run-time. - - Returns: - Number of boxes held in collection (integer) or None if this is not - inferrable at graph construction time. - """ - return self.data['boxes'].get_shape()[0].value - - def get_all_fields(self): - """Returns all fields.""" - return self.data.keys() - - def get_extra_fields(self): - """Returns all non-box fields (i.e., everything not named 'boxes').""" - return [k for k in self.data.keys() if k != 'boxes'] - - def add_field(self, field, field_data): - """Add field to box list. - - This method can be used to add related box data such as - weights/labels, etc. - - Args: - field: a string key to access the data via `get` - field_data: a tensor containing the data to store in the BoxList - """ - self.data[field] = field_data - - def has_field(self, field): - return field in self.data - - def get(self): - """Convenience function for accessing box coordinates. - - Returns: - a tensor with shape [N, 4] representing box coordinates. - """ - return self.get_field('boxes') - - def set(self, boxes): - """Convenience function for setting box coordinates. - - Args: - boxes: a tensor of shape [N, 4] representing box corners - - Raises: - ValueError: if invalid dimensions for bbox data - """ - if len(boxes.get_shape()) != 2 or boxes.get_shape()[-1] != 4: - raise ValueError('Invalid dimensions for box data.') - self.data['boxes'] = boxes - - def get_field(self, field): - """Accesses a box collection and associated fields. - - This function returns specified field with object; if no field is specified, - it returns the box coordinates. - - Args: - field: this optional string parameter can be used to specify - a related field to be accessed. - - Returns: - a tensor representing the box collection or an associated field. - - Raises: - ValueError: if invalid field - """ - if not self.has_field(field): - raise ValueError('field ' + str(field) + ' does not exist') - return self.data[field] - - def set_field(self, field, value): - """Sets the value of a field. - - Updates the field of a box_list with a given value. - - Args: - field: (string) name of the field to set value. - value: the value to assign to the field. - - Raises: - ValueError: if the box_list does not have specified field. - """ - if not self.has_field(field): - raise ValueError('field %s does not exist' % field) - self.data[field] = value - - def get_center_coordinates_and_sizes(self, scope=None): - """Computes the center coordinates, height and width of the boxes. - - Args: - scope: name scope of the function. - - Returns: - a list of 4 1-D tensors [ycenter, xcenter, height, width]. - """ - with tf.name_scope(scope, 'get_center_coordinates_and_sizes'): - box_corners = self.get() - ymin, xmin, ymax, xmax = tf.unstack(tf.transpose(box_corners)) - width = xmax - xmin - height = ymax - ymin - ycenter = ymin + height / 2. - xcenter = xmin + width / 2. - return [ycenter, xcenter, height, width] - - def transpose_coordinates(self, scope=None): - """Transpose the coordinate representation in a boxlist. - - Args: - scope: name scope of the function. - """ - with tf.name_scope(scope, 'transpose_coordinates'): - y_min, x_min, y_max, x_max = tf.split( - value=self.get(), num_or_size_splits=4, axis=1) - self.set(tf.concat([x_min, y_min, x_max, y_max], 1)) - - def as_tensor_dict(self, fields=None): - """Retrieves specified fields as a dictionary of tensors. - - Args: - fields: (optional) list of fields to return in the dictionary. - If None (default), all fields are returned. - - Returns: - tensor_dict: A dictionary of tensors specified by fields. - - Raises: - ValueError: if specified field is not contained in boxlist. - """ - tensor_dict = {} - if fields is None: - fields = self.get_all_fields() - for field in fields: - if not self.has_field(field): - raise ValueError('boxlist must contain all specified fields') - tensor_dict[field] = self.get_field(field) - return tensor_dict diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_ops.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_ops.py deleted file mode 100644 index a755ef68e..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_ops.py +++ /dev/null @@ -1,1061 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Bounding Box List operations. - -Example box operations that are supported: - * areas: compute bounding box areas - * iou: pairwise intersection-over-union scores - * sq_dist: pairwise distances between bounding boxes - -Whenever box_list_ops functions output a BoxList, the fields of the incoming -BoxList are retained unless documented otherwise. -""" -import tensorflow as tf - -from object_detection.core import box_list -from object_detection.utils import shape_utils - - -class SortOrder(object): - """Enum class for sort order. - - Attributes: - ascend: ascend order. - descend: descend order. - """ - ascend = 1 - descend = 2 - - -def area(boxlist, scope=None): - """Computes area of boxes. - - Args: - boxlist: BoxList holding N boxes - scope: name scope. - - Returns: - a tensor with shape [N] representing box areas. - """ - with tf.name_scope(scope, 'Area'): - y_min, x_min, y_max, x_max = tf.split( - value=boxlist.get(), num_or_size_splits=4, axis=1) - return tf.squeeze((y_max - y_min) * (x_max - x_min), [1]) - - -def height_width(boxlist, scope=None): - """Computes height and width of boxes in boxlist. - - Args: - boxlist: BoxList holding N boxes - scope: name scope. - - Returns: - Height: A tensor with shape [N] representing box heights. - Width: A tensor with shape [N] representing box widths. - """ - with tf.name_scope(scope, 'HeightWidth'): - y_min, x_min, y_max, x_max = tf.split( - value=boxlist.get(), num_or_size_splits=4, axis=1) - return tf.squeeze(y_max - y_min, [1]), tf.squeeze(x_max - x_min, [1]) - - -def scale(boxlist, y_scale, x_scale, scope=None): - """scale box coordinates in x and y dimensions. - - Args: - boxlist: BoxList holding N boxes - y_scale: (float) scalar tensor - x_scale: (float) scalar tensor - scope: name scope. - - Returns: - boxlist: BoxList holding N boxes - """ - with tf.name_scope(scope, 'Scale'): - y_scale = tf.cast(y_scale, tf.float32) - x_scale = tf.cast(x_scale, tf.float32) - y_min, x_min, y_max, x_max = tf.split( - value=boxlist.get(), num_or_size_splits=4, axis=1) - y_min = y_scale * y_min - y_max = y_scale * y_max - x_min = x_scale * x_min - x_max = x_scale * x_max - scaled_boxlist = box_list.BoxList( - tf.concat([y_min, x_min, y_max, x_max], 1)) - return _copy_extra_fields(scaled_boxlist, boxlist) - - -def clip_to_window(boxlist, window, filter_nonoverlapping=True, scope=None): - """Clip bounding boxes to a window. - - This op clips any input bounding boxes (represented by bounding box - corners) to a window, optionally filtering out boxes that do not - overlap at all with the window. - - Args: - boxlist: BoxList holding M_in boxes - window: a tensor of shape [4] representing the [y_min, x_min, y_max, x_max] - window to which the op should clip boxes. - filter_nonoverlapping: whether to filter out boxes that do not overlap at - all with the window. - scope: name scope. - - Returns: - a BoxList holding M_out boxes where M_out <= M_in - """ - with tf.name_scope(scope, 'ClipToWindow'): - y_min, x_min, y_max, x_max = tf.split( - value=boxlist.get(), num_or_size_splits=4, axis=1) - win_y_min, win_x_min, win_y_max, win_x_max = tf.unstack(window) - y_min_clipped = tf.maximum(tf.minimum(y_min, win_y_max), win_y_min) - y_max_clipped = tf.maximum(tf.minimum(y_max, win_y_max), win_y_min) - x_min_clipped = tf.maximum(tf.minimum(x_min, win_x_max), win_x_min) - x_max_clipped = tf.maximum(tf.minimum(x_max, win_x_max), win_x_min) - clipped = box_list.BoxList( - tf.concat([y_min_clipped, x_min_clipped, y_max_clipped, x_max_clipped], - 1)) - clipped = _copy_extra_fields(clipped, boxlist) - if filter_nonoverlapping: - areas = area(clipped) - nonzero_area_indices = tf.cast( - tf.reshape(tf.where(tf.greater(areas, 0.0)), [-1]), tf.int32) - clipped = gather(clipped, nonzero_area_indices) - return clipped - - -def prune_outside_window(boxlist, window, scope=None): - """Prunes bounding boxes that fall outside a given window. - - This function prunes bounding boxes that even partially fall outside the given - window. See also clip_to_window which only prunes bounding boxes that fall - completely outside the window, and clips any bounding boxes that partially - overflow. - - Args: - boxlist: a BoxList holding M_in boxes. - window: a float tensor of shape [4] representing [ymin, xmin, ymax, xmax] - of the window - scope: name scope. - - Returns: - pruned_corners: a tensor with shape [M_out, 4] where M_out <= M_in - valid_indices: a tensor with shape [M_out] indexing the valid bounding boxes - in the input tensor. - """ - with tf.name_scope(scope, 'PruneOutsideWindow'): - y_min, x_min, y_max, x_max = tf.split( - value=boxlist.get(), num_or_size_splits=4, axis=1) - win_y_min, win_x_min, win_y_max, win_x_max = tf.unstack(window) - coordinate_violations = tf.concat([ - tf.less(y_min, win_y_min), tf.less(x_min, win_x_min), - tf.greater(y_max, win_y_max), tf.greater(x_max, win_x_max) - ], 1) - valid_indices = tf.reshape( - tf.where(tf.logical_not(tf.reduce_any(coordinate_violations, 1))), [-1]) - return gather(boxlist, valid_indices), valid_indices - - -def prune_completely_outside_window(boxlist, window, scope=None): - """Prunes bounding boxes that fall completely outside of the given window. - - The function clip_to_window prunes bounding boxes that fall - completely outside the window, but also clips any bounding boxes that - partially overflow. This function does not clip partially overflowing boxes. - - Args: - boxlist: a BoxList holding M_in boxes. - window: a float tensor of shape [4] representing [ymin, xmin, ymax, xmax] - of the window - scope: name scope. - - Returns: - pruned_boxlist: a new BoxList with all bounding boxes partially or fully in - the window. - valid_indices: a tensor with shape [M_out] indexing the valid bounding boxes - in the input tensor. - """ - with tf.name_scope(scope, 'PruneCompleteleyOutsideWindow'): - y_min, x_min, y_max, x_max = tf.split( - value=boxlist.get(), num_or_size_splits=4, axis=1) - win_y_min, win_x_min, win_y_max, win_x_max = tf.unstack(window) - coordinate_violations = tf.concat([ - tf.greater_equal(y_min, win_y_max), tf.greater_equal(x_min, win_x_max), - tf.less_equal(y_max, win_y_min), tf.less_equal(x_max, win_x_min) - ], 1) - valid_indices = tf.reshape( - tf.where(tf.logical_not(tf.reduce_any(coordinate_violations, 1))), [-1]) - return gather(boxlist, valid_indices), valid_indices - - -def intersection(boxlist1, boxlist2, scope=None): - """Compute pairwise intersection areas between boxes. - - Args: - boxlist1: BoxList holding N boxes - boxlist2: BoxList holding M boxes - scope: name scope. - - Returns: - a tensor with shape [N, M] representing pairwise intersections - """ - with tf.name_scope(scope, 'Intersection'): - y_min1, x_min1, y_max1, x_max1 = tf.split( - value=boxlist1.get(), num_or_size_splits=4, axis=1) - y_min2, x_min2, y_max2, x_max2 = tf.split( - value=boxlist2.get(), num_or_size_splits=4, axis=1) - all_pairs_min_ymax = tf.minimum(y_max1, tf.transpose(y_max2)) - all_pairs_max_ymin = tf.maximum(y_min1, tf.transpose(y_min2)) - intersect_heights = tf.maximum(0.0, all_pairs_min_ymax - all_pairs_max_ymin) - all_pairs_min_xmax = tf.minimum(x_max1, tf.transpose(x_max2)) - all_pairs_max_xmin = tf.maximum(x_min1, tf.transpose(x_min2)) - intersect_widths = tf.maximum(0.0, all_pairs_min_xmax - all_pairs_max_xmin) - return intersect_heights * intersect_widths - - -def matched_intersection(boxlist1, boxlist2, scope=None): - """Compute intersection areas between corresponding boxes in two boxlists. - - Args: - boxlist1: BoxList holding N boxes - boxlist2: BoxList holding N boxes - scope: name scope. - - Returns: - a tensor with shape [N] representing pairwise intersections - """ - with tf.name_scope(scope, 'MatchedIntersection'): - y_min1, x_min1, y_max1, x_max1 = tf.split( - value=boxlist1.get(), num_or_size_splits=4, axis=1) - y_min2, x_min2, y_max2, x_max2 = tf.split( - value=boxlist2.get(), num_or_size_splits=4, axis=1) - min_ymax = tf.minimum(y_max1, y_max2) - max_ymin = tf.maximum(y_min1, y_min2) - intersect_heights = tf.maximum(0.0, min_ymax - max_ymin) - min_xmax = tf.minimum(x_max1, x_max2) - max_xmin = tf.maximum(x_min1, x_min2) - intersect_widths = tf.maximum(0.0, min_xmax - max_xmin) - return tf.reshape(intersect_heights * intersect_widths, [-1]) - - -def iou(boxlist1, boxlist2, scope=None): - """Computes pairwise intersection-over-union between box collections. - - Args: - boxlist1: BoxList holding N boxes - boxlist2: BoxList holding M boxes - scope: name scope. - - Returns: - a tensor with shape [N, M] representing pairwise iou scores. - """ - with tf.name_scope(scope, 'IOU'): - intersections = intersection(boxlist1, boxlist2) - areas1 = area(boxlist1) - areas2 = area(boxlist2) - unions = ( - tf.expand_dims(areas1, 1) + tf.expand_dims(areas2, 0) - intersections) - return tf.where( - tf.equal(intersections, 0.0), - tf.zeros_like(intersections), tf.truediv(intersections, unions)) - - -def matched_iou(boxlist1, boxlist2, scope=None): - """Compute intersection-over-union between corresponding boxes in boxlists. - - Args: - boxlist1: BoxList holding N boxes - boxlist2: BoxList holding N boxes - scope: name scope. - - Returns: - a tensor with shape [N] representing pairwise iou scores. - """ - with tf.name_scope(scope, 'MatchedIOU'): - intersections = matched_intersection(boxlist1, boxlist2) - areas1 = area(boxlist1) - areas2 = area(boxlist2) - unions = areas1 + areas2 - intersections - return tf.where( - tf.equal(intersections, 0.0), - tf.zeros_like(intersections), tf.truediv(intersections, unions)) - - -def ioa(boxlist1, boxlist2, scope=None): - """Computes pairwise intersection-over-area between box collections. - - intersection-over-area (IOA) between two boxes box1 and box2 is defined as - their intersection area over box2's area. Note that ioa is not symmetric, - that is, ioa(box1, box2) != ioa(box2, box1). - - Args: - boxlist1: BoxList holding N boxes - boxlist2: BoxList holding M boxes - scope: name scope. - - Returns: - a tensor with shape [N, M] representing pairwise ioa scores. - """ - with tf.name_scope(scope, 'IOA'): - intersections = intersection(boxlist1, boxlist2) - areas = tf.expand_dims(area(boxlist2), 0) - return tf.truediv(intersections, areas) - - -def prune_non_overlapping_boxes( - boxlist1, boxlist2, min_overlap=0.0, scope=None): - """Prunes the boxes in boxlist1 that overlap less than thresh with boxlist2. - - For each box in boxlist1, we want its IOA to be more than minoverlap with - at least one of the boxes in boxlist2. If it does not, we remove it. - - Args: - boxlist1: BoxList holding N boxes. - boxlist2: BoxList holding M boxes. - min_overlap: Minimum required overlap between boxes, to count them as - overlapping. - scope: name scope. - - Returns: - new_boxlist1: A pruned boxlist with size [N', 4]. - keep_inds: A tensor with shape [N'] indexing kept bounding boxes in the - first input BoxList `boxlist1`. - """ - with tf.name_scope(scope, 'PruneNonOverlappingBoxes'): - ioa_ = ioa(boxlist2, boxlist1) # [M, N] tensor - ioa_ = tf.reduce_max(ioa_, reduction_indices=[0]) # [N] tensor - keep_bool = tf.greater_equal(ioa_, tf.constant(min_overlap)) - keep_inds = tf.squeeze(tf.where(keep_bool), squeeze_dims=[1]) - new_boxlist1 = gather(boxlist1, keep_inds) - return new_boxlist1, keep_inds - - -def prune_small_boxes(boxlist, min_side, scope=None): - """Prunes small boxes in the boxlist which have a side smaller than min_side. - - Args: - boxlist: BoxList holding N boxes. - min_side: Minimum width AND height of box to survive pruning. - scope: name scope. - - Returns: - A pruned boxlist. - """ - with tf.name_scope(scope, 'PruneSmallBoxes'): - height, width = height_width(boxlist) - is_valid = tf.logical_and(tf.greater_equal(width, min_side), - tf.greater_equal(height, min_side)) - return gather(boxlist, tf.reshape(tf.where(is_valid), [-1])) - - -def change_coordinate_frame(boxlist, window, scope=None): - """Change coordinate frame of the boxlist to be relative to window's frame. - - Given a window of the form [ymin, xmin, ymax, xmax], - changes bounding box coordinates from boxlist to be relative to this window - (e.g., the min corner maps to (0,0) and the max corner maps to (1,1)). - - An example use case is data augmentation: where we are given groundtruth - boxes (boxlist) and would like to randomly crop the image to some - window (window). In this case we need to change the coordinate frame of - each groundtruth box to be relative to this new window. - - Args: - boxlist: A BoxList object holding N boxes. - window: A rank 1 tensor [4]. - scope: name scope. - - Returns: - Returns a BoxList object with N boxes. - """ - with tf.name_scope(scope, 'ChangeCoordinateFrame'): - win_height = window[2] - window[0] - win_width = window[3] - window[1] - boxlist_new = scale(box_list.BoxList( - boxlist.get() - [window[0], window[1], window[0], window[1]]), - 1.0 / win_height, 1.0 / win_width) - boxlist_new = _copy_extra_fields(boxlist_new, boxlist) - return boxlist_new - - -def sq_dist(boxlist1, boxlist2, scope=None): - """Computes the pairwise squared distances between box corners. - - This op treats each box as if it were a point in a 4d Euclidean space and - computes pairwise squared distances. - - Mathematically, we are given two matrices of box coordinates X and Y, - where X(i,:) is the i'th row of X, containing the 4 numbers defining the - corners of the i'th box in boxlist1. Similarly Y(j,:) corresponds to - boxlist2. We compute - Z(i,j) = ||X(i,:) - Y(j,:)||^2 - = ||X(i,:)||^2 + ||Y(j,:)||^2 - 2 X(i,:)' * Y(j,:), - - Args: - boxlist1: BoxList holding N boxes - boxlist2: BoxList holding M boxes - scope: name scope. - - Returns: - a tensor with shape [N, M] representing pairwise distances - """ - with tf.name_scope(scope, 'SqDist'): - sqnorm1 = tf.reduce_sum(tf.square(boxlist1.get()), 1, keep_dims=True) - sqnorm2 = tf.reduce_sum(tf.square(boxlist2.get()), 1, keep_dims=True) - innerprod = tf.matmul(boxlist1.get(), boxlist2.get(), - transpose_a=False, transpose_b=True) - return sqnorm1 + tf.transpose(sqnorm2) - 2.0 * innerprod - - -def boolean_mask(boxlist, indicator, fields=None, scope=None): - """Select boxes from BoxList according to indicator and return new BoxList. - - `boolean_mask` returns the subset of boxes that are marked as "True" by the - indicator tensor. By default, `boolean_mask` returns boxes corresponding to - the input index list, as well as all additional fields stored in the boxlist - (indexing into the first dimension). However one can optionally only draw - from a subset of fields. - - Args: - boxlist: BoxList holding N boxes - indicator: a rank-1 boolean tensor - fields: (optional) list of fields to also gather from. If None (default), - all fields are gathered from. Pass an empty fields list to only gather - the box coordinates. - scope: name scope. - - Returns: - subboxlist: a BoxList corresponding to the subset of the input BoxList - specified by indicator - Raises: - ValueError: if `indicator` is not a rank-1 boolean tensor. - """ - with tf.name_scope(scope, 'BooleanMask'): - if indicator.shape.ndims != 1: - raise ValueError('indicator should have rank 1') - if indicator.dtype != tf.bool: - raise ValueError('indicator should be a boolean tensor') - subboxlist = box_list.BoxList(tf.boolean_mask(boxlist.get(), indicator)) - if fields is None: - fields = boxlist.get_extra_fields() - for field in fields: - if not boxlist.has_field(field): - raise ValueError('boxlist must contain all specified fields') - subfieldlist = tf.boolean_mask(boxlist.get_field(field), indicator) - subboxlist.add_field(field, subfieldlist) - return subboxlist - - -def gather(boxlist, indices, fields=None, scope=None): - """Gather boxes from BoxList according to indices and return new BoxList. - - By default, `gather` returns boxes corresponding to the input index list, as - well as all additional fields stored in the boxlist (indexing into the - first dimension). However one can optionally only gather from a - subset of fields. - - Args: - boxlist: BoxList holding N boxes - indices: a rank-1 tensor of type int32 / int64 - fields: (optional) list of fields to also gather from. If None (default), - all fields are gathered from. Pass an empty fields list to only gather - the box coordinates. - scope: name scope. - - Returns: - subboxlist: a BoxList corresponding to the subset of the input BoxList - specified by indices - Raises: - ValueError: if specified field is not contained in boxlist or if the - indices are not of type int32 - """ - with tf.name_scope(scope, 'Gather'): - if len(indices.shape.as_list()) != 1: - raise ValueError('indices should have rank 1') - if indices.dtype != tf.int32 and indices.dtype != tf.int64: - raise ValueError('indices should be an int32 / int64 tensor') - subboxlist = box_list.BoxList(tf.gather(boxlist.get(), indices)) - if fields is None: - fields = boxlist.get_extra_fields() - for field in fields: - if not boxlist.has_field(field): - raise ValueError('boxlist must contain all specified fields') - subfieldlist = tf.gather(boxlist.get_field(field), indices) - subboxlist.add_field(field, subfieldlist) - return subboxlist - - -def concatenate(boxlists, fields=None, scope=None): - """Concatenate list of BoxLists. - - This op concatenates a list of input BoxLists into a larger BoxList. It also - handles concatenation of BoxList fields as long as the field tensor shapes - are equal except for the first dimension. - - Args: - boxlists: list of BoxList objects - fields: optional list of fields to also concatenate. By default, all - fields from the first BoxList in the list are included in the - concatenation. - scope: name scope. - - Returns: - a BoxList with number of boxes equal to - sum([boxlist.num_boxes() for boxlist in BoxList]) - Raises: - ValueError: if boxlists is invalid (i.e., is not a list, is empty, or - contains non BoxList objects), or if requested fields are not contained in - all boxlists - """ - with tf.name_scope(scope, 'Concatenate'): - if not isinstance(boxlists, list): - raise ValueError('boxlists should be a list') - if not boxlists: - raise ValueError('boxlists should have nonzero length') - for boxlist in boxlists: - if not isinstance(boxlist, box_list.BoxList): - raise ValueError('all elements of boxlists should be BoxList objects') - concatenated = box_list.BoxList( - tf.concat([boxlist.get() for boxlist in boxlists], 0)) - if fields is None: - fields = boxlists[0].get_extra_fields() - for field in fields: - first_field_shape = boxlists[0].get_field(field).get_shape().as_list() - first_field_shape[0] = -1 - if None in first_field_shape: - raise ValueError('field %s must have fully defined shape except for the' - ' 0th dimension.' % field) - for boxlist in boxlists: - if not boxlist.has_field(field): - raise ValueError('boxlist must contain all requested fields') - field_shape = boxlist.get_field(field).get_shape().as_list() - field_shape[0] = -1 - if field_shape != first_field_shape: - raise ValueError('field %s must have same shape for all boxlists ' - 'except for the 0th dimension.' % field) - concatenated_field = tf.concat( - [boxlist.get_field(field) for boxlist in boxlists], 0) - concatenated.add_field(field, concatenated_field) - return concatenated - - -def sort_by_field(boxlist, field, order=SortOrder.descend, scope=None): - """Sort boxes and associated fields according to a scalar field. - - A common use case is reordering the boxes according to descending scores. - - Args: - boxlist: BoxList holding N boxes. - field: A BoxList field for sorting and reordering the BoxList. - order: (Optional) descend or ascend. Default is descend. - scope: name scope. - - Returns: - sorted_boxlist: A sorted BoxList with the field in the specified order. - - Raises: - ValueError: if specified field does not exist - ValueError: if the order is not either descend or ascend - """ - with tf.name_scope(scope, 'SortByField'): - if order != SortOrder.descend and order != SortOrder.ascend: - raise ValueError('Invalid sort order') - - field_to_sort = boxlist.get_field(field) - if len(field_to_sort.shape.as_list()) != 1: - raise ValueError('Field should have rank 1') - - num_boxes = boxlist.num_boxes() - num_entries = tf.size(field_to_sort) - length_assert = tf.Assert( - tf.equal(num_boxes, num_entries), - ['Incorrect field size: actual vs expected.', num_entries, num_boxes]) - - with tf.control_dependencies([length_assert]): - # TODO(derekjchow): Remove with tf.device when top_k operation runs - # correctly on GPU. - with tf.device('/cpu:0'): - _, sorted_indices = tf.nn.top_k(field_to_sort, num_boxes, sorted=True) - - if order == SortOrder.ascend: - sorted_indices = tf.reverse_v2(sorted_indices, [0]) - - return gather(boxlist, sorted_indices) - - -def visualize_boxes_in_image(image, boxlist, normalized=False, scope=None): - """Overlay bounding box list on image. - - Currently this visualization plots a 1 pixel thick red bounding box on top - of the image. Note that tf.image.draw_bounding_boxes essentially is - 1 indexed. - - Args: - image: an image tensor with shape [height, width, 3] - boxlist: a BoxList - normalized: (boolean) specify whether corners are to be interpreted - as absolute coordinates in image space or normalized with respect to the - image size. - scope: name scope. - - Returns: - image_and_boxes: an image tensor with shape [height, width, 3] - """ - with tf.name_scope(scope, 'VisualizeBoxesInImage'): - if not normalized: - height, width, _ = tf.unstack(tf.shape(image)) - boxlist = scale(boxlist, - 1.0 / tf.cast(height, tf.float32), - 1.0 / tf.cast(width, tf.float32)) - corners = tf.expand_dims(boxlist.get(), 0) - image = tf.expand_dims(image, 0) - return tf.squeeze(tf.image.draw_bounding_boxes(image, corners), [0]) - - -def filter_field_value_equals(boxlist, field, value, scope=None): - """Filter to keep only boxes with field entries equal to the given value. - - Args: - boxlist: BoxList holding N boxes. - field: field name for filtering. - value: scalar value. - scope: name scope. - - Returns: - a BoxList holding M boxes where M <= N - - Raises: - ValueError: if boxlist not a BoxList object or if it does not have - the specified field. - """ - with tf.name_scope(scope, 'FilterFieldValueEquals'): - if not isinstance(boxlist, box_list.BoxList): - raise ValueError('boxlist must be a BoxList') - if not boxlist.has_field(field): - raise ValueError('boxlist must contain the specified field') - filter_field = boxlist.get_field(field) - gather_index = tf.reshape(tf.where(tf.equal(filter_field, value)), [-1]) - return gather(boxlist, gather_index) - - -def filter_greater_than(boxlist, thresh, scope=None): - """Filter to keep only boxes with score exceeding a given threshold. - - This op keeps the collection of boxes whose corresponding scores are - greater than the input threshold. - - TODO(jonathanhuang): Change function name to filter_scores_greater_than - - Args: - boxlist: BoxList holding N boxes. Must contain a 'scores' field - representing detection scores. - thresh: scalar threshold - scope: name scope. - - Returns: - a BoxList holding M boxes where M <= N - - Raises: - ValueError: if boxlist not a BoxList object or if it does not - have a scores field - """ - with tf.name_scope(scope, 'FilterGreaterThan'): - if not isinstance(boxlist, box_list.BoxList): - raise ValueError('boxlist must be a BoxList') - if not boxlist.has_field('scores'): - raise ValueError('input boxlist must have \'scores\' field') - scores = boxlist.get_field('scores') - if len(scores.shape.as_list()) > 2: - raise ValueError('Scores should have rank 1 or 2') - if len(scores.shape.as_list()) == 2 and scores.shape.as_list()[1] != 1: - raise ValueError('Scores should have rank 1 or have shape ' - 'consistent with [None, 1]') - high_score_indices = tf.cast(tf.reshape( - tf.where(tf.greater(scores, thresh)), - [-1]), tf.int32) - return gather(boxlist, high_score_indices) - - -def non_max_suppression(boxlist, thresh, max_output_size, scope=None): - """Non maximum suppression. - - This op greedily selects a subset of detection bounding boxes, pruning - away boxes that have high IOU (intersection over union) overlap (> thresh) - with already selected boxes. Note that this only works for a single class --- - to apply NMS to multi-class predictions, use MultiClassNonMaxSuppression. - - Args: - boxlist: BoxList holding N boxes. Must contain a 'scores' field - representing detection scores. - thresh: scalar threshold - max_output_size: maximum number of retained boxes - scope: name scope. - - Returns: - a BoxList holding M boxes where M <= max_output_size - Raises: - ValueError: if thresh is not in [0, 1] - """ - with tf.name_scope(scope, 'NonMaxSuppression'): - if not 0 <= thresh <= 1.0: - raise ValueError('thresh must be between 0 and 1') - if not isinstance(boxlist, box_list.BoxList): - raise ValueError('boxlist must be a BoxList') - if not boxlist.has_field('scores'): - raise ValueError('input boxlist must have \'scores\' field') - selected_indices = tf.image.non_max_suppression( - boxlist.get(), boxlist.get_field('scores'), - max_output_size, iou_threshold=thresh) - return gather(boxlist, selected_indices) - - -def _copy_extra_fields(boxlist_to_copy_to, boxlist_to_copy_from): - """Copies the extra fields of boxlist_to_copy_from to boxlist_to_copy_to. - - Args: - boxlist_to_copy_to: BoxList to which extra fields are copied. - boxlist_to_copy_from: BoxList from which fields are copied. - - Returns: - boxlist_to_copy_to with extra fields. - """ - for field in boxlist_to_copy_from.get_extra_fields(): - boxlist_to_copy_to.add_field(field, boxlist_to_copy_from.get_field(field)) - return boxlist_to_copy_to - - -def to_normalized_coordinates(boxlist, height, width, - check_range=True, scope=None): - """Converts absolute box coordinates to normalized coordinates in [0, 1]. - - Usually one uses the dynamic shape of the image or conv-layer tensor: - boxlist = box_list_ops.to_normalized_coordinates(boxlist, - tf.shape(images)[1], - tf.shape(images)[2]), - - This function raises an assertion failed error at graph execution time when - the maximum coordinate is smaller than 1.01 (which means that coordinates are - already normalized). The value 1.01 is to deal with small rounding errors. - - Args: - boxlist: BoxList with coordinates in terms of pixel-locations. - height: Maximum value for height of absolute box coordinates. - width: Maximum value for width of absolute box coordinates. - check_range: If True, checks if the coordinates are normalized or not. - scope: name scope. - - Returns: - boxlist with normalized coordinates in [0, 1]. - """ - with tf.name_scope(scope, 'ToNormalizedCoordinates'): - height = tf.cast(height, tf.float32) - width = tf.cast(width, tf.float32) - - if check_range: - max_val = tf.reduce_max(boxlist.get()) - max_assert = tf.Assert(tf.greater(max_val, 1.01), - ['max value is lower than 1.01: ', max_val]) - with tf.control_dependencies([max_assert]): - width = tf.identity(width) - - return scale(boxlist, 1 / height, 1 / width) - - -def to_absolute_coordinates(boxlist, - height, - width, - check_range=True, - maximum_normalized_coordinate=1.1, - scope=None): - """Converts normalized box coordinates to absolute pixel coordinates. - - This function raises an assertion failed error when the maximum box coordinate - value is larger than maximum_normalized_coordinate (in which case coordinates - are already absolute). - - Args: - boxlist: BoxList with coordinates in range [0, 1]. - height: Maximum value for height of absolute box coordinates. - width: Maximum value for width of absolute box coordinates. - check_range: If True, checks if the coordinates are normalized or not. - maximum_normalized_coordinate: Maximum coordinate value to be considered - as normalized, default to 1.1. - scope: name scope. - - Returns: - boxlist with absolute coordinates in terms of the image size. - - """ - with tf.name_scope(scope, 'ToAbsoluteCoordinates'): - height = tf.cast(height, tf.float32) - width = tf.cast(width, tf.float32) - - # Ensure range of input boxes is correct. - if check_range: - box_maximum = tf.reduce_max(boxlist.get()) - max_assert = tf.Assert( - tf.greater_equal(maximum_normalized_coordinate, box_maximum), - ['maximum box coordinate value is larger ' - 'than %f: ' % maximum_normalized_coordinate, box_maximum]) - with tf.control_dependencies([max_assert]): - width = tf.identity(width) - - return scale(boxlist, height, width) - - -def refine_boxes_multi_class(pool_boxes, - num_classes, - nms_iou_thresh, - nms_max_detections, - voting_iou_thresh=0.5): - """Refines a pool of boxes using non max suppression and box voting. - - Box refinement is done independently for each class. - - Args: - pool_boxes: (BoxList) A collection of boxes to be refined. pool_boxes must - have a rank 1 'scores' field and a rank 1 'classes' field. - num_classes: (int scalar) Number of classes. - nms_iou_thresh: (float scalar) iou threshold for non max suppression (NMS). - nms_max_detections: (int scalar) maximum output size for NMS. - voting_iou_thresh: (float scalar) iou threshold for box voting. - - Returns: - BoxList of refined boxes. - - Raises: - ValueError: if - a) nms_iou_thresh or voting_iou_thresh is not in [0, 1]. - b) pool_boxes is not a BoxList. - c) pool_boxes does not have a scores and classes field. - """ - if not 0.0 <= nms_iou_thresh <= 1.0: - raise ValueError('nms_iou_thresh must be between 0 and 1') - if not 0.0 <= voting_iou_thresh <= 1.0: - raise ValueError('voting_iou_thresh must be between 0 and 1') - if not isinstance(pool_boxes, box_list.BoxList): - raise ValueError('pool_boxes must be a BoxList') - if not pool_boxes.has_field('scores'): - raise ValueError('pool_boxes must have a \'scores\' field') - if not pool_boxes.has_field('classes'): - raise ValueError('pool_boxes must have a \'classes\' field') - - refined_boxes = [] - for i in range(num_classes): - boxes_class = filter_field_value_equals(pool_boxes, 'classes', i) - refined_boxes_class = refine_boxes(boxes_class, nms_iou_thresh, - nms_max_detections, voting_iou_thresh) - refined_boxes.append(refined_boxes_class) - return sort_by_field(concatenate(refined_boxes), 'scores') - - -def refine_boxes(pool_boxes, - nms_iou_thresh, - nms_max_detections, - voting_iou_thresh=0.5): - """Refines a pool of boxes using non max suppression and box voting. - - Args: - pool_boxes: (BoxList) A collection of boxes to be refined. pool_boxes must - have a rank 1 'scores' field. - nms_iou_thresh: (float scalar) iou threshold for non max suppression (NMS). - nms_max_detections: (int scalar) maximum output size for NMS. - voting_iou_thresh: (float scalar) iou threshold for box voting. - - Returns: - BoxList of refined boxes. - - Raises: - ValueError: if - a) nms_iou_thresh or voting_iou_thresh is not in [0, 1]. - b) pool_boxes is not a BoxList. - c) pool_boxes does not have a scores field. - """ - if not 0.0 <= nms_iou_thresh <= 1.0: - raise ValueError('nms_iou_thresh must be between 0 and 1') - if not 0.0 <= voting_iou_thresh <= 1.0: - raise ValueError('voting_iou_thresh must be between 0 and 1') - if not isinstance(pool_boxes, box_list.BoxList): - raise ValueError('pool_boxes must be a BoxList') - if not pool_boxes.has_field('scores'): - raise ValueError('pool_boxes must have a \'scores\' field') - - nms_boxes = non_max_suppression( - pool_boxes, nms_iou_thresh, nms_max_detections) - return box_voting(nms_boxes, pool_boxes, voting_iou_thresh) - - -def box_voting(selected_boxes, pool_boxes, iou_thresh=0.5): - """Performs box voting as described in S. Gidaris and N. Komodakis, ICCV 2015. - - Performs box voting as described in 'Object detection via a multi-region & - semantic segmentation-aware CNN model', Gidaris and Komodakis, ICCV 2015. For - each box 'B' in selected_boxes, we find the set 'S' of boxes in pool_boxes - with iou overlap >= iou_thresh. The location of B is set to the weighted - average location of boxes in S (scores are used for weighting). And the score - of B is set to the average score of boxes in S. - - Args: - selected_boxes: BoxList containing a subset of boxes in pool_boxes. These - boxes are usually selected from pool_boxes using non max suppression. - pool_boxes: BoxList containing a set of (possibly redundant) boxes. - iou_thresh: (float scalar) iou threshold for matching boxes in - selected_boxes and pool_boxes. - - Returns: - BoxList containing averaged locations and scores for each box in - selected_boxes. - - Raises: - ValueError: if - a) selected_boxes or pool_boxes is not a BoxList. - b) if iou_thresh is not in [0, 1]. - c) pool_boxes does not have a scores field. - """ - if not 0.0 <= iou_thresh <= 1.0: - raise ValueError('iou_thresh must be between 0 and 1') - if not isinstance(selected_boxes, box_list.BoxList): - raise ValueError('selected_boxes must be a BoxList') - if not isinstance(pool_boxes, box_list.BoxList): - raise ValueError('pool_boxes must be a BoxList') - if not pool_boxes.has_field('scores'): - raise ValueError('pool_boxes must have a \'scores\' field') - - iou_ = iou(selected_boxes, pool_boxes) - match_indicator = tf.to_float(tf.greater(iou_, iou_thresh)) - num_matches = tf.reduce_sum(match_indicator, 1) - # TODO(kbanoop): Handle the case where some boxes in selected_boxes do not - # match to any boxes in pool_boxes. For such boxes without any matches, we - # should return the original boxes without voting. - match_assert = tf.Assert( - tf.reduce_all(tf.greater(num_matches, 0)), - ['Each box in selected_boxes must match with at least one box ' - 'in pool_boxes.']) - - scores = tf.expand_dims(pool_boxes.get_field('scores'), 1) - scores_assert = tf.Assert( - tf.reduce_all(tf.greater_equal(scores, 0)), - ['Scores must be non negative.']) - - with tf.control_dependencies([scores_assert, match_assert]): - sum_scores = tf.matmul(match_indicator, scores) - averaged_scores = tf.reshape(sum_scores, [-1]) / num_matches - - box_locations = tf.matmul(match_indicator, - pool_boxes.get() * scores) / sum_scores - averaged_boxes = box_list.BoxList(box_locations) - _copy_extra_fields(averaged_boxes, selected_boxes) - averaged_boxes.add_field('scores', averaged_scores) - return averaged_boxes - - -def pad_or_clip_box_list(boxlist, num_boxes, scope=None): - """Pads or clips all fields of a BoxList. - - Args: - boxlist: A BoxList with arbitrary of number of boxes. - num_boxes: First num_boxes in boxlist are kept. - The fields are zero-padded if num_boxes is bigger than the - actual number of boxes. - scope: name scope. - - Returns: - BoxList with all fields padded or clipped. - """ - with tf.name_scope(scope, 'PadOrClipBoxList'): - subboxlist = box_list.BoxList(shape_utils.pad_or_clip_tensor( - boxlist.get(), num_boxes)) - for field in boxlist.get_extra_fields(): - subfield = shape_utils.pad_or_clip_tensor( - boxlist.get_field(field), num_boxes) - subboxlist.add_field(field, subfield) - return subboxlist - - -def select_random_box(boxlist, - default_box=None, - seed=None, - scope=None): - """Selects a random bounding box from a `BoxList`. - - Args: - boxlist: A BoxList. - default_box: A [1, 4] float32 tensor. If no boxes are present in `boxlist`, - this default box will be returned. If None, will use a default box of - [[-1., -1., -1., -1.]]. - seed: Random seed. - scope: Name scope. - - Returns: - bbox: A [1, 4] tensor with a random bounding box. - valid: A bool tensor indicating whether a valid bounding box is returned - (True) or whether the default box is returned (False). - """ - with tf.name_scope(scope, 'SelectRandomBox'): - bboxes = boxlist.get() - combined_shape = shape_utils.combined_static_and_dynamic_shape(bboxes) - number_of_boxes = combined_shape[0] - default_box = default_box or tf.constant([[-1., -1., -1., -1.]]) - - def select_box(): - random_index = tf.random_uniform([], - maxval=number_of_boxes, - dtype=tf.int32, - seed=seed) - return tf.expand_dims(bboxes[random_index], axis=0), tf.constant(True) - - return tf.cond( - tf.greater_equal(number_of_boxes, 1), - true_fn=select_box, - false_fn=lambda: (default_box, tf.constant(False))) - - -def get_minimal_coverage_box(boxlist, - default_box=None, - scope=None): - """Creates a single bounding box which covers all boxes in the boxlist. - - Args: - boxlist: A Boxlist. - default_box: A [1, 4] float32 tensor. If no boxes are present in `boxlist`, - this default box will be returned. If None, will use a default box of - [[0., 0., 1., 1.]]. - scope: Name scope. - - Returns: - A [1, 4] float32 tensor with a bounding box that tightly covers all the - boxes in the box list. If the boxlist does not contain any boxes, the - default box is returned. - """ - with tf.name_scope(scope, 'CreateCoverageBox'): - num_boxes = boxlist.num_boxes() - - def coverage_box(bboxes): - y_min, x_min, y_max, x_max = tf.split( - value=bboxes, num_or_size_splits=4, axis=1) - y_min_coverage = tf.reduce_min(y_min, axis=0) - x_min_coverage = tf.reduce_min(x_min, axis=0) - y_max_coverage = tf.reduce_max(y_max, axis=0) - x_max_coverage = tf.reduce_max(x_max, axis=0) - return tf.stack( - [y_min_coverage, x_min_coverage, y_max_coverage, x_max_coverage], - axis=1) - - default_box = default_box or tf.constant([[0., 0., 1., 1.]]) - return tf.cond( - tf.greater_equal(num_boxes, 1), - true_fn=lambda: coverage_box(boxlist.get()), - false_fn=lambda: default_box) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_ops_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_ops_test.py deleted file mode 100644 index bb76cfd35..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_ops_test.py +++ /dev/null @@ -1,1036 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.box_list_ops.""" -import numpy as np -import tensorflow as tf -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops - -from object_detection.core import box_list -from object_detection.core import box_list_ops - - -class BoxListOpsTest(tf.test.TestCase): - """Tests for common bounding box operations.""" - - def test_area(self): - corners = tf.constant([[0.0, 0.0, 10.0, 20.0], [1.0, 2.0, 3.0, 4.0]]) - exp_output = [200.0, 4.0] - boxes = box_list.BoxList(corners) - areas = box_list_ops.area(boxes) - with self.test_session() as sess: - areas_output = sess.run(areas) - self.assertAllClose(areas_output, exp_output) - - def test_height_width(self): - corners = tf.constant([[0.0, 0.0, 10.0, 20.0], [1.0, 2.0, 3.0, 4.0]]) - exp_output_heights = [10., 2.] - exp_output_widths = [20., 2.] - boxes = box_list.BoxList(corners) - heights, widths = box_list_ops.height_width(boxes) - with self.test_session() as sess: - output_heights, output_widths = sess.run([heights, widths]) - self.assertAllClose(output_heights, exp_output_heights) - self.assertAllClose(output_widths, exp_output_widths) - - def test_scale(self): - corners = tf.constant([[0, 0, 100, 200], [50, 120, 100, 140]], - dtype=tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('extra_data', tf.constant([[1], [2]])) - - y_scale = tf.constant(1.0/100) - x_scale = tf.constant(1.0/200) - scaled_boxes = box_list_ops.scale(boxes, y_scale, x_scale) - exp_output = [[0, 0, 1, 1], [0.5, 0.6, 1.0, 0.7]] - with self.test_session() as sess: - scaled_corners_out = sess.run(scaled_boxes.get()) - self.assertAllClose(scaled_corners_out, exp_output) - extra_data_out = sess.run(scaled_boxes.get_field('extra_data')) - self.assertAllEqual(extra_data_out, [[1], [2]]) - - def test_clip_to_window_filter_boxes_which_fall_outside_the_window( - self): - window = tf.constant([0, 0, 9, 14], tf.float32) - corners = tf.constant([[5.0, 5.0, 6.0, 6.0], - [-1.0, -2.0, 4.0, 5.0], - [2.0, 3.0, 5.0, 9.0], - [0.0, 0.0, 9.0, 14.0], - [-100.0, -100.0, 300.0, 600.0], - [-10.0, -10.0, -9.0, -9.0]]) - boxes = box_list.BoxList(corners) - boxes.add_field('extra_data', tf.constant([[1], [2], [3], [4], [5], [6]])) - exp_output = [[5.0, 5.0, 6.0, 6.0], [0.0, 0.0, 4.0, 5.0], - [2.0, 3.0, 5.0, 9.0], [0.0, 0.0, 9.0, 14.0], - [0.0, 0.0, 9.0, 14.0]] - pruned = box_list_ops.clip_to_window( - boxes, window, filter_nonoverlapping=True) - with self.test_session() as sess: - pruned_output = sess.run(pruned.get()) - self.assertAllClose(pruned_output, exp_output) - extra_data_out = sess.run(pruned.get_field('extra_data')) - self.assertAllEqual(extra_data_out, [[1], [2], [3], [4], [5]]) - - def test_clip_to_window_without_filtering_boxes_which_fall_outside_the_window( - self): - window = tf.constant([0, 0, 9, 14], tf.float32) - corners = tf.constant([[5.0, 5.0, 6.0, 6.0], - [-1.0, -2.0, 4.0, 5.0], - [2.0, 3.0, 5.0, 9.0], - [0.0, 0.0, 9.0, 14.0], - [-100.0, -100.0, 300.0, 600.0], - [-10.0, -10.0, -9.0, -9.0]]) - boxes = box_list.BoxList(corners) - boxes.add_field('extra_data', tf.constant([[1], [2], [3], [4], [5], [6]])) - exp_output = [[5.0, 5.0, 6.0, 6.0], [0.0, 0.0, 4.0, 5.0], - [2.0, 3.0, 5.0, 9.0], [0.0, 0.0, 9.0, 14.0], - [0.0, 0.0, 9.0, 14.0], [0.0, 0.0, 0.0, 0.0]] - pruned = box_list_ops.clip_to_window( - boxes, window, filter_nonoverlapping=False) - with self.test_session() as sess: - pruned_output = sess.run(pruned.get()) - self.assertAllClose(pruned_output, exp_output) - extra_data_out = sess.run(pruned.get_field('extra_data')) - self.assertAllEqual(extra_data_out, [[1], [2], [3], [4], [5], [6]]) - - def test_prune_outside_window_filters_boxes_which_fall_outside_the_window( - self): - window = tf.constant([0, 0, 9, 14], tf.float32) - corners = tf.constant([[5.0, 5.0, 6.0, 6.0], - [-1.0, -2.0, 4.0, 5.0], - [2.0, 3.0, 5.0, 9.0], - [0.0, 0.0, 9.0, 14.0], - [-10.0, -10.0, -9.0, -9.0], - [-100.0, -100.0, 300.0, 600.0]]) - boxes = box_list.BoxList(corners) - boxes.add_field('extra_data', tf.constant([[1], [2], [3], [4], [5], [6]])) - exp_output = [[5.0, 5.0, 6.0, 6.0], - [2.0, 3.0, 5.0, 9.0], - [0.0, 0.0, 9.0, 14.0]] - pruned, keep_indices = box_list_ops.prune_outside_window(boxes, window) - with self.test_session() as sess: - pruned_output = sess.run(pruned.get()) - self.assertAllClose(pruned_output, exp_output) - keep_indices_out = sess.run(keep_indices) - self.assertAllEqual(keep_indices_out, [0, 2, 3]) - extra_data_out = sess.run(pruned.get_field('extra_data')) - self.assertAllEqual(extra_data_out, [[1], [3], [4]]) - - def test_prune_completely_outside_window(self): - window = tf.constant([0, 0, 9, 14], tf.float32) - corners = tf.constant([[5.0, 5.0, 6.0, 6.0], - [-1.0, -2.0, 4.0, 5.0], - [2.0, 3.0, 5.0, 9.0], - [0.0, 0.0, 9.0, 14.0], - [-10.0, -10.0, -9.0, -9.0], - [-100.0, -100.0, 300.0, 600.0]]) - boxes = box_list.BoxList(corners) - boxes.add_field('extra_data', tf.constant([[1], [2], [3], [4], [5], [6]])) - exp_output = [[5.0, 5.0, 6.0, 6.0], - [-1.0, -2.0, 4.0, 5.0], - [2.0, 3.0, 5.0, 9.0], - [0.0, 0.0, 9.0, 14.0], - [-100.0, -100.0, 300.0, 600.0]] - pruned, keep_indices = box_list_ops.prune_completely_outside_window(boxes, - window) - with self.test_session() as sess: - pruned_output = sess.run(pruned.get()) - self.assertAllClose(pruned_output, exp_output) - keep_indices_out = sess.run(keep_indices) - self.assertAllEqual(keep_indices_out, [0, 1, 2, 3, 5]) - extra_data_out = sess.run(pruned.get_field('extra_data')) - self.assertAllEqual(extra_data_out, [[1], [2], [3], [4], [6]]) - - def test_prune_completely_outside_window_with_empty_boxlist(self): - window = tf.constant([0, 0, 9, 14], tf.float32) - corners = tf.zeros(shape=[0, 4], dtype=tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('extra_data', tf.zeros(shape=[0], dtype=tf.int32)) - pruned, keep_indices = box_list_ops.prune_completely_outside_window(boxes, - window) - pruned_boxes = pruned.get() - extra = pruned.get_field('extra_data') - - exp_pruned_boxes = np.zeros(shape=[0, 4], dtype=np.float32) - exp_extra = np.zeros(shape=[0], dtype=np.int32) - with self.test_session() as sess: - pruned_boxes_out, keep_indices_out, extra_out = sess.run( - [pruned_boxes, keep_indices, extra]) - self.assertAllClose(exp_pruned_boxes, pruned_boxes_out) - self.assertAllEqual([], keep_indices_out) - self.assertAllEqual(exp_extra, extra_out) - - def test_intersection(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - exp_output = [[2.0, 0.0, 6.0], [1.0, 0.0, 5.0]] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - intersect = box_list_ops.intersection(boxes1, boxes2) - with self.test_session() as sess: - intersect_output = sess.run(intersect) - self.assertAllClose(intersect_output, exp_output) - - def test_matched_intersection(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]]) - exp_output = [2.0, 0.0] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - intersect = box_list_ops.matched_intersection(boxes1, boxes2) - with self.test_session() as sess: - intersect_output = sess.run(intersect) - self.assertAllClose(intersect_output, exp_output) - - def test_iou(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - exp_output = [[2.0 / 16.0, 0, 6.0 / 400.0], [1.0 / 16.0, 0.0, 5.0 / 400.0]] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - iou = box_list_ops.iou(boxes1, boxes2) - with self.test_session() as sess: - iou_output = sess.run(iou) - self.assertAllClose(iou_output, exp_output) - - def test_matched_iou(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]]) - exp_output = [2.0 / 16.0, 0] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - iou = box_list_ops.matched_iou(boxes1, boxes2) - with self.test_session() as sess: - iou_output = sess.run(iou) - self.assertAllClose(iou_output, exp_output) - - def test_iouworks_on_empty_inputs(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - boxes_empty = box_list.BoxList(tf.zeros((0, 4))) - iou_empty_1 = box_list_ops.iou(boxes1, boxes_empty) - iou_empty_2 = box_list_ops.iou(boxes_empty, boxes2) - iou_empty_3 = box_list_ops.iou(boxes_empty, boxes_empty) - with self.test_session() as sess: - iou_output_1, iou_output_2, iou_output_3 = sess.run( - [iou_empty_1, iou_empty_2, iou_empty_3]) - self.assertAllEqual(iou_output_1.shape, (2, 0)) - self.assertAllEqual(iou_output_2.shape, (0, 3)) - self.assertAllEqual(iou_output_3.shape, (0, 0)) - - def test_ioa(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - exp_output_1 = [[2.0 / 12.0, 0, 6.0 / 400.0], - [1.0 / 12.0, 0.0, 5.0 / 400.0]] - exp_output_2 = [[2.0 / 6.0, 1.0 / 5.0], - [0, 0], - [6.0 / 6.0, 5.0 / 5.0]] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - ioa_1 = box_list_ops.ioa(boxes1, boxes2) - ioa_2 = box_list_ops.ioa(boxes2, boxes1) - with self.test_session() as sess: - ioa_output_1, ioa_output_2 = sess.run([ioa_1, ioa_2]) - self.assertAllClose(ioa_output_1, exp_output_1) - self.assertAllClose(ioa_output_2, exp_output_2) - - def test_prune_non_overlapping_boxes(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - minoverlap = 0.5 - - exp_output_1 = boxes1 - exp_output_2 = box_list.BoxList(tf.constant(0.0, shape=[0, 4])) - output_1, keep_indices_1 = box_list_ops.prune_non_overlapping_boxes( - boxes1, boxes2, min_overlap=minoverlap) - output_2, keep_indices_2 = box_list_ops.prune_non_overlapping_boxes( - boxes2, boxes1, min_overlap=minoverlap) - with self.test_session() as sess: - (output_1_, keep_indices_1_, output_2_, keep_indices_2_, exp_output_1_, - exp_output_2_) = sess.run( - [output_1.get(), keep_indices_1, - output_2.get(), keep_indices_2, - exp_output_1.get(), exp_output_2.get()]) - self.assertAllClose(output_1_, exp_output_1_) - self.assertAllClose(output_2_, exp_output_2_) - self.assertAllEqual(keep_indices_1_, [0, 1]) - self.assertAllEqual(keep_indices_2_, []) - - def test_prune_small_boxes(self): - boxes = tf.constant([[4.0, 3.0, 7.0, 5.0], - [5.0, 6.0, 10.0, 7.0], - [3.0, 4.0, 6.0, 8.0], - [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - exp_boxes = [[3.0, 4.0, 6.0, 8.0], - [0.0, 0.0, 20.0, 20.0]] - boxes = box_list.BoxList(boxes) - pruned_boxes = box_list_ops.prune_small_boxes(boxes, 3) - with self.test_session() as sess: - pruned_boxes = sess.run(pruned_boxes.get()) - self.assertAllEqual(pruned_boxes, exp_boxes) - - def test_prune_small_boxes_prunes_boxes_with_negative_side(self): - boxes = tf.constant([[4.0, 3.0, 7.0, 5.0], - [5.0, 6.0, 10.0, 7.0], - [3.0, 4.0, 6.0, 8.0], - [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0], - [2.0, 3.0, 1.5, 7.0], # negative height - [2.0, 3.0, 5.0, 1.7]]) # negative width - exp_boxes = [[3.0, 4.0, 6.0, 8.0], - [0.0, 0.0, 20.0, 20.0]] - boxes = box_list.BoxList(boxes) - pruned_boxes = box_list_ops.prune_small_boxes(boxes, 3) - with self.test_session() as sess: - pruned_boxes = sess.run(pruned_boxes.get()) - self.assertAllEqual(pruned_boxes, exp_boxes) - - def test_change_coordinate_frame(self): - corners = tf.constant([[0.25, 0.5, 0.75, 0.75], [0.5, 0.0, 1.0, 1.0]]) - window = tf.constant([0.25, 0.25, 0.75, 0.75]) - boxes = box_list.BoxList(corners) - - expected_corners = tf.constant([[0, 0.5, 1.0, 1.0], [0.5, -0.5, 1.5, 1.5]]) - expected_boxes = box_list.BoxList(expected_corners) - output = box_list_ops.change_coordinate_frame(boxes, window) - - with self.test_session() as sess: - output_, expected_boxes_ = sess.run([output.get(), expected_boxes.get()]) - self.assertAllClose(output_, expected_boxes_) - - def test_ioaworks_on_empty_inputs(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - boxes_empty = box_list.BoxList(tf.zeros((0, 4))) - ioa_empty_1 = box_list_ops.ioa(boxes1, boxes_empty) - ioa_empty_2 = box_list_ops.ioa(boxes_empty, boxes2) - ioa_empty_3 = box_list_ops.ioa(boxes_empty, boxes_empty) - with self.test_session() as sess: - ioa_output_1, ioa_output_2, ioa_output_3 = sess.run( - [ioa_empty_1, ioa_empty_2, ioa_empty_3]) - self.assertAllEqual(ioa_output_1.shape, (2, 0)) - self.assertAllEqual(ioa_output_2.shape, (0, 3)) - self.assertAllEqual(ioa_output_3.shape, (0, 0)) - - def test_pairwise_distances(self): - corners1 = tf.constant([[0.0, 0.0, 0.0, 0.0], - [1.0, 1.0, 0.0, 2.0]]) - corners2 = tf.constant([[3.0, 4.0, 1.0, 0.0], - [-4.0, 0.0, 0.0, 3.0], - [0.0, 0.0, 0.0, 0.0]]) - exp_output = [[26, 25, 0], [18, 27, 6]] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - dist_matrix = box_list_ops.sq_dist(boxes1, boxes2) - with self.test_session() as sess: - dist_output = sess.run(dist_matrix) - self.assertAllClose(dist_output, exp_output) - - def test_boolean_mask(self): - corners = tf.constant( - [4 * [0.0], 4 * [1.0], 4 * [2.0], 4 * [3.0], 4 * [4.0]]) - indicator = tf.constant([True, False, True, False, True], tf.bool) - expected_subset = [4 * [0.0], 4 * [2.0], 4 * [4.0]] - boxes = box_list.BoxList(corners) - subset = box_list_ops.boolean_mask(boxes, indicator) - with self.test_session() as sess: - subset_output = sess.run(subset.get()) - self.assertAllClose(subset_output, expected_subset) - - def test_boolean_mask_with_field(self): - corners = tf.constant( - [4 * [0.0], 4 * [1.0], 4 * [2.0], 4 * [3.0], 4 * [4.0]]) - indicator = tf.constant([True, False, True, False, True], tf.bool) - weights = tf.constant([[.1], [.3], [.5], [.7], [.9]], tf.float32) - expected_subset = [4 * [0.0], 4 * [2.0], 4 * [4.0]] - expected_weights = [[.1], [.5], [.9]] - - boxes = box_list.BoxList(corners) - boxes.add_field('weights', weights) - subset = box_list_ops.boolean_mask(boxes, indicator, ['weights']) - with self.test_session() as sess: - subset_output, weights_output = sess.run( - [subset.get(), subset.get_field('weights')]) - self.assertAllClose(subset_output, expected_subset) - self.assertAllClose(weights_output, expected_weights) - - def test_gather(self): - corners = tf.constant( - [4 * [0.0], 4 * [1.0], 4 * [2.0], 4 * [3.0], 4 * [4.0]]) - indices = tf.constant([0, 2, 4], tf.int32) - expected_subset = [4 * [0.0], 4 * [2.0], 4 * [4.0]] - boxes = box_list.BoxList(corners) - subset = box_list_ops.gather(boxes, indices) - with self.test_session() as sess: - subset_output = sess.run(subset.get()) - self.assertAllClose(subset_output, expected_subset) - - def test_gather_with_field(self): - corners = tf.constant([4*[0.0], 4*[1.0], 4*[2.0], 4*[3.0], 4*[4.0]]) - indices = tf.constant([0, 2, 4], tf.int32) - weights = tf.constant([[.1], [.3], [.5], [.7], [.9]], tf.float32) - expected_subset = [4 * [0.0], 4 * [2.0], 4 * [4.0]] - expected_weights = [[.1], [.5], [.9]] - - boxes = box_list.BoxList(corners) - boxes.add_field('weights', weights) - subset = box_list_ops.gather(boxes, indices, ['weights']) - with self.test_session() as sess: - subset_output, weights_output = sess.run( - [subset.get(), subset.get_field('weights')]) - self.assertAllClose(subset_output, expected_subset) - self.assertAllClose(weights_output, expected_weights) - - def test_gather_with_invalid_field(self): - corners = tf.constant([4 * [0.0], 4 * [1.0]]) - indices = tf.constant([0, 1], tf.int32) - weights = tf.constant([[.1], [.3]], tf.float32) - - boxes = box_list.BoxList(corners) - boxes.add_field('weights', weights) - with self.assertRaises(ValueError): - box_list_ops.gather(boxes, indices, ['foo', 'bar']) - - def test_gather_with_invalid_inputs(self): - corners = tf.constant( - [4 * [0.0], 4 * [1.0], 4 * [2.0], 4 * [3.0], 4 * [4.0]]) - indices_float32 = tf.constant([0, 2, 4], tf.float32) - boxes = box_list.BoxList(corners) - with self.assertRaises(ValueError): - _ = box_list_ops.gather(boxes, indices_float32) - indices_2d = tf.constant([[0, 2, 4]], tf.int32) - boxes = box_list.BoxList(corners) - with self.assertRaises(ValueError): - _ = box_list_ops.gather(boxes, indices_2d) - - def test_gather_with_dynamic_indexing(self): - corners = tf.constant([4 * [0.0], 4 * [1.0], 4 * [2.0], 4 * [3.0], 4 * [4.0] - ]) - weights = tf.constant([.5, .3, .7, .1, .9], tf.float32) - indices = tf.reshape(tf.where(tf.greater(weights, 0.4)), [-1]) - expected_subset = [4 * [0.0], 4 * [2.0], 4 * [4.0]] - expected_weights = [.5, .7, .9] - - boxes = box_list.BoxList(corners) - boxes.add_field('weights', weights) - subset = box_list_ops.gather(boxes, indices, ['weights']) - with self.test_session() as sess: - subset_output, weights_output = sess.run([subset.get(), subset.get_field( - 'weights')]) - self.assertAllClose(subset_output, expected_subset) - self.assertAllClose(weights_output, expected_weights) - - def test_sort_by_field_ascending_order(self): - exp_corners = [[0, 0, 1, 1], [0, 0.1, 1, 1.1], [0, -0.1, 1, 0.9], - [0, 10, 1, 11], [0, 10.1, 1, 11.1], [0, 100, 1, 101]] - exp_scores = [.95, .9, .75, .6, .5, .3] - exp_weights = [.2, .45, .6, .75, .8, .92] - shuffle = [2, 4, 0, 5, 1, 3] - corners = tf.constant([exp_corners[i] for i in shuffle], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('scores', tf.constant( - [exp_scores[i] for i in shuffle], tf.float32)) - boxes.add_field('weights', tf.constant( - [exp_weights[i] for i in shuffle], tf.float32)) - sort_by_weight = box_list_ops.sort_by_field( - boxes, - 'weights', - order=box_list_ops.SortOrder.ascend) - with self.test_session() as sess: - corners_out, scores_out, weights_out = sess.run([ - sort_by_weight.get(), - sort_by_weight.get_field('scores'), - sort_by_weight.get_field('weights')]) - self.assertAllClose(corners_out, exp_corners) - self.assertAllClose(scores_out, exp_scores) - self.assertAllClose(weights_out, exp_weights) - - def test_sort_by_field_descending_order(self): - exp_corners = [[0, 0, 1, 1], [0, 0.1, 1, 1.1], [0, -0.1, 1, 0.9], - [0, 10, 1, 11], [0, 10.1, 1, 11.1], [0, 100, 1, 101]] - exp_scores = [.95, .9, .75, .6, .5, .3] - exp_weights = [.2, .45, .6, .75, .8, .92] - shuffle = [2, 4, 0, 5, 1, 3] - - corners = tf.constant([exp_corners[i] for i in shuffle], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('scores', tf.constant( - [exp_scores[i] for i in shuffle], tf.float32)) - boxes.add_field('weights', tf.constant( - [exp_weights[i] for i in shuffle], tf.float32)) - - sort_by_score = box_list_ops.sort_by_field(boxes, 'scores') - with self.test_session() as sess: - corners_out, scores_out, weights_out = sess.run([sort_by_score.get( - ), sort_by_score.get_field('scores'), sort_by_score.get_field('weights')]) - self.assertAllClose(corners_out, exp_corners) - self.assertAllClose(scores_out, exp_scores) - self.assertAllClose(weights_out, exp_weights) - - def test_sort_by_field_invalid_inputs(self): - corners = tf.constant([4 * [0.0], 4 * [0.5], 4 * [1.0], 4 * [2.0], 4 * - [3.0], 4 * [4.0]]) - misc = tf.constant([[.95, .9], [.5, .3]], tf.float32) - weights = tf.constant([.1, .2], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('misc', misc) - boxes.add_field('weights', weights) - - with self.test_session() as sess: - with self.assertRaises(ValueError): - box_list_ops.sort_by_field(boxes, 'area') - - with self.assertRaises(ValueError): - box_list_ops.sort_by_field(boxes, 'misc') - - if ops._USE_C_API: - with self.assertRaises(ValueError): - box_list_ops.sort_by_field(boxes, 'weights') - else: - with self.assertRaisesWithPredicateMatch(errors.InvalidArgumentError, - 'Incorrect field size'): - sess.run(box_list_ops.sort_by_field(boxes, 'weights').get()) - - def test_visualize_boxes_in_image(self): - image = tf.zeros((6, 4, 3)) - corners = tf.constant([[0, 0, 5, 3], - [0, 0, 3, 2]], tf.float32) - boxes = box_list.BoxList(corners) - image_and_boxes = box_list_ops.visualize_boxes_in_image(image, boxes) - image_and_boxes_bw = tf.to_float( - tf.greater(tf.reduce_sum(image_and_boxes, 2), 0.0)) - exp_result = [[1, 1, 1, 0], - [1, 1, 1, 0], - [1, 1, 1, 0], - [1, 0, 1, 0], - [1, 1, 1, 0], - [0, 0, 0, 0]] - with self.test_session() as sess: - output = sess.run(image_and_boxes_bw) - self.assertAllEqual(output.astype(int), exp_result) - - def test_filter_field_value_equals(self): - corners = tf.constant([[0, 0, 1, 1], - [0, 0.1, 1, 1.1], - [0, -0.1, 1, 0.9], - [0, 10, 1, 11], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101]], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('classes', tf.constant([1, 2, 1, 2, 2, 1])) - exp_output1 = [[0, 0, 1, 1], [0, -0.1, 1, 0.9], [0, 100, 1, 101]] - exp_output2 = [[0, 0.1, 1, 1.1], [0, 10, 1, 11], [0, 10.1, 1, 11.1]] - - filtered_boxes1 = box_list_ops.filter_field_value_equals( - boxes, 'classes', 1) - filtered_boxes2 = box_list_ops.filter_field_value_equals( - boxes, 'classes', 2) - with self.test_session() as sess: - filtered_output1, filtered_output2 = sess.run([filtered_boxes1.get(), - filtered_boxes2.get()]) - self.assertAllClose(filtered_output1, exp_output1) - self.assertAllClose(filtered_output2, exp_output2) - - def test_filter_greater_than(self): - corners = tf.constant([[0, 0, 1, 1], - [0, 0.1, 1, 1.1], - [0, -0.1, 1, 0.9], - [0, 10, 1, 11], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101]], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('scores', tf.constant([.1, .75, .9, .5, .5, .8])) - thresh = .6 - exp_output = [[0, 0.1, 1, 1.1], [0, -0.1, 1, 0.9], [0, 100, 1, 101]] - - filtered_boxes = box_list_ops.filter_greater_than(boxes, thresh) - with self.test_session() as sess: - filtered_output = sess.run(filtered_boxes.get()) - self.assertAllClose(filtered_output, exp_output) - - def test_clip_box_list(self): - boxlist = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5], - [0.6, 0.6, 0.8, 0.8], [0.2, 0.2, 0.3, 0.3]], tf.float32)) - boxlist.add_field('classes', tf.constant([0, 0, 1, 1])) - boxlist.add_field('scores', tf.constant([0.75, 0.65, 0.3, 0.2])) - num_boxes = 2 - clipped_boxlist = box_list_ops.pad_or_clip_box_list(boxlist, num_boxes) - - expected_boxes = [[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5]] - expected_classes = [0, 0] - expected_scores = [0.75, 0.65] - with self.test_session() as sess: - boxes_out, classes_out, scores_out = sess.run( - [clipped_boxlist.get(), clipped_boxlist.get_field('classes'), - clipped_boxlist.get_field('scores')]) - - self.assertAllClose(expected_boxes, boxes_out) - self.assertAllEqual(expected_classes, classes_out) - self.assertAllClose(expected_scores, scores_out) - - def test_pad_box_list(self): - boxlist = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5]], tf.float32)) - boxlist.add_field('classes', tf.constant([0, 1])) - boxlist.add_field('scores', tf.constant([0.75, 0.2])) - num_boxes = 4 - padded_boxlist = box_list_ops.pad_or_clip_box_list(boxlist, num_boxes) - - expected_boxes = [[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5], - [0, 0, 0, 0], [0, 0, 0, 0]] - expected_classes = [0, 1, 0, 0] - expected_scores = [0.75, 0.2, 0, 0] - with self.test_session() as sess: - boxes_out, classes_out, scores_out = sess.run( - [padded_boxlist.get(), padded_boxlist.get_field('classes'), - padded_boxlist.get_field('scores')]) - - self.assertAllClose(expected_boxes, boxes_out) - self.assertAllEqual(expected_classes, classes_out) - self.assertAllClose(expected_scores, scores_out) - - def test_select_random_box(self): - boxes = [[0., 0., 1., 1.], - [0., 1., 2., 3.], - [0., 2., 3., 4.]] - - corners = tf.constant(boxes, dtype=tf.float32) - boxlist = box_list.BoxList(corners) - random_bbox, valid = box_list_ops.select_random_box(boxlist) - with self.test_session() as sess: - random_bbox_out, valid_out = sess.run([random_bbox, valid]) - - norm_small = any( - [np.linalg.norm(random_bbox_out - box) < 1e-6 for box in boxes]) - - self.assertTrue(norm_small) - self.assertTrue(valid_out) - - def test_select_random_box_with_empty_boxlist(self): - corners = tf.constant([], shape=[0, 4], dtype=tf.float32) - boxlist = box_list.BoxList(corners) - random_bbox, valid = box_list_ops.select_random_box(boxlist) - with self.test_session() as sess: - random_bbox_out, valid_out = sess.run([random_bbox, valid]) - - expected_bbox_out = np.array([[-1., -1., -1., -1.]], dtype=np.float32) - self.assertAllEqual(expected_bbox_out, random_bbox_out) - self.assertFalse(valid_out) - - def test_get_minimal_coverage_box(self): - boxes = [[0., 0., 1., 1.], - [-1., 1., 2., 3.], - [0., 2., 3., 4.]] - - expected_coverage_box = [[-1., 0., 3., 4.]] - - corners = tf.constant(boxes, dtype=tf.float32) - boxlist = box_list.BoxList(corners) - coverage_box = box_list_ops.get_minimal_coverage_box(boxlist) - with self.test_session() as sess: - coverage_box_out = sess.run(coverage_box) - - self.assertAllClose(expected_coverage_box, coverage_box_out) - - def test_get_minimal_coverage_box_with_empty_boxlist(self): - corners = tf.constant([], shape=[0, 4], dtype=tf.float32) - boxlist = box_list.BoxList(corners) - coverage_box = box_list_ops.get_minimal_coverage_box(boxlist) - with self.test_session() as sess: - coverage_box_out = sess.run(coverage_box) - - self.assertAllClose([[0.0, 0.0, 1.0, 1.0]], coverage_box_out) - - -class ConcatenateTest(tf.test.TestCase): - - def test_invalid_input_box_list_list(self): - with self.assertRaises(ValueError): - box_list_ops.concatenate(None) - with self.assertRaises(ValueError): - box_list_ops.concatenate([]) - with self.assertRaises(ValueError): - corners = tf.constant([[0, 0, 0, 0]], tf.float32) - boxlist = box_list.BoxList(corners) - box_list_ops.concatenate([boxlist, 2]) - - def test_concatenate_with_missing_fields(self): - corners1 = tf.constant([[0, 0, 0, 0], [1, 2, 3, 4]], tf.float32) - scores1 = tf.constant([1.0, 2.1]) - corners2 = tf.constant([[0, 3, 1, 6], [2, 4, 3, 8]], tf.float32) - boxlist1 = box_list.BoxList(corners1) - boxlist1.add_field('scores', scores1) - boxlist2 = box_list.BoxList(corners2) - with self.assertRaises(ValueError): - box_list_ops.concatenate([boxlist1, boxlist2]) - - def test_concatenate_with_incompatible_field_shapes(self): - corners1 = tf.constant([[0, 0, 0, 0], [1, 2, 3, 4]], tf.float32) - scores1 = tf.constant([1.0, 2.1]) - corners2 = tf.constant([[0, 3, 1, 6], [2, 4, 3, 8]], tf.float32) - scores2 = tf.constant([[1.0, 1.0], [2.1, 3.2]]) - boxlist1 = box_list.BoxList(corners1) - boxlist1.add_field('scores', scores1) - boxlist2 = box_list.BoxList(corners2) - boxlist2.add_field('scores', scores2) - with self.assertRaises(ValueError): - box_list_ops.concatenate([boxlist1, boxlist2]) - - def test_concatenate_is_correct(self): - corners1 = tf.constant([[0, 0, 0, 0], [1, 2, 3, 4]], tf.float32) - scores1 = tf.constant([1.0, 2.1]) - corners2 = tf.constant([[0, 3, 1, 6], [2, 4, 3, 8], [1, 0, 5, 10]], - tf.float32) - scores2 = tf.constant([1.0, 2.1, 5.6]) - - exp_corners = [[0, 0, 0, 0], - [1, 2, 3, 4], - [0, 3, 1, 6], - [2, 4, 3, 8], - [1, 0, 5, 10]] - exp_scores = [1.0, 2.1, 1.0, 2.1, 5.6] - - boxlist1 = box_list.BoxList(corners1) - boxlist1.add_field('scores', scores1) - boxlist2 = box_list.BoxList(corners2) - boxlist2.add_field('scores', scores2) - result = box_list_ops.concatenate([boxlist1, boxlist2]) - with self.test_session() as sess: - corners_output, scores_output = sess.run( - [result.get(), result.get_field('scores')]) - self.assertAllClose(corners_output, exp_corners) - self.assertAllClose(scores_output, exp_scores) - - -class NonMaxSuppressionTest(tf.test.TestCase): - - def test_select_from_three_clusters(self): - corners = tf.constant([[0, 0, 1, 1], - [0, 0.1, 1, 1.1], - [0, -0.1, 1, 0.9], - [0, 10, 1, 11], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101]], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('scores', tf.constant([.9, .75, .6, .95, .5, .3])) - iou_thresh = .5 - max_output_size = 3 - - exp_nms = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 100, 1, 101]] - nms = box_list_ops.non_max_suppression( - boxes, iou_thresh, max_output_size) - with self.test_session() as sess: - nms_output = sess.run(nms.get()) - self.assertAllClose(nms_output, exp_nms) - - def test_select_at_most_two_boxes_from_three_clusters(self): - corners = tf.constant([[0, 0, 1, 1], - [0, 0.1, 1, 1.1], - [0, -0.1, 1, 0.9], - [0, 10, 1, 11], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101]], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('scores', tf.constant([.9, .75, .6, .95, .5, .3])) - iou_thresh = .5 - max_output_size = 2 - - exp_nms = [[0, 10, 1, 11], - [0, 0, 1, 1]] - nms = box_list_ops.non_max_suppression( - boxes, iou_thresh, max_output_size) - with self.test_session() as sess: - nms_output = sess.run(nms.get()) - self.assertAllClose(nms_output, exp_nms) - - def test_select_at_most_thirty_boxes_from_three_clusters(self): - corners = tf.constant([[0, 0, 1, 1], - [0, 0.1, 1, 1.1], - [0, -0.1, 1, 0.9], - [0, 10, 1, 11], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101]], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('scores', tf.constant([.9, .75, .6, .95, .5, .3])) - iou_thresh = .5 - max_output_size = 30 - - exp_nms = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 100, 1, 101]] - nms = box_list_ops.non_max_suppression( - boxes, iou_thresh, max_output_size) - with self.test_session() as sess: - nms_output = sess.run(nms.get()) - self.assertAllClose(nms_output, exp_nms) - - def test_select_single_box(self): - corners = tf.constant([[0, 0, 1, 1]], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('scores', tf.constant([.9])) - iou_thresh = .5 - max_output_size = 3 - - exp_nms = [[0, 0, 1, 1]] - nms = box_list_ops.non_max_suppression( - boxes, iou_thresh, max_output_size) - with self.test_session() as sess: - nms_output = sess.run(nms.get()) - self.assertAllClose(nms_output, exp_nms) - - def test_select_from_ten_identical_boxes(self): - corners = tf.constant(10 * [[0, 0, 1, 1]], tf.float32) - boxes = box_list.BoxList(corners) - boxes.add_field('scores', tf.constant(10 * [.9])) - iou_thresh = .5 - max_output_size = 3 - - exp_nms = [[0, 0, 1, 1]] - nms = box_list_ops.non_max_suppression( - boxes, iou_thresh, max_output_size) - with self.test_session() as sess: - nms_output = sess.run(nms.get()) - self.assertAllClose(nms_output, exp_nms) - - def test_copy_extra_fields(self): - corners = tf.constant([[0, 0, 1, 1], - [0, 0.1, 1, 1.1]], tf.float32) - boxes = box_list.BoxList(corners) - tensor1 = np.array([[1], [4]]) - tensor2 = np.array([[1, 1], [2, 2]]) - boxes.add_field('tensor1', tf.constant(tensor1)) - boxes.add_field('tensor2', tf.constant(tensor2)) - new_boxes = box_list.BoxList(tf.constant([[0, 0, 10, 10], - [1, 3, 5, 5]], tf.float32)) - new_boxes = box_list_ops._copy_extra_fields(new_boxes, boxes) - with self.test_session() as sess: - self.assertAllClose(tensor1, sess.run(new_boxes.get_field('tensor1'))) - self.assertAllClose(tensor2, sess.run(new_boxes.get_field('tensor2'))) - - -class CoordinatesConversionTest(tf.test.TestCase): - - def test_to_normalized_coordinates(self): - coordinates = tf.constant([[0, 0, 100, 100], - [25, 25, 75, 75]], tf.float32) - img = tf.ones((128, 100, 100, 3)) - boxlist = box_list.BoxList(coordinates) - normalized_boxlist = box_list_ops.to_normalized_coordinates( - boxlist, tf.shape(img)[1], tf.shape(img)[2]) - expected_boxes = [[0, 0, 1, 1], - [0.25, 0.25, 0.75, 0.75]] - - with self.test_session() as sess: - normalized_boxes = sess.run(normalized_boxlist.get()) - self.assertAllClose(normalized_boxes, expected_boxes) - - def test_to_normalized_coordinates_already_normalized(self): - coordinates = tf.constant([[0, 0, 1, 1], - [0.25, 0.25, 0.75, 0.75]], tf.float32) - img = tf.ones((128, 100, 100, 3)) - boxlist = box_list.BoxList(coordinates) - normalized_boxlist = box_list_ops.to_normalized_coordinates( - boxlist, tf.shape(img)[1], tf.shape(img)[2]) - - with self.test_session() as sess: - with self.assertRaisesOpError('assertion failed'): - sess.run(normalized_boxlist.get()) - - def test_to_absolute_coordinates(self): - coordinates = tf.constant([[0, 0, 1, 1], - [0.25, 0.25, 0.75, 0.75]], tf.float32) - img = tf.ones((128, 100, 100, 3)) - boxlist = box_list.BoxList(coordinates) - absolute_boxlist = box_list_ops.to_absolute_coordinates(boxlist, - tf.shape(img)[1], - tf.shape(img)[2]) - expected_boxes = [[0, 0, 100, 100], - [25, 25, 75, 75]] - - with self.test_session() as sess: - absolute_boxes = sess.run(absolute_boxlist.get()) - self.assertAllClose(absolute_boxes, expected_boxes) - - def test_to_absolute_coordinates_already_abolute(self): - coordinates = tf.constant([[0, 0, 100, 100], - [25, 25, 75, 75]], tf.float32) - img = tf.ones((128, 100, 100, 3)) - boxlist = box_list.BoxList(coordinates) - absolute_boxlist = box_list_ops.to_absolute_coordinates(boxlist, - tf.shape(img)[1], - tf.shape(img)[2]) - - with self.test_session() as sess: - with self.assertRaisesOpError('assertion failed'): - sess.run(absolute_boxlist.get()) - - def test_convert_to_normalized_and_back(self): - coordinates = np.random.uniform(size=(100, 4)) - coordinates = np.round(np.sort(coordinates) * 200) - coordinates[:, 2:4] += 1 - coordinates[99, :] = [0, 0, 201, 201] - img = tf.ones((128, 202, 202, 3)) - - boxlist = box_list.BoxList(tf.constant(coordinates, tf.float32)) - boxlist = box_list_ops.to_normalized_coordinates(boxlist, - tf.shape(img)[1], - tf.shape(img)[2]) - boxlist = box_list_ops.to_absolute_coordinates(boxlist, - tf.shape(img)[1], - tf.shape(img)[2]) - - with self.test_session() as sess: - out = sess.run(boxlist.get()) - self.assertAllClose(out, coordinates) - - def test_convert_to_absolute_and_back(self): - coordinates = np.random.uniform(size=(100, 4)) - coordinates = np.sort(coordinates) - coordinates[99, :] = [0, 0, 1, 1] - img = tf.ones((128, 202, 202, 3)) - - boxlist = box_list.BoxList(tf.constant(coordinates, tf.float32)) - boxlist = box_list_ops.to_absolute_coordinates(boxlist, - tf.shape(img)[1], - tf.shape(img)[2]) - boxlist = box_list_ops.to_normalized_coordinates(boxlist, - tf.shape(img)[1], - tf.shape(img)[2]) - - with self.test_session() as sess: - out = sess.run(boxlist.get()) - self.assertAllClose(out, coordinates) - - def test_to_absolute_coordinates_maximum_coordinate_check(self): - coordinates = tf.constant([[0, 0, 1.2, 1.2], - [0.25, 0.25, 0.75, 0.75]], tf.float32) - img = tf.ones((128, 100, 100, 3)) - boxlist = box_list.BoxList(coordinates) - absolute_boxlist = box_list_ops.to_absolute_coordinates( - boxlist, - tf.shape(img)[1], - tf.shape(img)[2], - maximum_normalized_coordinate=1.1) - - with self.test_session() as sess: - with self.assertRaisesOpError('assertion failed'): - sess.run(absolute_boxlist.get()) - - -class BoxRefinementTest(tf.test.TestCase): - - def test_box_voting(self): - candidates = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.6, 0.6, 0.8, 0.8]], tf.float32)) - candidates.add_field('ExtraField', tf.constant([1, 2])) - pool = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5], - [0.6, 0.6, 0.8, 0.8]], tf.float32)) - pool.add_field('scores', tf.constant([0.75, 0.25, 0.3])) - averaged_boxes = box_list_ops.box_voting(candidates, pool) - expected_boxes = [[0.1, 0.1, 0.425, 0.425], [0.6, 0.6, 0.8, 0.8]] - expected_scores = [0.5, 0.3] - with self.test_session() as sess: - boxes_out, scores_out, extra_field_out = sess.run( - [averaged_boxes.get(), averaged_boxes.get_field('scores'), - averaged_boxes.get_field('ExtraField')]) - - self.assertAllClose(expected_boxes, boxes_out) - self.assertAllClose(expected_scores, scores_out) - self.assertAllEqual(extra_field_out, [1, 2]) - - def test_box_voting_fails_with_negative_scores(self): - candidates = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4]], tf.float32)) - pool = box_list.BoxList(tf.constant([[0.1, 0.1, 0.4, 0.4]], tf.float32)) - pool.add_field('scores', tf.constant([-0.2])) - averaged_boxes = box_list_ops.box_voting(candidates, pool) - - with self.test_session() as sess: - with self.assertRaisesOpError('Scores must be non negative'): - sess.run([averaged_boxes.get()]) - - def test_box_voting_fails_when_unmatched(self): - candidates = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4]], tf.float32)) - pool = box_list.BoxList(tf.constant([[0.6, 0.6, 0.8, 0.8]], tf.float32)) - pool.add_field('scores', tf.constant([0.2])) - averaged_boxes = box_list_ops.box_voting(candidates, pool) - - with self.test_session() as sess: - with self.assertRaisesOpError('Each box in selected_boxes must match ' - 'with at least one box in pool_boxes.'): - sess.run([averaged_boxes.get()]) - - def test_refine_boxes(self): - pool = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5], - [0.6, 0.6, 0.8, 0.8]], tf.float32)) - pool.add_field('ExtraField', tf.constant([1, 2, 3])) - pool.add_field('scores', tf.constant([0.75, 0.25, 0.3])) - refined_boxes = box_list_ops.refine_boxes(pool, 0.5, 10) - - expected_boxes = [[0.1, 0.1, 0.425, 0.425], [0.6, 0.6, 0.8, 0.8]] - expected_scores = [0.5, 0.3] - with self.test_session() as sess: - boxes_out, scores_out, extra_field_out = sess.run( - [refined_boxes.get(), refined_boxes.get_field('scores'), - refined_boxes.get_field('ExtraField')]) - - self.assertAllClose(expected_boxes, boxes_out) - self.assertAllClose(expected_scores, scores_out) - self.assertAllEqual(extra_field_out, [1, 3]) - - def test_refine_boxes_multi_class(self): - pool = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5], - [0.6, 0.6, 0.8, 0.8], [0.2, 0.2, 0.3, 0.3]], tf.float32)) - pool.add_field('classes', tf.constant([0, 0, 1, 1])) - pool.add_field('scores', tf.constant([0.75, 0.25, 0.3, 0.2])) - refined_boxes = box_list_ops.refine_boxes_multi_class(pool, 3, 0.5, 10) - - expected_boxes = [[0.1, 0.1, 0.425, 0.425], [0.6, 0.6, 0.8, 0.8], - [0.2, 0.2, 0.3, 0.3]] - expected_scores = [0.5, 0.3, 0.2] - with self.test_session() as sess: - boxes_out, scores_out, extra_field_out = sess.run( - [refined_boxes.get(), refined_boxes.get_field('scores'), - refined_boxes.get_field('classes')]) - - self.assertAllClose(expected_boxes, boxes_out) - self.assertAllClose(expected_scores, scores_out) - self.assertAllEqual(extra_field_out, [0, 1, 1]) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_test.py deleted file mode 100644 index edc00ebbc..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_list_test.py +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.box_list.""" - -import tensorflow as tf - -from object_detection.core import box_list - - -class BoxListTest(tf.test.TestCase): - """Tests for BoxList class.""" - - def test_num_boxes(self): - data = tf.constant([[0, 0, 1, 1], [1, 1, 2, 3], [3, 4, 5, 5]], tf.float32) - expected_num_boxes = 3 - - boxes = box_list.BoxList(data) - with self.test_session() as sess: - num_boxes_output = sess.run(boxes.num_boxes()) - self.assertEquals(num_boxes_output, expected_num_boxes) - - def test_get_correct_center_coordinates_and_sizes(self): - boxes = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - boxes = box_list.BoxList(tf.constant(boxes)) - centers_sizes = boxes.get_center_coordinates_and_sizes() - expected_centers_sizes = [[15, 0.35], [12.5, 0.25], [10, 0.3], [5, 0.3]] - with self.test_session() as sess: - centers_sizes_out = sess.run(centers_sizes) - self.assertAllClose(centers_sizes_out, expected_centers_sizes) - - def test_create_box_list_with_dynamic_shape(self): - data = tf.constant([[0, 0, 1, 1], [1, 1, 2, 3], [3, 4, 5, 5]], tf.float32) - indices = tf.reshape(tf.where(tf.greater([1, 0, 1], 0)), [-1]) - data = tf.gather(data, indices) - assert data.get_shape().as_list() == [None, 4] - expected_num_boxes = 2 - - boxes = box_list.BoxList(data) - with self.test_session() as sess: - num_boxes_output = sess.run(boxes.num_boxes()) - self.assertEquals(num_boxes_output, expected_num_boxes) - - def test_transpose_coordinates(self): - boxes = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - boxes = box_list.BoxList(tf.constant(boxes)) - boxes.transpose_coordinates() - expected_corners = [[10.0, 10.0, 15.0, 20.0], [0.1, 0.2, 0.4, 0.5]] - with self.test_session() as sess: - corners_out = sess.run(boxes.get()) - self.assertAllClose(corners_out, expected_corners) - - def test_box_list_invalid_inputs(self): - data0 = tf.constant([[[0, 0, 1, 1], [3, 4, 5, 5]]], tf.float32) - data1 = tf.constant([[0, 0, 1], [1, 1, 2], [3, 4, 5]], tf.float32) - data2 = tf.constant([[0, 0, 1], [1, 1, 2], [3, 4, 5]], tf.int32) - - with self.assertRaises(ValueError): - _ = box_list.BoxList(data0) - with self.assertRaises(ValueError): - _ = box_list.BoxList(data1) - with self.assertRaises(ValueError): - _ = box_list.BoxList(data2) - - def test_num_boxes_static(self): - box_corners = [[10.0, 10.0, 20.0, 15.0], [0.2, 0.1, 0.5, 0.4]] - boxes = box_list.BoxList(tf.constant(box_corners)) - self.assertEquals(boxes.num_boxes_static(), 2) - self.assertEquals(type(boxes.num_boxes_static()), int) - - def test_num_boxes_static_for_uninferrable_shape(self): - placeholder = tf.placeholder(tf.float32, shape=[None, 4]) - boxes = box_list.BoxList(placeholder) - self.assertEquals(boxes.num_boxes_static(), None) - - def test_as_tensor_dict(self): - boxlist = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5]], tf.float32)) - boxlist.add_field('classes', tf.constant([0, 1])) - boxlist.add_field('scores', tf.constant([0.75, 0.2])) - tensor_dict = boxlist.as_tensor_dict() - - expected_boxes = [[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5]] - expected_classes = [0, 1] - expected_scores = [0.75, 0.2] - - with self.test_session() as sess: - tensor_dict_out = sess.run(tensor_dict) - self.assertAllEqual(3, len(tensor_dict_out)) - self.assertAllClose(expected_boxes, tensor_dict_out['boxes']) - self.assertAllEqual(expected_classes, tensor_dict_out['classes']) - self.assertAllClose(expected_scores, tensor_dict_out['scores']) - - def test_as_tensor_dict_with_features(self): - boxlist = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5]], tf.float32)) - boxlist.add_field('classes', tf.constant([0, 1])) - boxlist.add_field('scores', tf.constant([0.75, 0.2])) - tensor_dict = boxlist.as_tensor_dict(['boxes', 'classes', 'scores']) - - expected_boxes = [[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5]] - expected_classes = [0, 1] - expected_scores = [0.75, 0.2] - - with self.test_session() as sess: - tensor_dict_out = sess.run(tensor_dict) - self.assertAllEqual(3, len(tensor_dict_out)) - self.assertAllClose(expected_boxes, tensor_dict_out['boxes']) - self.assertAllEqual(expected_classes, tensor_dict_out['classes']) - self.assertAllClose(expected_scores, tensor_dict_out['scores']) - - def test_as_tensor_dict_missing_field(self): - boxlist = box_list.BoxList( - tf.constant([[0.1, 0.1, 0.4, 0.4], [0.1, 0.1, 0.5, 0.5]], tf.float32)) - boxlist.add_field('classes', tf.constant([0, 1])) - boxlist.add_field('scores', tf.constant([0.75, 0.2])) - with self.assertRaises(ValueError): - boxlist.as_tensor_dict(['foo', 'bar']) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_predictor.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_predictor.py deleted file mode 100644 index 78d824237..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_predictor.py +++ /dev/null @@ -1,963 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Box predictor for object detectors. - -Box predictors are classes that take a high level -image feature map as input and produce two predictions, -(1) a tensor encoding box locations, and -(2) a tensor encoding classes for each box. - -These components are passed directly to loss functions -in our detection models. - -These modules are separated from the main model since the same -few box predictor architectures are shared across many models. -""" -from abc import abstractmethod -import math -import tensorflow as tf -from object_detection.utils import ops -from object_detection.utils import shape_utils -from object_detection.utils import static_shape - -slim = tf.contrib.slim - -BOX_ENCODINGS = 'box_encodings' -CLASS_PREDICTIONS_WITH_BACKGROUND = 'class_predictions_with_background' -MASK_PREDICTIONS = 'mask_predictions' - - -class BoxPredictor(object): - """BoxPredictor.""" - - def __init__(self, is_training, num_classes): - """Constructor. - - Args: - is_training: Indicates whether the BoxPredictor is in training mode. - num_classes: number of classes. Note that num_classes *does not* - include the background category, so if groundtruth labels take values - in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the - assigned classification targets can range from {0,... K}). - """ - self._is_training = is_training - self._num_classes = num_classes - - @property - def num_classes(self): - return self._num_classes - - def predict(self, image_features, num_predictions_per_location, - scope=None, **params): - """Computes encoded object locations and corresponding confidences. - - Takes a list of high level image feature maps as input and produces a list - of box encodings and a list of class scores where each element in the output - lists correspond to the feature maps in the input list. - - Args: - image_features: A list of float tensors of shape [batch_size, height_i, - width_i, channels_i] containing features for a batch of images. - num_predictions_per_location: A list of integers representing the number - of box predictions to be made per spatial location for each feature map. - scope: Variable and Op scope name. - **params: Additional keyword arguments for specific implementations of - BoxPredictor. - - Returns: - A dictionary containing at least the following tensors. - box_encodings: A list of float tensors. Each entry in the list - corresponds to a feature map in the input `image_features` list. All - tensors in the list have one of the two following shapes: - a. [batch_size, num_anchors_i, q, code_size] representing the location - of the objects, where q is 1 or the number of classes. - b. [batch_size, num_anchors_i, code_size]. - class_predictions_with_background: A list of float tensors of shape - [batch_size, num_anchors_i, num_classes + 1] representing the class - predictions for the proposals. Each entry in the list corresponds to a - feature map in the input `image_features` list. - - Raises: - ValueError: If length of `image_features` is not equal to length of - `num_predictions_per_location`. - """ - if len(image_features) != len(num_predictions_per_location): - raise ValueError('image_feature and num_predictions_per_location must ' - 'be of same length, found: {} vs {}'. - format(len(image_features), - len(num_predictions_per_location))) - if scope is not None: - with tf.variable_scope(scope): - return self._predict(image_features, num_predictions_per_location, - **params) - return self._predict(image_features, num_predictions_per_location, - **params) - - # TODO(rathodv): num_predictions_per_location could be moved to constructor. - # This is currently only used by ConvolutionalBoxPredictor. - @abstractmethod - def _predict(self, image_features, num_predictions_per_location, **params): - """Implementations must override this method. - - Args: - image_features: A list of float tensors of shape [batch_size, height_i, - width_i, channels_i] containing features for a batch of images. - num_predictions_per_location: A list of integers representing the number - of box predictions to be made per spatial location for each feature map. - **params: Additional keyword arguments for specific implementations of - BoxPredictor. - - Returns: - A dictionary containing at least the following tensors. - box_encodings: A list of float tensors. Each entry in the list - corresponds to a feature map in the input `image_features` list. All - tensors in the list have one of the two following shapes: - a. [batch_size, num_anchors_i, q, code_size] representing the location - of the objects, where q is 1 or the number of classes. - b. [batch_size, num_anchors_i, code_size]. - class_predictions_with_background: A list of float tensors of shape - [batch_size, num_anchors_i, num_classes + 1] representing the class - predictions for the proposals. Each entry in the list corresponds to a - feature map in the input `image_features` list. - """ - pass - - -class RfcnBoxPredictor(BoxPredictor): - """RFCN Box Predictor. - - Applies a position sensitive ROI pooling on position sensitive feature maps to - predict classes and refined locations. See https://arxiv.org/abs/1605.06409 - for details. - - This is used for the second stage of the RFCN meta architecture. Notice that - locations are *not* shared across classes, thus for each anchor, a separate - prediction is made for each class. - """ - - def __init__(self, - is_training, - num_classes, - conv_hyperparams_fn, - num_spatial_bins, - depth, - crop_size, - box_code_size): - """Constructor. - - Args: - is_training: Indicates whether the BoxPredictor is in training mode. - num_classes: number of classes. Note that num_classes *does not* - include the background category, so if groundtruth labels take values - in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the - assigned classification targets can range from {0,... K}). - conv_hyperparams_fn: A function to construct tf-slim arg_scope with - hyperparameters for convolutional layers. - num_spatial_bins: A list of two integers `[spatial_bins_y, - spatial_bins_x]`. - depth: Target depth to reduce the input feature maps to. - crop_size: A list of two integers `[crop_height, crop_width]`. - box_code_size: Size of encoding for each box. - """ - super(RfcnBoxPredictor, self).__init__(is_training, num_classes) - self._conv_hyperparams_fn = conv_hyperparams_fn - self._num_spatial_bins = num_spatial_bins - self._depth = depth - self._crop_size = crop_size - self._box_code_size = box_code_size - - @property - def num_classes(self): - return self._num_classes - - def _predict(self, image_features, num_predictions_per_location, - proposal_boxes): - """Computes encoded object locations and corresponding confidences. - - Args: - image_features: A list of float tensors of shape [batch_size, height_i, - width_i, channels_i] containing features for a batch of images. - num_predictions_per_location: A list of integers representing the number - of box predictions to be made per spatial location for each feature map. - Currently, this must be set to [1], or an error will be raised. - proposal_boxes: A float tensor of shape [batch_size, num_proposals, - box_code_size]. - - Returns: - box_encodings: A list of float tensors of shape - [batch_size, num_anchors_i, q, code_size] representing the location of - the objects, where q is 1 or the number of classes. Each entry in the - list corresponds to a feature map in the input `image_features` list. - class_predictions_with_background: A list of float tensors of shape - [batch_size, num_anchors_i, num_classes + 1] representing the class - predictions for the proposals. Each entry in the list corresponds to a - feature map in the input `image_features` list. - - Raises: - ValueError: if num_predictions_per_location is not 1 or if - len(image_features) is not 1. - """ - if (len(num_predictions_per_location) != 1 or - num_predictions_per_location[0] != 1): - raise ValueError('Currently RfcnBoxPredictor only supports ' - 'predicting a single box per class per location.') - if len(image_features) != 1: - raise ValueError('length of `image_features` must be 1. Found {}'. - format(len(image_features))) - image_feature = image_features[0] - num_predictions_per_location = num_predictions_per_location[0] - batch_size = tf.shape(proposal_boxes)[0] - num_boxes = tf.shape(proposal_boxes)[1] - def get_box_indices(proposals): - proposals_shape = proposals.get_shape().as_list() - if any(dim is None for dim in proposals_shape): - proposals_shape = tf.shape(proposals) - ones_mat = tf.ones(proposals_shape[:2], dtype=tf.int32) - multiplier = tf.expand_dims( - tf.range(start=0, limit=proposals_shape[0]), 1) - return tf.reshape(ones_mat * multiplier, [-1]) - - net = image_feature - with slim.arg_scope(self._conv_hyperparams_fn()): - net = slim.conv2d(net, self._depth, [1, 1], scope='reduce_depth') - # Location predictions. - location_feature_map_depth = (self._num_spatial_bins[0] * - self._num_spatial_bins[1] * - self.num_classes * - self._box_code_size) - location_feature_map = slim.conv2d(net, location_feature_map_depth, - [1, 1], activation_fn=None, - scope='refined_locations') - box_encodings = ops.position_sensitive_crop_regions( - location_feature_map, - boxes=tf.reshape(proposal_boxes, [-1, self._box_code_size]), - box_ind=get_box_indices(proposal_boxes), - crop_size=self._crop_size, - num_spatial_bins=self._num_spatial_bins, - global_pool=True) - box_encodings = tf.squeeze(box_encodings, squeeze_dims=[1, 2]) - box_encodings = tf.reshape(box_encodings, - [batch_size * num_boxes, 1, self.num_classes, - self._box_code_size]) - - # Class predictions. - total_classes = self.num_classes + 1 # Account for background class. - class_feature_map_depth = (self._num_spatial_bins[0] * - self._num_spatial_bins[1] * - total_classes) - class_feature_map = slim.conv2d(net, class_feature_map_depth, [1, 1], - activation_fn=None, - scope='class_predictions') - class_predictions_with_background = ops.position_sensitive_crop_regions( - class_feature_map, - boxes=tf.reshape(proposal_boxes, [-1, self._box_code_size]), - box_ind=get_box_indices(proposal_boxes), - crop_size=self._crop_size, - num_spatial_bins=self._num_spatial_bins, - global_pool=True) - class_predictions_with_background = tf.squeeze( - class_predictions_with_background, squeeze_dims=[1, 2]) - class_predictions_with_background = tf.reshape( - class_predictions_with_background, - [batch_size * num_boxes, 1, total_classes]) - - return {BOX_ENCODINGS: [box_encodings], - CLASS_PREDICTIONS_WITH_BACKGROUND: - [class_predictions_with_background]} - - -# TODO(rathodv): Change the implementation to return lists of predictions. -class MaskRCNNBoxPredictor(BoxPredictor): - """Mask R-CNN Box Predictor. - - See Mask R-CNN: He, K., Gkioxari, G., Dollar, P., & Girshick, R. (2017). - Mask R-CNN. arXiv preprint arXiv:1703.06870. - - This is used for the second stage of the Mask R-CNN detector where proposals - cropped from an image are arranged along the batch dimension of the input - image_features tensor. Notice that locations are *not* shared across classes, - thus for each anchor, a separate prediction is made for each class. - - In addition to predicting boxes and classes, optionally this class allows - predicting masks and/or keypoints inside detection boxes. - - Currently this box predictor makes per-class predictions; that is, each - anchor makes a separate box prediction for each class. - """ - - def __init__(self, - is_training, - num_classes, - fc_hyperparams_fn, - use_dropout, - dropout_keep_prob, - box_code_size, - conv_hyperparams_fn=None, - predict_instance_masks=False, - mask_height=14, - mask_width=14, - mask_prediction_num_conv_layers=2, - mask_prediction_conv_depth=256, - masks_are_class_agnostic=False, - predict_keypoints=False, - share_box_across_classes=False): - """Constructor. - - Args: - is_training: Indicates whether the BoxPredictor is in training mode. - num_classes: number of classes. Note that num_classes *does not* - include the background category, so if groundtruth labels take values - in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the - assigned classification targets can range from {0,... K}). - fc_hyperparams_fn: A function to generate tf-slim arg_scope with - hyperparameters for fully connected ops. - use_dropout: Option to use dropout or not. Note that a single dropout - op is applied here prior to both box and class predictions, which stands - in contrast to the ConvolutionalBoxPredictor below. - dropout_keep_prob: Keep probability for dropout. - This is only used if use_dropout is True. - box_code_size: Size of encoding for each box. - conv_hyperparams_fn: A function to generate tf-slim arg_scope with - hyperparameters for convolution ops. - predict_instance_masks: Whether to predict object masks inside detection - boxes. - mask_height: Desired output mask height. The default value is 14. - mask_width: Desired output mask width. The default value is 14. - mask_prediction_num_conv_layers: Number of convolution layers applied to - the image_features in mask prediction branch. - mask_prediction_conv_depth: The depth for the first conv2d_transpose op - applied to the image_features in the mask prediction branch. If set - to 0, the depth of the convolution layers will be automatically chosen - based on the number of object classes and the number of channels in the - image features. - masks_are_class_agnostic: Boolean determining if the mask-head is - class-agnostic or not. - predict_keypoints: Whether to predict keypoints insde detection boxes. - share_box_across_classes: Whether to share boxes across classes rather - than use a different box for each class. - - Raises: - ValueError: If predict_instance_masks is true but conv_hyperparams is not - set. - ValueError: If predict_keypoints is true since it is not implemented yet. - ValueError: If mask_prediction_num_conv_layers is smaller than two. - """ - super(MaskRCNNBoxPredictor, self).__init__(is_training, num_classes) - self._fc_hyperparams_fn = fc_hyperparams_fn - self._use_dropout = use_dropout - self._box_code_size = box_code_size - self._dropout_keep_prob = dropout_keep_prob - self._conv_hyperparams_fn = conv_hyperparams_fn - self._predict_instance_masks = predict_instance_masks - self._mask_height = mask_height - self._mask_width = mask_width - self._mask_prediction_num_conv_layers = mask_prediction_num_conv_layers - self._mask_prediction_conv_depth = mask_prediction_conv_depth - self._masks_are_class_agnostic = masks_are_class_agnostic - self._predict_keypoints = predict_keypoints - self._share_box_across_classes = share_box_across_classes - if self._predict_keypoints: - raise ValueError('Keypoint prediction is unimplemented.') - if ((self._predict_instance_masks or self._predict_keypoints) and - self._conv_hyperparams_fn is None): - raise ValueError('`conv_hyperparams` must be provided when predicting ' - 'masks.') - if self._mask_prediction_num_conv_layers < 2: - raise ValueError( - 'Mask prediction should consist of at least 2 conv layers') - - @property - def num_classes(self): - return self._num_classes - - @property - def predicts_instance_masks(self): - return self._predict_instance_masks - - def _predict_boxes_and_classes(self, image_features): - """Predicts boxes and class scores. - - Args: - image_features: A float tensor of shape [batch_size, height, width, - channels] containing features for a batch of images. - - Returns: - box_encodings: A float tensor of shape - [batch_size, 1, num_classes, code_size] representing the location of the - objects. - class_predictions_with_background: A float tensor of shape - [batch_size, 1, num_classes + 1] representing the class predictions for - the proposals. - """ - spatial_averaged_image_features = tf.reduce_mean(image_features, [1, 2], - keep_dims=True, - name='AvgPool') - flattened_image_features = slim.flatten(spatial_averaged_image_features) - if self._use_dropout: - flattened_image_features = slim.dropout(flattened_image_features, - keep_prob=self._dropout_keep_prob, - is_training=self._is_training) - number_of_boxes = 1 - if not self._share_box_across_classes: - number_of_boxes = self._num_classes - - with slim.arg_scope(self._fc_hyperparams_fn()): - box_encodings = slim.fully_connected( - flattened_image_features, - number_of_boxes * self._box_code_size, - activation_fn=None, - scope='BoxEncodingPredictor') - class_predictions_with_background = slim.fully_connected( - flattened_image_features, - self._num_classes + 1, - activation_fn=None, - scope='ClassPredictor') - box_encodings = tf.reshape( - box_encodings, [-1, 1, number_of_boxes, self._box_code_size]) - class_predictions_with_background = tf.reshape( - class_predictions_with_background, [-1, 1, self._num_classes + 1]) - return box_encodings, class_predictions_with_background - - def _get_mask_predictor_conv_depth(self, num_feature_channels, num_classes, - class_weight=3.0, feature_weight=2.0): - """Computes the depth of the mask predictor convolutions. - - Computes the depth of the mask predictor convolutions given feature channels - and number of classes by performing a weighted average of the two in - log space to compute the number of convolution channels. The weights that - are used for computing the weighted average do not need to sum to 1. - - Args: - num_feature_channels: An integer containing the number of feature - channels. - num_classes: An integer containing the number of classes. - class_weight: Class weight used in computing the weighted average. - feature_weight: Feature weight used in computing the weighted average. - - Returns: - An integer containing the number of convolution channels used by mask - predictor. - """ - num_feature_channels_log = math.log(float(num_feature_channels), 2.0) - num_classes_log = math.log(float(num_classes), 2.0) - weighted_num_feature_channels_log = ( - num_feature_channels_log * feature_weight) - weighted_num_classes_log = num_classes_log * class_weight - total_weight = feature_weight + class_weight - num_conv_channels_log = round( - (weighted_num_feature_channels_log + weighted_num_classes_log) / - total_weight) - return int(math.pow(2.0, num_conv_channels_log)) - - def _predict_masks(self, image_features): - """Performs mask prediction. - - Args: - image_features: A float tensor of shape [batch_size, height, width, - channels] containing features for a batch of images. - - Returns: - instance_masks: A float tensor of shape - [batch_size, 1, num_classes, image_height, image_width]. - """ - num_conv_channels = self._mask_prediction_conv_depth - if num_conv_channels == 0: - num_feature_channels = image_features.get_shape().as_list()[3] - num_conv_channels = self._get_mask_predictor_conv_depth( - num_feature_channels, self.num_classes) - with slim.arg_scope(self._conv_hyperparams_fn()): - upsampled_features = tf.image.resize_bilinear( - image_features, - [self._mask_height, self._mask_width], - align_corners=True) - for _ in range(self._mask_prediction_num_conv_layers - 1): - upsampled_features = slim.conv2d( - upsampled_features, - num_outputs=num_conv_channels, - kernel_size=[3, 3]) - num_masks = 1 if self._masks_are_class_agnostic else self.num_classes - mask_predictions = slim.conv2d(upsampled_features, - num_outputs=num_masks, - activation_fn=None, - kernel_size=[3, 3]) - return tf.expand_dims( - tf.transpose(mask_predictions, perm=[0, 3, 1, 2]), - axis=1, - name='MaskPredictor') - - def _predict(self, image_features, num_predictions_per_location, - predict_boxes_and_classes=True, predict_auxiliary_outputs=False): - """Optionally computes encoded object locations, confidences, and masks. - - Flattens image_features and applies fully connected ops (with no - non-linearity) to predict box encodings and class predictions. In this - setting, anchors are not spatially arranged in any way and are assumed to - have been folded into the batch dimension. Thus we output 1 for the - anchors dimension. - - Also optionally predicts instance masks. - The mask prediction head is based on the Mask RCNN paper with the following - modifications: We replace the deconvolution layer with a bilinear resize - and a convolution. - - Args: - image_features: A list of float tensors of shape [batch_size, height_i, - width_i, channels_i] containing features for a batch of images. - num_predictions_per_location: A list of integers representing the number - of box predictions to be made per spatial location for each feature map. - Currently, this must be set to [1], or an error will be raised. - predict_boxes_and_classes: If true, the function will perform box - refinement and classification. - predict_auxiliary_outputs: If true, the function will perform other - predictions such as mask, keypoint, boundaries, etc. if any. - - Returns: - A dictionary containing the following tensors. - box_encodings: A float tensor of shape - [batch_size, 1, num_classes, code_size] representing the - location of the objects. - class_predictions_with_background: A float tensor of shape - [batch_size, 1, num_classes + 1] representing the class - predictions for the proposals. - If predict_masks is True the dictionary also contains: - instance_masks: A float tensor of shape - [batch_size, 1, num_classes, image_height, image_width] - If predict_keypoints is True the dictionary also contains: - keypoints: [batch_size, 1, num_keypoints, 2] - - Raises: - ValueError: If num_predictions_per_location is not 1 or if both - predict_boxes_and_classes and predict_auxiliary_outputs are false or if - len(image_features) is not 1. - """ - if (len(num_predictions_per_location) != 1 or - num_predictions_per_location[0] != 1): - raise ValueError('Currently FullyConnectedBoxPredictor only supports ' - 'predicting a single box per class per location.') - if not predict_boxes_and_classes and not predict_auxiliary_outputs: - raise ValueError('Should perform at least one prediction.') - if len(image_features) != 1: - raise ValueError('length of `image_features` must be 1. Found {}'. - format(len(image_features))) - image_feature = image_features[0] - num_predictions_per_location = num_predictions_per_location[0] - predictions_dict = {} - - if predict_boxes_and_classes: - (box_encodings, class_predictions_with_background - ) = self._predict_boxes_and_classes(image_feature) - predictions_dict[BOX_ENCODINGS] = box_encodings - predictions_dict[ - CLASS_PREDICTIONS_WITH_BACKGROUND] = class_predictions_with_background - - if self._predict_instance_masks and predict_auxiliary_outputs: - predictions_dict[MASK_PREDICTIONS] = self._predict_masks(image_feature) - - return predictions_dict - - -class _NoopVariableScope(object): - """A dummy class that does not push any scope.""" - - def __enter__(self): - return None - - def __exit__(self, exc_type, exc_value, traceback): - return False - - -class ConvolutionalBoxPredictor(BoxPredictor): - """Convolutional Box Predictor. - - Optionally add an intermediate 1x1 convolutional layer after features and - predict in parallel branches box_encodings and - class_predictions_with_background. - - Currently this box predictor assumes that predictions are "shared" across - classes --- that is each anchor makes box predictions which do not depend - on class. - """ - - def __init__(self, - is_training, - num_classes, - conv_hyperparams_fn, - min_depth, - max_depth, - num_layers_before_predictor, - use_dropout, - dropout_keep_prob, - kernel_size, - box_code_size, - apply_sigmoid_to_scores=False, - class_prediction_bias_init=0.0, - use_depthwise=False): - """Constructor. - - Args: - is_training: Indicates whether the BoxPredictor is in training mode. - num_classes: number of classes. Note that num_classes *does not* - include the background category, so if groundtruth labels take values - in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the - assigned classification targets can range from {0,... K}). - conv_hyperparams_fn: A function to generate tf-slim arg_scope with - hyperparameters for convolution ops. - min_depth: Minimum feature depth prior to predicting box encodings - and class predictions. - max_depth: Maximum feature depth prior to predicting box encodings - and class predictions. If max_depth is set to 0, no additional - feature map will be inserted before location and class predictions. - num_layers_before_predictor: Number of the additional conv layers before - the predictor. - use_dropout: Option to use dropout for class prediction or not. - dropout_keep_prob: Keep probability for dropout. - This is only used if use_dropout is True. - kernel_size: Size of final convolution kernel. If the - spatial resolution of the feature map is smaller than the kernel size, - then the kernel size is automatically set to be - min(feature_width, feature_height). - box_code_size: Size of encoding for each box. - apply_sigmoid_to_scores: if True, apply the sigmoid on the output - class_predictions. - class_prediction_bias_init: constant value to initialize bias of the last - conv2d layer before class prediction. - use_depthwise: Whether to use depthwise convolutions for prediction - steps. Default is False. - - Raises: - ValueError: if min_depth > max_depth. - """ - super(ConvolutionalBoxPredictor, self).__init__(is_training, num_classes) - if min_depth > max_depth: - raise ValueError('min_depth should be less than or equal to max_depth') - self._conv_hyperparams_fn = conv_hyperparams_fn - self._min_depth = min_depth - self._max_depth = max_depth - self._num_layers_before_predictor = num_layers_before_predictor - self._use_dropout = use_dropout - self._kernel_size = kernel_size - self._box_code_size = box_code_size - self._dropout_keep_prob = dropout_keep_prob - self._apply_sigmoid_to_scores = apply_sigmoid_to_scores - self._class_prediction_bias_init = class_prediction_bias_init - self._use_depthwise = use_depthwise - - def _predict(self, image_features, num_predictions_per_location_list): - """Computes encoded object locations and corresponding confidences. - - Args: - image_features: A list of float tensors of shape [batch_size, height_i, - width_i, channels_i] containing features for a batch of images. - num_predictions_per_location_list: A list of integers representing the - number of box predictions to be made per spatial location for each - feature map. - - Returns: - box_encodings: A list of float tensors of shape - [batch_size, num_anchors_i, q, code_size] representing the location of - the objects, where q is 1 or the number of classes. Each entry in the - list corresponds to a feature map in the input `image_features` list. - class_predictions_with_background: A list of float tensors of shape - [batch_size, num_anchors_i, num_classes + 1] representing the class - predictions for the proposals. Each entry in the list corresponds to a - feature map in the input `image_features` list. - """ - box_encodings_list = [] - class_predictions_list = [] - # TODO(rathodv): Come up with a better way to generate scope names - # in box predictor once we have time to retrain all models in the zoo. - # The following lines create scope names to be backwards compatible with the - # existing checkpoints. - box_predictor_scopes = [_NoopVariableScope()] - if len(image_features) > 1: - box_predictor_scopes = [ - tf.variable_scope('BoxPredictor_{}'.format(i)) - for i in range(len(image_features)) - ] - - for (image_feature, - num_predictions_per_location, box_predictor_scope) in zip( - image_features, num_predictions_per_location_list, - box_predictor_scopes): - with box_predictor_scope: - # Add a slot for the background class. - num_class_slots = self.num_classes + 1 - net = image_feature - with slim.arg_scope(self._conv_hyperparams_fn()), \ - slim.arg_scope([slim.dropout], is_training=self._is_training): - # Add additional conv layers before the class predictor. - features_depth = static_shape.get_depth(image_feature.get_shape()) - depth = max(min(features_depth, self._max_depth), self._min_depth) - tf.logging.info('depth of additional conv before box predictor: {}'. - format(depth)) - if depth > 0 and self._num_layers_before_predictor > 0: - for i in range(self._num_layers_before_predictor): - net = slim.conv2d( - net, depth, [1, 1], scope='Conv2d_%d_1x1_%d' % (i, depth)) - with slim.arg_scope([slim.conv2d], activation_fn=None, - normalizer_fn=None, normalizer_params=None): - if self._use_depthwise: - box_encodings = slim.separable_conv2d( - net, None, [self._kernel_size, self._kernel_size], - padding='SAME', depth_multiplier=1, stride=1, - rate=1, scope='BoxEncodingPredictor_depthwise') - box_encodings = slim.conv2d( - box_encodings, - num_predictions_per_location * self._box_code_size, [1, 1], - scope='BoxEncodingPredictor') - else: - box_encodings = slim.conv2d( - net, num_predictions_per_location * self._box_code_size, - [self._kernel_size, self._kernel_size], - scope='BoxEncodingPredictor') - if self._use_dropout: - net = slim.dropout(net, keep_prob=self._dropout_keep_prob) - if self._use_depthwise: - class_predictions_with_background = slim.separable_conv2d( - net, None, [self._kernel_size, self._kernel_size], - padding='SAME', depth_multiplier=1, stride=1, - rate=1, scope='ClassPredictor_depthwise') - class_predictions_with_background = slim.conv2d( - class_predictions_with_background, - num_predictions_per_location * num_class_slots, - [1, 1], scope='ClassPredictor') - else: - class_predictions_with_background = slim.conv2d( - net, num_predictions_per_location * num_class_slots, - [self._kernel_size, self._kernel_size], - scope='ClassPredictor', - biases_initializer=tf.constant_initializer( - self._class_prediction_bias_init)) - if self._apply_sigmoid_to_scores: - class_predictions_with_background = tf.sigmoid( - class_predictions_with_background) - - combined_feature_map_shape = (shape_utils. - combined_static_and_dynamic_shape( - image_feature)) - box_encodings = tf.reshape( - box_encodings, tf.stack([combined_feature_map_shape[0], - combined_feature_map_shape[1] * - combined_feature_map_shape[2] * - num_predictions_per_location, - 1, self._box_code_size])) - box_encodings_list.append(box_encodings) - class_predictions_with_background = tf.reshape( - class_predictions_with_background, - tf.stack([combined_feature_map_shape[0], - combined_feature_map_shape[1] * - combined_feature_map_shape[2] * - num_predictions_per_location, - num_class_slots])) - class_predictions_list.append(class_predictions_with_background) - return { - BOX_ENCODINGS: box_encodings_list, - CLASS_PREDICTIONS_WITH_BACKGROUND: class_predictions_list - } - - -# TODO(rathodv): Replace with slim.arg_scope_func_key once its available -# externally. -def _arg_scope_func_key(op): - """Returns a key that can be used to index arg_scope dictionary.""" - return getattr(op, '_key_op', str(op)) - - -# TODO(rathodv): Merge the implementation with ConvolutionalBoxPredictor above -# since they are very similar. -class WeightSharedConvolutionalBoxPredictor(BoxPredictor): - """Convolutional Box Predictor with weight sharing. - - Defines the box predictor as defined in - https://arxiv.org/abs/1708.02002. This class differs from - ConvolutionalBoxPredictor in that it shares weights and biases while - predicting from different feature maps. However, batch_norm parameters are not - shared because the statistics of the activations vary among the different - feature maps. - - Also note that separate multi-layer towers are constructed for the box - encoding and class predictors respectively. - """ - - def __init__(self, - is_training, - num_classes, - conv_hyperparams_fn, - depth, - num_layers_before_predictor, - box_code_size, - kernel_size=3, - class_prediction_bias_init=0.0, - use_dropout=False, - dropout_keep_prob=0.8): - """Constructor. - - Args: - is_training: Indicates whether the BoxPredictor is in training mode. - num_classes: number of classes. Note that num_classes *does not* - include the background category, so if groundtruth labels take values - in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the - assigned classification targets can range from {0,... K}). - conv_hyperparams_fn: A function to generate tf-slim arg_scope with - hyperparameters for convolution ops. - depth: depth of conv layers. - num_layers_before_predictor: Number of the additional conv layers before - the predictor. - box_code_size: Size of encoding for each box. - kernel_size: Size of final convolution kernel. - class_prediction_bias_init: constant value to initialize bias of the last - conv2d layer before class prediction. - use_dropout: Whether to apply dropout to class prediction head. - dropout_keep_prob: Probability of keeping activiations. - """ - super(WeightSharedConvolutionalBoxPredictor, self).__init__(is_training, - num_classes) - self._conv_hyperparams_fn = conv_hyperparams_fn - self._depth = depth - self._num_layers_before_predictor = num_layers_before_predictor - self._box_code_size = box_code_size - self._kernel_size = kernel_size - self._class_prediction_bias_init = class_prediction_bias_init - self._use_dropout = use_dropout - self._dropout_keep_prob = dropout_keep_prob - - def _predict(self, image_features, num_predictions_per_location_list): - """Computes encoded object locations and corresponding confidences. - - Args: - image_features: A list of float tensors of shape [batch_size, height_i, - width_i, channels] containing features for a batch of images. Note that - all tensors in the list must have the same number of channels. - num_predictions_per_location_list: A list of integers representing the - number of box predictions to be made per spatial location for each - feature map. Note that all values must be the same since the weights are - shared. - - Returns: - box_encodings: A list of float tensors of shape - [batch_size, num_anchors_i, code_size] representing the location of - the objects. Each entry in the list corresponds to a feature map in the - input `image_features` list. - class_predictions_with_background: A list of float tensors of shape - [batch_size, num_anchors_i, num_classes + 1] representing the class - predictions for the proposals. Each entry in the list corresponds to a - feature map in the input `image_features` list. - - - Raises: - ValueError: If the image feature maps do not have the same number of - channels or if the num predictions per locations is differs between the - feature maps. - """ - if len(set(num_predictions_per_location_list)) > 1: - raise ValueError('num predictions per location must be same for all' - 'feature maps, found: {}'.format( - num_predictions_per_location_list)) - feature_channels = [ - image_feature.shape[3].value for image_feature in image_features - ] - if len(set(feature_channels)) > 1: - raise ValueError('all feature maps must have the same number of ' - 'channels, found: {}'.format(feature_channels)) - box_encodings_list = [] - class_predictions_list = [] - for feature_index, (image_feature, - num_predictions_per_location) in enumerate( - zip(image_features, - num_predictions_per_location_list)): - # Add a slot for the background class. - with tf.variable_scope('WeightSharedConvolutionalBoxPredictor', - reuse=tf.AUTO_REUSE): - num_class_slots = self.num_classes + 1 - box_encodings_net = image_feature - class_predictions_net = image_feature - with slim.arg_scope(self._conv_hyperparams_fn()) as sc: - apply_batch_norm = _arg_scope_func_key(slim.batch_norm) in sc - for i in range(self._num_layers_before_predictor): - box_encodings_net = slim.conv2d( - box_encodings_net, - self._depth, - [self._kernel_size, self._kernel_size], - stride=1, - padding='SAME', - activation_fn=None, - normalizer_fn=(tf.identity if apply_batch_norm else None), - scope='BoxPredictionTower/conv2d_{}'.format(i)) - if apply_batch_norm: - box_encodings_net = slim.batch_norm( - box_encodings_net, - scope='BoxPredictionTower/conv2d_{}/BatchNorm/feature_{}'. - format(i, feature_index)) - box_encodings_net = tf.nn.relu6(box_encodings_net) - box_encodings = slim.conv2d( - box_encodings_net, - num_predictions_per_location * self._box_code_size, - [self._kernel_size, self._kernel_size], - activation_fn=None, stride=1, padding='SAME', - normalizer_fn=None, - scope='BoxPredictor') - - for i in range(self._num_layers_before_predictor): - class_predictions_net = slim.conv2d( - class_predictions_net, - self._depth, - [self._kernel_size, self._kernel_size], - stride=1, - padding='SAME', - activation_fn=None, - normalizer_fn=(tf.identity if apply_batch_norm else None), - scope='ClassPredictionTower/conv2d_{}'.format(i)) - if apply_batch_norm: - class_predictions_net = slim.batch_norm( - class_predictions_net, - scope='ClassPredictionTower/conv2d_{}/BatchNorm/feature_{}' - .format(i, feature_index)) - class_predictions_net = tf.nn.relu6(class_predictions_net) - if self._use_dropout: - class_predictions_net = slim.dropout( - class_predictions_net, keep_prob=self._dropout_keep_prob) - class_predictions_with_background = slim.conv2d( - class_predictions_net, - num_predictions_per_location * num_class_slots, - [self._kernel_size, self._kernel_size], - activation_fn=None, stride=1, padding='SAME', - normalizer_fn=None, - biases_initializer=tf.constant_initializer( - self._class_prediction_bias_init), - scope='ClassPredictor') - - combined_feature_map_shape = (shape_utils. - combined_static_and_dynamic_shape( - image_feature)) - box_encodings = tf.reshape( - box_encodings, tf.stack([combined_feature_map_shape[0], - combined_feature_map_shape[1] * - combined_feature_map_shape[2] * - num_predictions_per_location, - self._box_code_size])) - box_encodings_list.append(box_encodings) - class_predictions_with_background = tf.reshape( - class_predictions_with_background, - tf.stack([combined_feature_map_shape[0], - combined_feature_map_shape[1] * - combined_feature_map_shape[2] * - num_predictions_per_location, - num_class_slots])) - class_predictions_list.append(class_predictions_with_background) - return { - BOX_ENCODINGS: box_encodings_list, - CLASS_PREDICTIONS_WITH_BACKGROUND: class_predictions_list - } diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_predictor_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_predictor_test.py deleted file mode 100644 index 49680596f..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/box_predictor_test.py +++ /dev/null @@ -1,724 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.box_predictor.""" -import numpy as np -import tensorflow as tf - -from google.protobuf import text_format -from object_detection.builders import hyperparams_builder -from object_detection.core import box_predictor -from object_detection.protos import hyperparams_pb2 -from object_detection.utils import test_case - - -class MaskRCNNBoxPredictorTest(tf.test.TestCase): - - def _build_arg_scope_with_hyperparams(self, - op_type=hyperparams_pb2.Hyperparams.FC): - hyperparams = hyperparams_pb2.Hyperparams() - hyperparams_text_proto = """ - activation: NONE - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - text_format.Merge(hyperparams_text_proto, hyperparams) - hyperparams.op = op_type - return hyperparams_builder.build(hyperparams, is_training=True) - - def test_get_boxes_with_five_classes(self): - image_features = tf.random_uniform([2, 7, 7, 3], dtype=tf.float32) - mask_box_predictor = box_predictor.MaskRCNNBoxPredictor( - is_training=False, - num_classes=5, - fc_hyperparams_fn=self._build_arg_scope_with_hyperparams(), - use_dropout=False, - dropout_keep_prob=0.5, - box_code_size=4, - ) - box_predictions = mask_box_predictor.predict( - [image_features], num_predictions_per_location=[1], - scope='BoxPredictor') - box_encodings = box_predictions[box_predictor.BOX_ENCODINGS] - class_predictions_with_background = box_predictions[ - box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND] - init_op = tf.global_variables_initializer() - with self.test_session() as sess: - sess.run(init_op) - (box_encodings_shape, - class_predictions_with_background_shape) = sess.run( - [tf.shape(box_encodings), - tf.shape(class_predictions_with_background)]) - self.assertAllEqual(box_encodings_shape, [2, 1, 5, 4]) - self.assertAllEqual(class_predictions_with_background_shape, [2, 1, 6]) - - def test_get_boxes_with_five_classes_share_box_across_classes(self): - image_features = tf.random_uniform([2, 7, 7, 3], dtype=tf.float32) - mask_box_predictor = box_predictor.MaskRCNNBoxPredictor( - is_training=False, - num_classes=5, - fc_hyperparams_fn=self._build_arg_scope_with_hyperparams(), - use_dropout=False, - dropout_keep_prob=0.5, - box_code_size=4, - share_box_across_classes=True - ) - box_predictions = mask_box_predictor.predict( - [image_features], num_predictions_per_location=[1], - scope='BoxPredictor') - box_encodings = box_predictions[box_predictor.BOX_ENCODINGS] - class_predictions_with_background = box_predictions[ - box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND] - init_op = tf.global_variables_initializer() - with self.test_session() as sess: - sess.run(init_op) - (box_encodings_shape, - class_predictions_with_background_shape) = sess.run( - [tf.shape(box_encodings), - tf.shape(class_predictions_with_background)]) - self.assertAllEqual(box_encodings_shape, [2, 1, 1, 4]) - self.assertAllEqual(class_predictions_with_background_shape, [2, 1, 6]) - - def test_value_error_on_predict_instance_masks_with_no_conv_hyperparms(self): - with self.assertRaises(ValueError): - box_predictor.MaskRCNNBoxPredictor( - is_training=False, - num_classes=5, - fc_hyperparams_fn=self._build_arg_scope_with_hyperparams(), - use_dropout=False, - dropout_keep_prob=0.5, - box_code_size=4, - predict_instance_masks=True) - - def test_get_instance_masks(self): - image_features = tf.random_uniform([2, 7, 7, 3], dtype=tf.float32) - mask_box_predictor = box_predictor.MaskRCNNBoxPredictor( - is_training=False, - num_classes=5, - fc_hyperparams_fn=self._build_arg_scope_with_hyperparams(), - use_dropout=False, - dropout_keep_prob=0.5, - box_code_size=4, - conv_hyperparams_fn=self._build_arg_scope_with_hyperparams( - op_type=hyperparams_pb2.Hyperparams.CONV), - predict_instance_masks=True) - box_predictions = mask_box_predictor.predict( - [image_features], - num_predictions_per_location=[1], - scope='BoxPredictor', - predict_boxes_and_classes=True, - predict_auxiliary_outputs=True) - mask_predictions = box_predictions[box_predictor.MASK_PREDICTIONS] - self.assertListEqual([2, 1, 5, 14, 14], - mask_predictions.get_shape().as_list()) - - def test_do_not_return_instance_masks_without_request(self): - image_features = tf.random_uniform([2, 7, 7, 3], dtype=tf.float32) - mask_box_predictor = box_predictor.MaskRCNNBoxPredictor( - is_training=False, - num_classes=5, - fc_hyperparams_fn=self._build_arg_scope_with_hyperparams(), - use_dropout=False, - dropout_keep_prob=0.5, - box_code_size=4) - box_predictions = mask_box_predictor.predict( - [image_features], num_predictions_per_location=[1], - scope='BoxPredictor') - self.assertEqual(len(box_predictions), 2) - self.assertTrue(box_predictor.BOX_ENCODINGS in box_predictions) - self.assertTrue(box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND - in box_predictions) - - def test_value_error_on_predict_keypoints(self): - with self.assertRaises(ValueError): - box_predictor.MaskRCNNBoxPredictor( - is_training=False, - num_classes=5, - fc_hyperparams_fn=self._build_arg_scope_with_hyperparams(), - use_dropout=False, - dropout_keep_prob=0.5, - box_code_size=4, - predict_keypoints=True) - - -class RfcnBoxPredictorTest(tf.test.TestCase): - - def _build_arg_scope_with_conv_hyperparams(self): - conv_hyperparams = hyperparams_pb2.Hyperparams() - conv_hyperparams_text_proto = """ - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams) - return hyperparams_builder.build(conv_hyperparams, is_training=True) - - def test_get_correct_box_encoding_and_class_prediction_shapes(self): - image_features = tf.random_uniform([4, 8, 8, 64], dtype=tf.float32) - proposal_boxes = tf.random_normal([4, 2, 4], dtype=tf.float32) - rfcn_box_predictor = box_predictor.RfcnBoxPredictor( - is_training=False, - num_classes=2, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - num_spatial_bins=[3, 3], - depth=4, - crop_size=[12, 12], - box_code_size=4 - ) - box_predictions = rfcn_box_predictor.predict( - [image_features], num_predictions_per_location=[1], - scope='BoxPredictor', - proposal_boxes=proposal_boxes) - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - class_predictions_with_background = tf.concat( - box_predictions[box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], - axis=1) - - init_op = tf.global_variables_initializer() - with self.test_session() as sess: - sess.run(init_op) - (box_encodings_shape, - class_predictions_shape) = sess.run( - [tf.shape(box_encodings), - tf.shape(class_predictions_with_background)]) - self.assertAllEqual(box_encodings_shape, [8, 1, 2, 4]) - self.assertAllEqual(class_predictions_shape, [8, 1, 3]) - - -class ConvolutionalBoxPredictorTest(test_case.TestCase): - - def _build_arg_scope_with_conv_hyperparams(self): - conv_hyperparams = hyperparams_pb2.Hyperparams() - conv_hyperparams_text_proto = """ - activation: RELU_6 - regularizer { - l2_regularizer { - } - } - initializer { - truncated_normal_initializer { - } - } - """ - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams) - return hyperparams_builder.build(conv_hyperparams, is_training=True) - - def test_get_boxes_for_five_aspect_ratios_per_location(self): - def graph_fn(image_features): - conv_box_predictor = box_predictor.ConvolutionalBoxPredictor( - is_training=False, - num_classes=0, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - min_depth=0, - max_depth=32, - num_layers_before_predictor=1, - use_dropout=True, - dropout_keep_prob=0.8, - kernel_size=1, - box_code_size=4 - ) - box_predictions = conv_box_predictor.predict( - [image_features], num_predictions_per_location=[5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - objectness_predictions = tf.concat( - box_predictions[box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], - axis=1) - return (box_encodings, objectness_predictions) - image_features = np.random.rand(4, 8, 8, 64).astype(np.float32) - (box_encodings, objectness_predictions) = self.execute(graph_fn, - [image_features]) - self.assertAllEqual(box_encodings.shape, [4, 320, 1, 4]) - self.assertAllEqual(objectness_predictions.shape, [4, 320, 1]) - - def test_get_boxes_for_one_aspect_ratio_per_location(self): - def graph_fn(image_features): - conv_box_predictor = box_predictor.ConvolutionalBoxPredictor( - is_training=False, - num_classes=0, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - min_depth=0, - max_depth=32, - num_layers_before_predictor=1, - use_dropout=True, - dropout_keep_prob=0.8, - kernel_size=1, - box_code_size=4 - ) - box_predictions = conv_box_predictor.predict( - [image_features], num_predictions_per_location=[1], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - objectness_predictions = tf.concat(box_predictions[ - box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], axis=1) - return (box_encodings, objectness_predictions) - image_features = np.random.rand(4, 8, 8, 64).astype(np.float32) - (box_encodings, objectness_predictions) = self.execute(graph_fn, - [image_features]) - self.assertAllEqual(box_encodings.shape, [4, 64, 1, 4]) - self.assertAllEqual(objectness_predictions.shape, [4, 64, 1]) - - def test_get_multi_class_predictions_for_five_aspect_ratios_per_location( - self): - num_classes_without_background = 6 - image_features = np.random.rand(4, 8, 8, 64).astype(np.float32) - def graph_fn(image_features): - conv_box_predictor = box_predictor.ConvolutionalBoxPredictor( - is_training=False, - num_classes=num_classes_without_background, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - min_depth=0, - max_depth=32, - num_layers_before_predictor=1, - use_dropout=True, - dropout_keep_prob=0.8, - kernel_size=1, - box_code_size=4 - ) - box_predictions = conv_box_predictor.predict( - [image_features], - num_predictions_per_location=[5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - class_predictions_with_background = tf.concat( - box_predictions[box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], - axis=1) - return (box_encodings, class_predictions_with_background) - (box_encodings, - class_predictions_with_background) = self.execute(graph_fn, - [image_features]) - self.assertAllEqual(box_encodings.shape, [4, 320, 1, 4]) - self.assertAllEqual(class_predictions_with_background.shape, - [4, 320, num_classes_without_background+1]) - - def test_get_predictions_with_feature_maps_of_dynamic_shape( - self): - image_features = tf.placeholder(dtype=tf.float32, shape=[4, None, None, 64]) - conv_box_predictor = box_predictor.ConvolutionalBoxPredictor( - is_training=False, - num_classes=0, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - min_depth=0, - max_depth=32, - num_layers_before_predictor=1, - use_dropout=True, - dropout_keep_prob=0.8, - kernel_size=1, - box_code_size=4 - ) - box_predictions = conv_box_predictor.predict( - [image_features], num_predictions_per_location=[5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - objectness_predictions = tf.concat( - box_predictions[box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], - axis=1) - init_op = tf.global_variables_initializer() - - resolution = 32 - expected_num_anchors = resolution*resolution*5 - with self.test_session() as sess: - sess.run(init_op) - (box_encodings_shape, - objectness_predictions_shape) = sess.run( - [tf.shape(box_encodings), tf.shape(objectness_predictions)], - feed_dict={image_features: - np.random.rand(4, resolution, resolution, 64)}) - actual_variable_set = set( - [var.op.name for var in tf.trainable_variables()]) - self.assertAllEqual(box_encodings_shape, [4, expected_num_anchors, 1, 4]) - self.assertAllEqual(objectness_predictions_shape, - [4, expected_num_anchors, 1]) - expected_variable_set = set([ - 'BoxPredictor/Conv2d_0_1x1_32/biases', - 'BoxPredictor/Conv2d_0_1x1_32/weights', - 'BoxPredictor/BoxEncodingPredictor/biases', - 'BoxPredictor/BoxEncodingPredictor/weights', - 'BoxPredictor/ClassPredictor/biases', - 'BoxPredictor/ClassPredictor/weights']) - self.assertEqual(expected_variable_set, actual_variable_set) - - def test_use_depthwise_convolution(self): - image_features = tf.placeholder(dtype=tf.float32, shape=[4, None, None, 64]) - conv_box_predictor = box_predictor.ConvolutionalBoxPredictor( - is_training=False, - num_classes=0, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - min_depth=0, - max_depth=32, - num_layers_before_predictor=1, - dropout_keep_prob=0.8, - kernel_size=1, - box_code_size=4, - use_dropout=True, - use_depthwise=True - ) - box_predictions = conv_box_predictor.predict( - [image_features], num_predictions_per_location=[5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - objectness_predictions = tf.concat( - box_predictions[box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], - axis=1) - init_op = tf.global_variables_initializer() - - resolution = 32 - expected_num_anchors = resolution*resolution*5 - with self.test_session() as sess: - sess.run(init_op) - (box_encodings_shape, - objectness_predictions_shape) = sess.run( - [tf.shape(box_encodings), tf.shape(objectness_predictions)], - feed_dict={image_features: - np.random.rand(4, resolution, resolution, 64)}) - actual_variable_set = set( - [var.op.name for var in tf.trainable_variables()]) - self.assertAllEqual(box_encodings_shape, [4, expected_num_anchors, 1, 4]) - self.assertAllEqual(objectness_predictions_shape, - [4, expected_num_anchors, 1]) - expected_variable_set = set([ - 'BoxPredictor/Conv2d_0_1x1_32/biases', - 'BoxPredictor/Conv2d_0_1x1_32/weights', - 'BoxPredictor/BoxEncodingPredictor_depthwise/biases', - 'BoxPredictor/BoxEncodingPredictor_depthwise/depthwise_weights', - 'BoxPredictor/BoxEncodingPredictor/biases', - 'BoxPredictor/BoxEncodingPredictor/weights', - 'BoxPredictor/ClassPredictor_depthwise/biases', - 'BoxPredictor/ClassPredictor_depthwise/depthwise_weights', - 'BoxPredictor/ClassPredictor/biases', - 'BoxPredictor/ClassPredictor/weights']) - self.assertEqual(expected_variable_set, actual_variable_set) - - -class WeightSharedConvolutionalBoxPredictorTest(test_case.TestCase): - - def _build_arg_scope_with_conv_hyperparams(self): - conv_hyperparams = hyperparams_pb2.Hyperparams() - conv_hyperparams_text_proto = """ - activation: RELU_6 - regularizer { - l2_regularizer { - } - } - initializer { - random_normal_initializer { - stddev: 0.01 - mean: 0.0 - } - } - batch_norm { - train: true, - } - """ - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams) - return hyperparams_builder.build(conv_hyperparams, is_training=True) - - def _build_conv_arg_scope_no_batch_norm(self): - conv_hyperparams = hyperparams_pb2.Hyperparams() - conv_hyperparams_text_proto = """ - activation: RELU_6 - regularizer { - l2_regularizer { - } - } - initializer { - random_normal_initializer { - stddev: 0.01 - mean: 0.0 - } - } - """ - text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams) - return hyperparams_builder.build(conv_hyperparams, is_training=True) - - def test_get_boxes_for_five_aspect_ratios_per_location(self): - - def graph_fn(image_features): - conv_box_predictor = box_predictor.WeightSharedConvolutionalBoxPredictor( - is_training=False, - num_classes=0, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - depth=32, - num_layers_before_predictor=1, - box_code_size=4) - box_predictions = conv_box_predictor.predict( - [image_features], num_predictions_per_location=[5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - objectness_predictions = tf.concat(box_predictions[ - box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], axis=1) - return (box_encodings, objectness_predictions) - image_features = np.random.rand(4, 8, 8, 64).astype(np.float32) - (box_encodings, objectness_predictions) = self.execute( - graph_fn, [image_features]) - self.assertAllEqual(box_encodings.shape, [4, 320, 4]) - self.assertAllEqual(objectness_predictions.shape, [4, 320, 1]) - - def test_bias_predictions_to_background_with_sigmoid_score_conversion(self): - - def graph_fn(image_features): - conv_box_predictor = box_predictor.WeightSharedConvolutionalBoxPredictor( - is_training=True, - num_classes=2, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - depth=32, - num_layers_before_predictor=1, - class_prediction_bias_init=-4.6, - box_code_size=4) - box_predictions = conv_box_predictor.predict( - [image_features], num_predictions_per_location=[5], - scope='BoxPredictor') - class_predictions = tf.concat(box_predictions[ - box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], axis=1) - return (tf.nn.sigmoid(class_predictions),) - image_features = np.random.rand(4, 8, 8, 64).astype(np.float32) - class_predictions = self.execute(graph_fn, [image_features]) - self.assertAlmostEqual(np.mean(class_predictions), 0.01, places=3) - - def test_get_multi_class_predictions_for_five_aspect_ratios_per_location( - self): - - num_classes_without_background = 6 - def graph_fn(image_features): - conv_box_predictor = box_predictor.WeightSharedConvolutionalBoxPredictor( - is_training=False, - num_classes=num_classes_without_background, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - depth=32, - num_layers_before_predictor=1, - box_code_size=4) - box_predictions = conv_box_predictor.predict( - [image_features], - num_predictions_per_location=[5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - class_predictions_with_background = tf.concat(box_predictions[ - box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], axis=1) - return (box_encodings, class_predictions_with_background) - - image_features = np.random.rand(4, 8, 8, 64).astype(np.float32) - (box_encodings, class_predictions_with_background) = self.execute( - graph_fn, [image_features]) - self.assertAllEqual(box_encodings.shape, [4, 320, 4]) - self.assertAllEqual(class_predictions_with_background.shape, - [4, 320, num_classes_without_background+1]) - - def test_get_multi_class_predictions_from_two_feature_maps( - self): - - num_classes_without_background = 6 - def graph_fn(image_features1, image_features2): - conv_box_predictor = box_predictor.WeightSharedConvolutionalBoxPredictor( - is_training=False, - num_classes=num_classes_without_background, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - depth=32, - num_layers_before_predictor=1, - box_code_size=4) - box_predictions = conv_box_predictor.predict( - [image_features1, image_features2], - num_predictions_per_location=[5, 5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - class_predictions_with_background = tf.concat( - box_predictions[box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], - axis=1) - return (box_encodings, class_predictions_with_background) - - image_features1 = np.random.rand(4, 8, 8, 64).astype(np.float32) - image_features2 = np.random.rand(4, 8, 8, 64).astype(np.float32) - (box_encodings, class_predictions_with_background) = self.execute( - graph_fn, [image_features1, image_features2]) - self.assertAllEqual(box_encodings.shape, [4, 640, 4]) - self.assertAllEqual(class_predictions_with_background.shape, - [4, 640, num_classes_without_background+1]) - - def test_predictions_from_multiple_feature_maps_share_weights_not_batchnorm( - self): - num_classes_without_background = 6 - def graph_fn(image_features1, image_features2): - conv_box_predictor = box_predictor.WeightSharedConvolutionalBoxPredictor( - is_training=False, - num_classes=num_classes_without_background, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - depth=32, - num_layers_before_predictor=2, - box_code_size=4) - box_predictions = conv_box_predictor.predict( - [image_features1, image_features2], - num_predictions_per_location=[5, 5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - class_predictions_with_background = tf.concat( - box_predictions[box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], - axis=1) - return (box_encodings, class_predictions_with_background) - - with self.test_session(graph=tf.Graph()): - graph_fn(tf.random_uniform([4, 32, 32, 3], dtype=tf.float32), - tf.random_uniform([4, 16, 16, 3], dtype=tf.float32)) - actual_variable_set = set( - [var.op.name for var in tf.trainable_variables()]) - expected_variable_set = set([ - # Box prediction tower - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_0/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_0/BatchNorm/feature_0/beta'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_0/BatchNorm/feature_1/beta'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_1/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_1/BatchNorm/feature_0/beta'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_1/BatchNorm/feature_1/beta'), - # Box prediction head - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictor/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictor/biases'), - # Class prediction tower - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_0/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_0/BatchNorm/feature_0/beta'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_0/BatchNorm/feature_1/beta'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_1/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_1/BatchNorm/feature_0/beta'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_1/BatchNorm/feature_1/beta'), - # Class prediction head - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictor/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictor/biases')]) - self.assertEqual(expected_variable_set, actual_variable_set) - - def test_no_batchnorm_params_when_batchnorm_is_not_configured(self): - num_classes_without_background = 6 - def graph_fn(image_features1, image_features2): - conv_box_predictor = box_predictor.WeightSharedConvolutionalBoxPredictor( - is_training=False, - num_classes=num_classes_without_background, - conv_hyperparams_fn=self._build_conv_arg_scope_no_batch_norm(), - depth=32, - num_layers_before_predictor=2, - box_code_size=4) - box_predictions = conv_box_predictor.predict( - [image_features1, image_features2], - num_predictions_per_location=[5, 5], - scope='BoxPredictor') - box_encodings = tf.concat( - box_predictions[box_predictor.BOX_ENCODINGS], axis=1) - class_predictions_with_background = tf.concat( - box_predictions[box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], - axis=1) - return (box_encodings, class_predictions_with_background) - - with self.test_session(graph=tf.Graph()): - graph_fn(tf.random_uniform([4, 32, 32, 3], dtype=tf.float32), - tf.random_uniform([4, 16, 16, 3], dtype=tf.float32)) - actual_variable_set = set( - [var.op.name for var in tf.trainable_variables()]) - expected_variable_set = set([ - # Box prediction tower - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_0/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_0/biases'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_1/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictionTower/conv2d_1/biases'), - # Box prediction head - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictor/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'BoxPredictor/biases'), - # Class prediction tower - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_0/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_0/biases'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_1/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictionTower/conv2d_1/biases'), - # Class prediction head - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictor/weights'), - ('BoxPredictor/WeightSharedConvolutionalBoxPredictor/' - 'ClassPredictor/biases')]) - self.assertEqual(expected_variable_set, actual_variable_set) - - def test_get_predictions_with_feature_maps_of_dynamic_shape( - self): - image_features = tf.placeholder(dtype=tf.float32, shape=[4, None, None, 64]) - conv_box_predictor = box_predictor.WeightSharedConvolutionalBoxPredictor( - is_training=False, - num_classes=0, - conv_hyperparams_fn=self._build_arg_scope_with_conv_hyperparams(), - depth=32, - num_layers_before_predictor=1, - box_code_size=4) - box_predictions = conv_box_predictor.predict( - [image_features], num_predictions_per_location=[5], - scope='BoxPredictor') - box_encodings = tf.concat(box_predictions[box_predictor.BOX_ENCODINGS], - axis=1) - objectness_predictions = tf.concat(box_predictions[ - box_predictor.CLASS_PREDICTIONS_WITH_BACKGROUND], axis=1) - init_op = tf.global_variables_initializer() - - resolution = 32 - expected_num_anchors = resolution*resolution*5 - with self.test_session() as sess: - sess.run(init_op) - (box_encodings_shape, - objectness_predictions_shape) = sess.run( - [tf.shape(box_encodings), tf.shape(objectness_predictions)], - feed_dict={image_features: - np.random.rand(4, resolution, resolution, 64)}) - self.assertAllEqual(box_encodings_shape, [4, expected_num_anchors, 4]) - self.assertAllEqual(objectness_predictions_shape, - [4, expected_num_anchors, 1]) - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/data_decoder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/data_decoder.py deleted file mode 100644 index 9ae18c1f9..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/data_decoder.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Interface for data decoders. - -Data decoders decode the input data and return a dictionary of tensors keyed by -the entries in core.reader.Fields. -""" -from abc import ABCMeta -from abc import abstractmethod - - -class DataDecoder(object): - """Interface for data decoders.""" - __metaclass__ = ABCMeta - - @abstractmethod - def decode(self, data): - """Return a single image and associated labels. - - Args: - data: a string tensor holding a serialized protocol buffer corresponding - to data for a single image. - - Returns: - tensor_dict: a dictionary containing tensors. Possible keys are defined in - reader.Fields. - """ - pass diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/data_parser.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/data_parser.py deleted file mode 100644 index 3dac4de28..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/data_parser.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Interface for data parsers. - -Data parser parses input data and returns a dictionary of numpy arrays -keyed by the entries in standard_fields.py. Since the parser parses records -to numpy arrays (materialized tensors) directly, it is used to read data for -evaluation/visualization; to parse the data during training, DataDecoder should -be used. -""" -from abc import ABCMeta -from abc import abstractmethod - - -class DataToNumpyParser(object): - __metaclass__ = ABCMeta - - @abstractmethod - def parse(self, input_data): - """Parses input and returns a numpy array or a dictionary of numpy arrays. - - Args: - input_data: an input data - - Returns: - A numpy array or a dictionary of numpy arrays or None, if input - cannot be parsed. - """ - pass diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/keypoint_ops.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/keypoint_ops.py deleted file mode 100644 index e520845f9..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/keypoint_ops.py +++ /dev/null @@ -1,282 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Keypoint operations. - -Keypoints are represented as tensors of shape [num_instances, num_keypoints, 2], -where the last dimension holds rank 2 tensors of the form [y, x] representing -the coordinates of the keypoint. -""" -import numpy as np -import tensorflow as tf - - -def scale(keypoints, y_scale, x_scale, scope=None): - """Scales keypoint coordinates in x and y dimensions. - - Args: - keypoints: a tensor of shape [num_instances, num_keypoints, 2] - y_scale: (float) scalar tensor - x_scale: (float) scalar tensor - scope: name scope. - - Returns: - new_keypoints: a tensor of shape [num_instances, num_keypoints, 2] - """ - with tf.name_scope(scope, 'Scale'): - y_scale = tf.cast(y_scale, tf.float32) - x_scale = tf.cast(x_scale, tf.float32) - new_keypoints = keypoints * [[[y_scale, x_scale]]] - return new_keypoints - - -def clip_to_window(keypoints, window, scope=None): - """Clips keypoints to a window. - - This op clips any input keypoints to a window. - - Args: - keypoints: a tensor of shape [num_instances, num_keypoints, 2] - window: a tensor of shape [4] representing the [y_min, x_min, y_max, x_max] - window to which the op should clip the keypoints. - scope: name scope. - - Returns: - new_keypoints: a tensor of shape [num_instances, num_keypoints, 2] - """ - with tf.name_scope(scope, 'ClipToWindow'): - y, x = tf.split(value=keypoints, num_or_size_splits=2, axis=2) - win_y_min, win_x_min, win_y_max, win_x_max = tf.unstack(window) - y = tf.maximum(tf.minimum(y, win_y_max), win_y_min) - x = tf.maximum(tf.minimum(x, win_x_max), win_x_min) - new_keypoints = tf.concat([y, x], 2) - return new_keypoints - - -def prune_outside_window(keypoints, window, scope=None): - """Prunes keypoints that fall outside a given window. - - This function replaces keypoints that fall outside the given window with nan. - See also clip_to_window which clips any keypoints that fall outside the given - window. - - Args: - keypoints: a tensor of shape [num_instances, num_keypoints, 2] - window: a tensor of shape [4] representing the [y_min, x_min, y_max, x_max] - window outside of which the op should prune the keypoints. - scope: name scope. - - Returns: - new_keypoints: a tensor of shape [num_instances, num_keypoints, 2] - """ - with tf.name_scope(scope, 'PruneOutsideWindow'): - y, x = tf.split(value=keypoints, num_or_size_splits=2, axis=2) - win_y_min, win_x_min, win_y_max, win_x_max = tf.unstack(window) - - valid_indices = tf.logical_and( - tf.logical_and(y >= win_y_min, y <= win_y_max), - tf.logical_and(x >= win_x_min, x <= win_x_max)) - - new_y = tf.where(valid_indices, y, np.nan * tf.ones_like(y)) - new_x = tf.where(valid_indices, x, np.nan * tf.ones_like(x)) - new_keypoints = tf.concat([new_y, new_x], 2) - - return new_keypoints - - -def change_coordinate_frame(keypoints, window, scope=None): - """Changes coordinate frame of the keypoints to be relative to window's frame. - - Given a window of the form [y_min, x_min, y_max, x_max], changes keypoint - coordinates from keypoints of shape [num_instances, num_keypoints, 2] - to be relative to this window. - - An example use case is data augmentation: where we are given groundtruth - keypoints and would like to randomly crop the image to some window. In this - case we need to change the coordinate frame of each groundtruth keypoint to be - relative to this new window. - - Args: - keypoints: a tensor of shape [num_instances, num_keypoints, 2] - window: a tensor of shape [4] representing the [y_min, x_min, y_max, x_max] - window we should change the coordinate frame to. - scope: name scope. - - Returns: - new_keypoints: a tensor of shape [num_instances, num_keypoints, 2] - """ - with tf.name_scope(scope, 'ChangeCoordinateFrame'): - win_height = window[2] - window[0] - win_width = window[3] - window[1] - new_keypoints = scale(keypoints - [window[0], window[1]], 1.0 / win_height, - 1.0 / win_width) - return new_keypoints - - -def to_normalized_coordinates(keypoints, height, width, - check_range=True, scope=None): - """Converts absolute keypoint coordinates to normalized coordinates in [0, 1]. - - Usually one uses the dynamic shape of the image or conv-layer tensor: - keypoints = keypoint_ops.to_normalized_coordinates(keypoints, - tf.shape(images)[1], - tf.shape(images)[2]), - - This function raises an assertion failed error at graph execution time when - the maximum coordinate is smaller than 1.01 (which means that coordinates are - already normalized). The value 1.01 is to deal with small rounding errors. - - Args: - keypoints: A tensor of shape [num_instances, num_keypoints, 2]. - height: Maximum value for y coordinate of absolute keypoint coordinates. - width: Maximum value for x coordinate of absolute keypoint coordinates. - check_range: If True, checks if the coordinates are normalized. - scope: name scope. - - Returns: - tensor of shape [num_instances, num_keypoints, 2] with normalized - coordinates in [0, 1]. - """ - with tf.name_scope(scope, 'ToNormalizedCoordinates'): - height = tf.cast(height, tf.float32) - width = tf.cast(width, tf.float32) - - if check_range: - max_val = tf.reduce_max(keypoints) - max_assert = tf.Assert(tf.greater(max_val, 1.01), - ['max value is lower than 1.01: ', max_val]) - with tf.control_dependencies([max_assert]): - width = tf.identity(width) - - return scale(keypoints, 1.0 / height, 1.0 / width) - - -def to_absolute_coordinates(keypoints, height, width, - check_range=True, scope=None): - """Converts normalized keypoint coordinates to absolute pixel coordinates. - - This function raises an assertion failed error when the maximum keypoint - coordinate value is larger than 1.01 (in which case coordinates are already - absolute). - - Args: - keypoints: A tensor of shape [num_instances, num_keypoints, 2] - height: Maximum value for y coordinate of absolute keypoint coordinates. - width: Maximum value for x coordinate of absolute keypoint coordinates. - check_range: If True, checks if the coordinates are normalized or not. - scope: name scope. - - Returns: - tensor of shape [num_instances, num_keypoints, 2] with absolute coordinates - in terms of the image size. - - """ - with tf.name_scope(scope, 'ToAbsoluteCoordinates'): - height = tf.cast(height, tf.float32) - width = tf.cast(width, tf.float32) - - # Ensure range of input keypoints is correct. - if check_range: - max_val = tf.reduce_max(keypoints) - max_assert = tf.Assert(tf.greater_equal(1.01, max_val), - ['maximum keypoint coordinate value is larger ' - 'than 1.01: ', max_val]) - with tf.control_dependencies([max_assert]): - width = tf.identity(width) - - return scale(keypoints, height, width) - - -def flip_horizontal(keypoints, flip_point, flip_permutation, scope=None): - """Flips the keypoints horizontally around the flip_point. - - This operation flips the x coordinate for each keypoint around the flip_point - and also permutes the keypoints in a manner specified by flip_permutation. - - Args: - keypoints: a tensor of shape [num_instances, num_keypoints, 2] - flip_point: (float) scalar tensor representing the x coordinate to flip the - keypoints around. - flip_permutation: rank 1 int32 tensor containing the keypoint flip - permutation. This specifies the mapping from original keypoint indices - to the flipped keypoint indices. This is used primarily for keypoints - that are not reflection invariant. E.g. Suppose there are 3 keypoints - representing ['head', 'right_eye', 'left_eye'], then a logical choice for - flip_permutation might be [0, 2, 1] since we want to swap the 'left_eye' - and 'right_eye' after a horizontal flip. - scope: name scope. - - Returns: - new_keypoints: a tensor of shape [num_instances, num_keypoints, 2] - """ - with tf.name_scope(scope, 'FlipHorizontal'): - keypoints = tf.transpose(keypoints, [1, 0, 2]) - keypoints = tf.gather(keypoints, flip_permutation) - v, u = tf.split(value=keypoints, num_or_size_splits=2, axis=2) - u = flip_point * 2.0 - u - new_keypoints = tf.concat([v, u], 2) - new_keypoints = tf.transpose(new_keypoints, [1, 0, 2]) - return new_keypoints - - -def flip_vertical(keypoints, flip_point, flip_permutation, scope=None): - """Flips the keypoints vertically around the flip_point. - - This operation flips the y coordinate for each keypoint around the flip_point - and also permutes the keypoints in a manner specified by flip_permutation. - - Args: - keypoints: a tensor of shape [num_instances, num_keypoints, 2] - flip_point: (float) scalar tensor representing the y coordinate to flip the - keypoints around. - flip_permutation: rank 1 int32 tensor containing the keypoint flip - permutation. This specifies the mapping from original keypoint indices - to the flipped keypoint indices. This is used primarily for keypoints - that are not reflection invariant. E.g. Suppose there are 3 keypoints - representing ['head', 'right_eye', 'left_eye'], then a logical choice for - flip_permutation might be [0, 2, 1] since we want to swap the 'left_eye' - and 'right_eye' after a horizontal flip. - scope: name scope. - - Returns: - new_keypoints: a tensor of shape [num_instances, num_keypoints, 2] - """ - with tf.name_scope(scope, 'FlipVertical'): - keypoints = tf.transpose(keypoints, [1, 0, 2]) - keypoints = tf.gather(keypoints, flip_permutation) - v, u = tf.split(value=keypoints, num_or_size_splits=2, axis=2) - v = flip_point * 2.0 - v - new_keypoints = tf.concat([v, u], 2) - new_keypoints = tf.transpose(new_keypoints, [1, 0, 2]) - return new_keypoints - - -def rot90(keypoints, scope=None): - """Rotates the keypoints counter-clockwise by 90 degrees. - - Args: - keypoints: a tensor of shape [num_instances, num_keypoints, 2] - scope: name scope. - - Returns: - new_keypoints: a tensor of shape [num_instances, num_keypoints, 2] - """ - with tf.name_scope(scope, 'Rot90'): - keypoints = tf.transpose(keypoints, [1, 0, 2]) - v, u = tf.split(value=keypoints[:, :, ::-1], num_or_size_splits=2, axis=2) - v = 1.0 - v - new_keypoints = tf.concat([v, u], 2) - new_keypoints = tf.transpose(new_keypoints, [1, 0, 2]) - return new_keypoints diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/keypoint_ops_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/keypoint_ops_test.py deleted file mode 100644 index 1c09c55aa..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/keypoint_ops_test.py +++ /dev/null @@ -1,200 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.keypoint_ops.""" -import numpy as np -import tensorflow as tf - -from object_detection.core import keypoint_ops - - -class KeypointOpsTest(tf.test.TestCase): - """Tests for common keypoint operations.""" - - def test_scale(self): - keypoints = tf.constant([ - [[0.0, 0.0], [100.0, 200.0]], - [[50.0, 120.0], [100.0, 140.0]] - ]) - y_scale = tf.constant(1.0 / 100) - x_scale = tf.constant(1.0 / 200) - - expected_keypoints = tf.constant([ - [[0., 0.], [1.0, 1.0]], - [[0.5, 0.6], [1.0, 0.7]] - ]) - output = keypoint_ops.scale(keypoints, y_scale, x_scale) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - def test_clip_to_window(self): - keypoints = tf.constant([ - [[0.25, 0.5], [0.75, 0.75]], - [[0.5, 0.0], [1.0, 1.0]] - ]) - window = tf.constant([0.25, 0.25, 0.75, 0.75]) - - expected_keypoints = tf.constant([ - [[0.25, 0.5], [0.75, 0.75]], - [[0.5, 0.25], [0.75, 0.75]] - ]) - output = keypoint_ops.clip_to_window(keypoints, window) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - def test_prune_outside_window(self): - keypoints = tf.constant([ - [[0.25, 0.5], [0.75, 0.75]], - [[0.5, 0.0], [1.0, 1.0]] - ]) - window = tf.constant([0.25, 0.25, 0.75, 0.75]) - - expected_keypoints = tf.constant([[[0.25, 0.5], [0.75, 0.75]], - [[np.nan, np.nan], [np.nan, np.nan]]]) - output = keypoint_ops.prune_outside_window(keypoints, window) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - def test_change_coordinate_frame(self): - keypoints = tf.constant([ - [[0.25, 0.5], [0.75, 0.75]], - [[0.5, 0.0], [1.0, 1.0]] - ]) - window = tf.constant([0.25, 0.25, 0.75, 0.75]) - - expected_keypoints = tf.constant([ - [[0, 0.5], [1.0, 1.0]], - [[0.5, -0.5], [1.5, 1.5]] - ]) - output = keypoint_ops.change_coordinate_frame(keypoints, window) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - def test_to_normalized_coordinates(self): - keypoints = tf.constant([ - [[10., 30.], [30., 45.]], - [[20., 0.], [40., 60.]] - ]) - output = keypoint_ops.to_normalized_coordinates( - keypoints, 40, 60) - expected_keypoints = tf.constant([ - [[0.25, 0.5], [0.75, 0.75]], - [[0.5, 0.0], [1.0, 1.0]] - ]) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - def test_to_normalized_coordinates_already_normalized(self): - keypoints = tf.constant([ - [[0.25, 0.5], [0.75, 0.75]], - [[0.5, 0.0], [1.0, 1.0]] - ]) - output = keypoint_ops.to_normalized_coordinates( - keypoints, 40, 60) - - with self.test_session() as sess: - with self.assertRaisesOpError('assertion failed'): - sess.run(output) - - def test_to_absolute_coordinates(self): - keypoints = tf.constant([ - [[0.25, 0.5], [0.75, 0.75]], - [[0.5, 0.0], [1.0, 1.0]] - ]) - output = keypoint_ops.to_absolute_coordinates( - keypoints, 40, 60) - expected_keypoints = tf.constant([ - [[10., 30.], [30., 45.]], - [[20., 0.], [40., 60.]] - ]) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - def test_to_absolute_coordinates_already_absolute(self): - keypoints = tf.constant([ - [[10., 30.], [30., 45.]], - [[20., 0.], [40., 60.]] - ]) - output = keypoint_ops.to_absolute_coordinates( - keypoints, 40, 60) - - with self.test_session() as sess: - with self.assertRaisesOpError('assertion failed'): - sess.run(output) - - def test_flip_horizontal(self): - keypoints = tf.constant([ - [[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]], - [[0.4, 0.4], [0.5, 0.5], [0.6, 0.6]] - ]) - flip_permutation = [0, 2, 1] - - expected_keypoints = tf.constant([ - [[0.1, 0.9], [0.3, 0.7], [0.2, 0.8]], - [[0.4, 0.6], [0.6, 0.4], [0.5, 0.5]], - ]) - output = keypoint_ops.flip_horizontal(keypoints, 0.5, flip_permutation) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - def test_flip_vertical(self): - keypoints = tf.constant([ - [[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]], - [[0.4, 0.4], [0.5, 0.5], [0.6, 0.6]] - ]) - flip_permutation = [0, 2, 1] - - expected_keypoints = tf.constant([ - [[0.9, 0.1], [0.7, 0.3], [0.8, 0.2]], - [[0.6, 0.4], [0.4, 0.6], [0.5, 0.5]], - ]) - output = keypoint_ops.flip_vertical(keypoints, 0.5, flip_permutation) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - def test_rot90(self): - keypoints = tf.constant([ - [[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]], - [[0.4, 0.6], [0.5, 0.6], [0.6, 0.7]] - ]) - expected_keypoints = tf.constant([ - [[0.9, 0.1], [0.8, 0.2], [0.7, 0.3]], - [[0.4, 0.4], [0.4, 0.5], [0.3, 0.6]], - ]) - output = keypoint_ops.rot90(keypoints) - - with self.test_session() as sess: - output_, expected_keypoints_ = sess.run([output, expected_keypoints]) - self.assertAllClose(output_, expected_keypoints_) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/losses.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/losses.py deleted file mode 100644 index 5471c955f..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/losses.py +++ /dev/null @@ -1,641 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Classification and regression loss functions for object detection. - -Localization losses: - * WeightedL2LocalizationLoss - * WeightedSmoothL1LocalizationLoss - * WeightedIOULocalizationLoss - -Classification losses: - * WeightedSigmoidClassificationLoss - * WeightedSoftmaxClassificationLoss - * WeightedSoftmaxClassificationAgainstLogitsLoss - * BootstrappedSigmoidClassificationLoss -""" -from abc import ABCMeta -from abc import abstractmethod - -import tensorflow as tf - -from object_detection.core import box_list -from object_detection.core import box_list_ops -from object_detection.utils import ops - -slim = tf.contrib.slim - - -class Loss(object): - """Abstract base class for loss functions.""" - __metaclass__ = ABCMeta - - def __call__(self, - prediction_tensor, - target_tensor, - ignore_nan_targets=False, - scope=None, - **params): - """Call the loss function. - - Args: - prediction_tensor: an N-d tensor of shape [batch, anchors, ...] - representing predicted quantities. - target_tensor: an N-d tensor of shape [batch, anchors, ...] representing - regression or classification targets. - ignore_nan_targets: whether to ignore nan targets in the loss computation. - E.g. can be used if the target tensor is missing groundtruth data that - shouldn't be factored into the loss. - scope: Op scope name. Defaults to 'Loss' if None. - **params: Additional keyword arguments for specific implementations of - the Loss. - - Returns: - loss: a tensor representing the value of the loss function. - """ - with tf.name_scope(scope, 'Loss', - [prediction_tensor, target_tensor, params]) as scope: - if ignore_nan_targets: - target_tensor = tf.where(tf.is_nan(target_tensor), - prediction_tensor, - target_tensor) - return self._compute_loss(prediction_tensor, target_tensor, **params) - - @abstractmethod - def _compute_loss(self, prediction_tensor, target_tensor, **params): - """Method to be overridden by implementations. - - Args: - prediction_tensor: a tensor representing predicted quantities - target_tensor: a tensor representing regression or classification targets - **params: Additional keyword arguments for specific implementations of - the Loss. - - Returns: - loss: an N-d tensor of shape [batch, anchors, ...] containing the loss per - anchor - """ - pass - - -class WeightedL2LocalizationLoss(Loss): - """L2 localization loss function with anchorwise output support. - - Loss[b,a] = .5 * ||weights[b,a] * (prediction[b,a,:] - target[b,a,:])||^2 - """ - - def _compute_loss(self, prediction_tensor, target_tensor, weights): - """Compute loss function. - - Args: - prediction_tensor: A float tensor of shape [batch_size, num_anchors, - code_size] representing the (encoded) predicted locations of objects. - target_tensor: A float tensor of shape [batch_size, num_anchors, - code_size] representing the regression targets - weights: a float tensor of shape [batch_size, num_anchors] - - Returns: - loss: a float tensor of shape [batch_size, num_anchors] tensor - representing the value of the loss function. - """ - weighted_diff = (prediction_tensor - target_tensor) * tf.expand_dims( - weights, 2) - square_diff = 0.5 * tf.square(weighted_diff) - return tf.reduce_sum(square_diff, 2) - - -class WeightedSmoothL1LocalizationLoss(Loss): - """Smooth L1 localization loss function aka Huber Loss.. - - The smooth L1_loss is defined elementwise as .5 x^2 if |x| <= delta and - 0.5 x^2 + delta * (|x|-delta) otherwise, where x is the difference between - predictions and target. - - See also Equation (3) in the Fast R-CNN paper by Ross Girshick (ICCV 2015) - """ - - def __init__(self, delta=1.0): - """Constructor. - - Args: - delta: delta for smooth L1 loss. - """ - self._delta = delta - - def _compute_loss(self, prediction_tensor, target_tensor, weights): - """Compute loss function. - - Args: - prediction_tensor: A float tensor of shape [batch_size, num_anchors, - code_size] representing the (encoded) predicted locations of objects. - target_tensor: A float tensor of shape [batch_size, num_anchors, - code_size] representing the regression targets - weights: a float tensor of shape [batch_size, num_anchors] - - Returns: - loss: a float tensor of shape [batch_size, num_anchors] tensor - representing the value of the loss function. - """ - return tf.reduce_sum(tf.losses.huber_loss( - target_tensor, - prediction_tensor, - delta=self._delta, - weights=tf.expand_dims(weights, axis=2), - loss_collection=None, - reduction=tf.losses.Reduction.NONE - ), axis=2) - - -class WeightedIOULocalizationLoss(Loss): - """IOU localization loss function. - - Sums the IOU for corresponding pairs of predicted/groundtruth boxes - and for each pair assign a loss of 1 - IOU. We then compute a weighted - sum over all pairs which is returned as the total loss. - """ - - def _compute_loss(self, prediction_tensor, target_tensor, weights): - """Compute loss function. - - Args: - prediction_tensor: A float tensor of shape [batch_size, num_anchors, 4] - representing the decoded predicted boxes - target_tensor: A float tensor of shape [batch_size, num_anchors, 4] - representing the decoded target boxes - weights: a float tensor of shape [batch_size, num_anchors] - - Returns: - loss: a float tensor of shape [batch_size, num_anchors] tensor - representing the value of the loss function. - """ - predicted_boxes = box_list.BoxList(tf.reshape(prediction_tensor, [-1, 4])) - target_boxes = box_list.BoxList(tf.reshape(target_tensor, [-1, 4])) - per_anchor_iou_loss = 1.0 - box_list_ops.matched_iou(predicted_boxes, - target_boxes) - return tf.reshape(weights, [-1]) * per_anchor_iou_loss - - -class WeightedSigmoidClassificationLoss(Loss): - """Sigmoid cross entropy classification loss function.""" - - def _compute_loss(self, - prediction_tensor, - target_tensor, - weights, - class_indices=None): - """Compute loss function. - - Args: - prediction_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing the predicted logits for each class - target_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing one-hot encoded classification targets - weights: a float tensor of shape [batch_size, num_anchors] - class_indices: (Optional) A 1-D integer tensor of class indices. - If provided, computes loss only for the specified class indices. - - Returns: - loss: a float tensor of shape [batch_size, num_anchors, num_classes] - representing the value of the loss function. - """ - weights = tf.expand_dims(weights, 2) - if class_indices is not None: - weights *= tf.reshape( - ops.indices_to_dense_vector(class_indices, - tf.shape(prediction_tensor)[2]), - [1, 1, -1]) - per_entry_cross_ent = (tf.nn.sigmoid_cross_entropy_with_logits( - labels=target_tensor, logits=prediction_tensor)) - return per_entry_cross_ent * weights - - -class SigmoidFocalClassificationLoss(Loss): - """Sigmoid focal cross entropy loss. - - Focal loss down-weights well classified examples and focusses on the hard - examples. See https://arxiv.org/pdf/1708.02002.pdf for the loss definition. - """ - - def __init__(self, gamma=2.0, alpha=0.25): - """Constructor. - - Args: - gamma: exponent of the modulating factor (1 - p_t) ^ gamma. - alpha: optional alpha weighting factor to balance positives vs negatives. - """ - self._alpha = alpha - self._gamma = gamma - - def _compute_loss(self, - prediction_tensor, - target_tensor, - weights, - class_indices=None): - """Compute loss function. - - Args: - prediction_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing the predicted logits for each class - target_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing one-hot encoded classification targets - weights: a float tensor of shape [batch_size, num_anchors] - class_indices: (Optional) A 1-D integer tensor of class indices. - If provided, computes loss only for the specified class indices. - - Returns: - loss: a float tensor of shape [batch_size, num_anchors, num_classes] - representing the value of the loss function. - """ - weights = tf.expand_dims(weights, 2) - if class_indices is not None: - weights *= tf.reshape( - ops.indices_to_dense_vector(class_indices, - tf.shape(prediction_tensor)[2]), - [1, 1, -1]) - per_entry_cross_ent = (tf.nn.sigmoid_cross_entropy_with_logits( - labels=target_tensor, logits=prediction_tensor)) - prediction_probabilities = tf.sigmoid(prediction_tensor) - p_t = ((target_tensor * prediction_probabilities) + - ((1 - target_tensor) * (1 - prediction_probabilities))) - modulating_factor = 1.0 - if self._gamma: - modulating_factor = tf.pow(1.0 - p_t, self._gamma) - alpha_weight_factor = 1.0 - if self._alpha is not None: - alpha_weight_factor = (target_tensor * self._alpha + - (1 - target_tensor) * (1 - self._alpha)) - focal_cross_entropy_loss = (modulating_factor * alpha_weight_factor * - per_entry_cross_ent) - return focal_cross_entropy_loss * weights - - -class WeightedSoftmaxClassificationLoss(Loss): - """Softmax loss function.""" - - def __init__(self, logit_scale=1.0): - """Constructor. - - Args: - logit_scale: When this value is high, the prediction is "diffused" and - when this value is low, the prediction is made peakier. - (default 1.0) - - """ - self._logit_scale = logit_scale - - def _compute_loss(self, prediction_tensor, target_tensor, weights): - """Compute loss function. - - Args: - prediction_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing the predicted logits for each class - target_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing one-hot encoded classification targets - weights: a float tensor of shape [batch_size, num_anchors] - - Returns: - loss: a float tensor of shape [batch_size, num_anchors] - representing the value of the loss function. - """ - num_classes = prediction_tensor.get_shape().as_list()[-1] - prediction_tensor = tf.divide( - prediction_tensor, self._logit_scale, name='scale_logit') - per_row_cross_ent = (tf.nn.softmax_cross_entropy_with_logits( - labels=tf.reshape(target_tensor, [-1, num_classes]), - logits=tf.reshape(prediction_tensor, [-1, num_classes]))) - return tf.reshape(per_row_cross_ent, tf.shape(weights)) * weights - - -class WeightedSoftmaxClassificationAgainstLogitsLoss(Loss): - """Softmax loss function against logits. - - Targets are expected to be provided in logits space instead of "one hot" or - "probability distribution" space. - """ - - def __init__(self, logit_scale=1.0): - """Constructor. - - Args: - logit_scale: When this value is high, the target is "diffused" and - when this value is low, the target is made peakier. - (default 1.0) - - """ - self._logit_scale = logit_scale - - def _scale_and_softmax_logits(self, logits): - """Scale logits then apply softmax.""" - scaled_logits = tf.divide(logits, self._logit_scale, name='scale_logits') - return tf.nn.softmax(scaled_logits, name='convert_scores') - - def _compute_loss(self, prediction_tensor, target_tensor, weights): - """Compute loss function. - - Args: - prediction_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing the predicted logits for each class - target_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing logit classification targets - weights: a float tensor of shape [batch_size, num_anchors] - - Returns: - loss: a float tensor of shape [batch_size, num_anchors] - representing the value of the loss function. - """ - num_classes = prediction_tensor.get_shape().as_list()[-1] - target_tensor = self._scale_and_softmax_logits(target_tensor) - prediction_tensor = tf.divide(prediction_tensor, self._logit_scale, - name='scale_logits') - - per_row_cross_ent = (tf.nn.softmax_cross_entropy_with_logits( - labels=tf.reshape(target_tensor, [-1, num_classes]), - logits=tf.reshape(prediction_tensor, [-1, num_classes]))) - return tf.reshape(per_row_cross_ent, tf.shape(weights)) * weights - - -class BootstrappedSigmoidClassificationLoss(Loss): - """Bootstrapped sigmoid cross entropy classification loss function. - - This loss uses a convex combination of training labels and the current model's - predictions as training targets in the classification loss. The idea is that - as the model improves over time, its predictions can be trusted more and we - can use these predictions to mitigate the damage of noisy/incorrect labels, - because incorrect labels are likely to be eventually highly inconsistent with - other stimuli predicted to have the same label by the model. - - In "soft" bootstrapping, we use all predicted class probabilities, whereas in - "hard" bootstrapping, we use the single class favored by the model. - - See also Training Deep Neural Networks On Noisy Labels with Bootstrapping by - Reed et al. (ICLR 2015). - """ - - def __init__(self, alpha, bootstrap_type='soft'): - """Constructor. - - Args: - alpha: a float32 scalar tensor between 0 and 1 representing interpolation - weight - bootstrap_type: set to either 'hard' or 'soft' (default) - - Raises: - ValueError: if bootstrap_type is not either 'hard' or 'soft' - """ - if bootstrap_type != 'hard' and bootstrap_type != 'soft': - raise ValueError('Unrecognized bootstrap_type: must be one of ' - '\'hard\' or \'soft.\'') - self._alpha = alpha - self._bootstrap_type = bootstrap_type - - def _compute_loss(self, prediction_tensor, target_tensor, weights): - """Compute loss function. - - Args: - prediction_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing the predicted logits for each class - target_tensor: A float tensor of shape [batch_size, num_anchors, - num_classes] representing one-hot encoded classification targets - weights: a float tensor of shape [batch_size, num_anchors] - - Returns: - loss: a float tensor of shape [batch_size, num_anchors, num_classes] - representing the value of the loss function. - """ - if self._bootstrap_type == 'soft': - bootstrap_target_tensor = self._alpha * target_tensor + ( - 1.0 - self._alpha) * tf.sigmoid(prediction_tensor) - else: - bootstrap_target_tensor = self._alpha * target_tensor + ( - 1.0 - self._alpha) * tf.cast( - tf.sigmoid(prediction_tensor) > 0.5, tf.float32) - per_entry_cross_ent = (tf.nn.sigmoid_cross_entropy_with_logits( - labels=bootstrap_target_tensor, logits=prediction_tensor)) - return per_entry_cross_ent * tf.expand_dims(weights, 2) - - -class HardExampleMiner(object): - """Hard example mining for regions in a list of images. - - Implements hard example mining to select a subset of regions to be - back-propagated. For each image, selects the regions with highest losses, - subject to the condition that a newly selected region cannot have - an IOU > iou_threshold with any of the previously selected regions. - This can be achieved by re-using a greedy non-maximum suppression algorithm. - A constraint on the number of negatives mined per positive region can also be - enforced. - - Reference papers: "Training Region-based Object Detectors with Online - Hard Example Mining" (CVPR 2016) by Srivastava et al., and - "SSD: Single Shot MultiBox Detector" (ECCV 2016) by Liu et al. - """ - - def __init__(self, - num_hard_examples=64, - iou_threshold=0.7, - loss_type='both', - cls_loss_weight=0.05, - loc_loss_weight=0.06, - max_negatives_per_positive=None, - min_negatives_per_image=0): - """Constructor. - - The hard example mining implemented by this class can replicate the behavior - in the two aforementioned papers (Srivastava et al., and Liu et al). - To replicate the A2 paper (Srivastava et al), num_hard_examples is set - to a fixed parameter (64 by default) and iou_threshold is set to .7 for - running non-max-suppression the predicted boxes prior to hard mining. - In order to replicate the SSD paper (Liu et al), num_hard_examples should - be set to None, max_negatives_per_positive should be 3 and iou_threshold - should be 1.0 (in order to effectively turn off NMS). - - Args: - num_hard_examples: maximum number of hard examples to be - selected per image (prior to enforcing max negative to positive ratio - constraint). If set to None, all examples obtained after NMS are - considered. - iou_threshold: minimum intersection over union for an example - to be discarded during NMS. - loss_type: use only classification losses ('cls', default), - localization losses ('loc') or both losses ('both'). - In the last case, cls_loss_weight and loc_loss_weight are used to - compute weighted sum of the two losses. - cls_loss_weight: weight for classification loss. - loc_loss_weight: weight for location loss. - max_negatives_per_positive: maximum number of negatives to retain for - each positive anchor. By default, num_negatives_per_positive is None, - which means that we do not enforce a prespecified negative:positive - ratio. Note also that num_negatives_per_positives can be a float - (and will be converted to be a float even if it is passed in otherwise). - min_negatives_per_image: minimum number of negative anchors to sample for - a given image. Setting this to a positive number allows sampling - negatives in an image without any positive anchors and thus not biased - towards at least one detection per image. - """ - self._num_hard_examples = num_hard_examples - self._iou_threshold = iou_threshold - self._loss_type = loss_type - self._cls_loss_weight = cls_loss_weight - self._loc_loss_weight = loc_loss_weight - self._max_negatives_per_positive = max_negatives_per_positive - self._min_negatives_per_image = min_negatives_per_image - if self._max_negatives_per_positive is not None: - self._max_negatives_per_positive = float(self._max_negatives_per_positive) - self._num_positives_list = None - self._num_negatives_list = None - - def __call__(self, - location_losses, - cls_losses, - decoded_boxlist_list, - match_list=None): - """Computes localization and classification losses after hard mining. - - Args: - location_losses: a float tensor of shape [num_images, num_anchors] - representing anchorwise localization losses. - cls_losses: a float tensor of shape [num_images, num_anchors] - representing anchorwise classification losses. - decoded_boxlist_list: a list of decoded BoxList representing location - predictions for each image. - match_list: an optional list of matcher.Match objects encoding the match - between anchors and groundtruth boxes for each image of the batch, - with rows of the Match objects corresponding to groundtruth boxes - and columns corresponding to anchors. Match objects in match_list are - used to reference which anchors are positive, negative or ignored. If - self._max_negatives_per_positive exists, these are then used to enforce - a prespecified negative to positive ratio. - - Returns: - mined_location_loss: a float scalar with sum of localization losses from - selected hard examples. - mined_cls_loss: a float scalar with sum of classification losses from - selected hard examples. - Raises: - ValueError: if location_losses, cls_losses and decoded_boxlist_list do - not have compatible shapes (i.e., they must correspond to the same - number of images). - ValueError: if match_list is specified but its length does not match - len(decoded_boxlist_list). - """ - mined_location_losses = [] - mined_cls_losses = [] - location_losses = tf.unstack(location_losses) - cls_losses = tf.unstack(cls_losses) - num_images = len(decoded_boxlist_list) - if not match_list: - match_list = num_images * [None] - if not len(location_losses) == len(decoded_boxlist_list) == len(cls_losses): - raise ValueError('location_losses, cls_losses and decoded_boxlist_list ' - 'do not have compatible shapes.') - if not isinstance(match_list, list): - raise ValueError('match_list must be a list.') - if len(match_list) != len(decoded_boxlist_list): - raise ValueError('match_list must either be None or have ' - 'length=len(decoded_boxlist_list).') - num_positives_list = [] - num_negatives_list = [] - for ind, detection_boxlist in enumerate(decoded_boxlist_list): - box_locations = detection_boxlist.get() - match = match_list[ind] - image_losses = cls_losses[ind] - if self._loss_type == 'loc': - image_losses = location_losses[ind] - elif self._loss_type == 'both': - image_losses *= self._cls_loss_weight - image_losses += location_losses[ind] * self._loc_loss_weight - if self._num_hard_examples is not None: - num_hard_examples = self._num_hard_examples - else: - num_hard_examples = detection_boxlist.num_boxes() - selected_indices = tf.image.non_max_suppression( - box_locations, image_losses, num_hard_examples, self._iou_threshold) - if self._max_negatives_per_positive is not None and match: - (selected_indices, num_positives, - num_negatives) = self._subsample_selection_to_desired_neg_pos_ratio( - selected_indices, match, self._max_negatives_per_positive, - self._min_negatives_per_image) - num_positives_list.append(num_positives) - num_negatives_list.append(num_negatives) - mined_location_losses.append( - tf.reduce_sum(tf.gather(location_losses[ind], selected_indices))) - mined_cls_losses.append( - tf.reduce_sum(tf.gather(cls_losses[ind], selected_indices))) - location_loss = tf.reduce_sum(tf.stack(mined_location_losses)) - cls_loss = tf.reduce_sum(tf.stack(mined_cls_losses)) - if match and self._max_negatives_per_positive: - self._num_positives_list = num_positives_list - self._num_negatives_list = num_negatives_list - return (location_loss, cls_loss) - - def summarize(self): - """Summarize the number of positives and negatives after mining.""" - if self._num_positives_list and self._num_negatives_list: - avg_num_positives = tf.reduce_mean(tf.to_float(self._num_positives_list)) - avg_num_negatives = tf.reduce_mean(tf.to_float(self._num_negatives_list)) - tf.summary.scalar('HardExampleMiner/NumPositives', avg_num_positives) - tf.summary.scalar('HardExampleMiner/NumNegatives', avg_num_negatives) - - def _subsample_selection_to_desired_neg_pos_ratio(self, - indices, - match, - max_negatives_per_positive, - min_negatives_per_image=0): - """Subsample a collection of selected indices to a desired neg:pos ratio. - - This function takes a subset of M indices (indexing into a large anchor - collection of N anchors where M=0, - meaning that column i is matched with row match_results[i]. - (2) match_results[i]=-1, meaning that column i is not matched. - (3) match_results[i]=-2, meaning that column i is ignored. - use_matmul_gather: Use matrix multiplication based gather instead of - standard tf.gather. (Default: False). - - Raises: - ValueError: if match_results does not have rank 1 or is not an - integer int32 scalar tensor - """ - if match_results.shape.ndims != 1: - raise ValueError('match_results should have rank 1') - if match_results.dtype != tf.int32: - raise ValueError('match_results should be an int32 or int64 scalar ' - 'tensor') - self._match_results = match_results - self._gather_op = tf.gather - if use_matmul_gather: - self._gather_op = ops.matmul_gather_on_zeroth_axis - - @property - def match_results(self): - """The accessor for match results. - - Returns: - the tensor which encodes the match results. - """ - return self._match_results - - def matched_column_indices(self): - """Returns column indices that match to some row. - - The indices returned by this op are always sorted in increasing order. - - Returns: - column_indices: int32 tensor of shape [K] with column indices. - """ - return self._reshape_and_cast(tf.where(tf.greater(self._match_results, -1))) - - def matched_column_indicator(self): - """Returns column indices that are matched. - - Returns: - column_indices: int32 tensor of shape [K] with column indices. - """ - return tf.greater_equal(self._match_results, 0) - - def num_matched_columns(self): - """Returns number (int32 scalar tensor) of matched columns.""" - return tf.size(self.matched_column_indices()) - - def unmatched_column_indices(self): - """Returns column indices that do not match any row. - - The indices returned by this op are always sorted in increasing order. - - Returns: - column_indices: int32 tensor of shape [K] with column indices. - """ - return self._reshape_and_cast(tf.where(tf.equal(self._match_results, -1))) - - def unmatched_column_indicator(self): - """Returns column indices that are unmatched. - - Returns: - column_indices: int32 tensor of shape [K] with column indices. - """ - return tf.equal(self._match_results, -1) - - def num_unmatched_columns(self): - """Returns number (int32 scalar tensor) of unmatched columns.""" - return tf.size(self.unmatched_column_indices()) - - def ignored_column_indices(self): - """Returns column indices that are ignored (neither Matched nor Unmatched). - - The indices returned by this op are always sorted in increasing order. - - Returns: - column_indices: int32 tensor of shape [K] with column indices. - """ - return self._reshape_and_cast(tf.where(self.ignored_column_indicator())) - - def ignored_column_indicator(self): - """Returns boolean column indicator where True means the colum is ignored. - - Returns: - column_indicator: boolean vector which is True for all ignored column - indices. - """ - return tf.equal(self._match_results, -2) - - def num_ignored_columns(self): - """Returns number (int32 scalar tensor) of matched columns.""" - return tf.size(self.ignored_column_indices()) - - def unmatched_or_ignored_column_indices(self): - """Returns column indices that are unmatched or ignored. - - The indices returned by this op are always sorted in increasing order. - - Returns: - column_indices: int32 tensor of shape [K] with column indices. - """ - return self._reshape_and_cast(tf.where(tf.greater(0, self._match_results))) - - def matched_row_indices(self): - """Returns row indices that match some column. - - The indices returned by this op are ordered so as to be in correspondence - with the output of matched_column_indicator(). For example if - self.matched_column_indicator() is [0,2], and self.matched_row_indices() is - [7, 3], then we know that column 0 was matched to row 7 and column 2 was - matched to row 3. - - Returns: - row_indices: int32 tensor of shape [K] with row indices. - """ - return self._reshape_and_cast( - self._gather_op(self._match_results, self.matched_column_indices())) - - def _reshape_and_cast(self, t): - return tf.cast(tf.reshape(t, [-1]), tf.int32) - - def gather_based_on_match(self, input_tensor, unmatched_value, - ignored_value): - """Gathers elements from `input_tensor` based on match results. - - For columns that are matched to a row, gathered_tensor[col] is set to - input_tensor[match_results[col]]. For columns that are unmatched, - gathered_tensor[col] is set to unmatched_value. Finally, for columns that - are ignored gathered_tensor[col] is set to ignored_value. - - Note that the input_tensor.shape[1:] must match with unmatched_value.shape - and ignored_value.shape - - Args: - input_tensor: Tensor to gather values from. - unmatched_value: Constant tensor value for unmatched columns. - ignored_value: Constant tensor value for ignored columns. - - Returns: - gathered_tensor: A tensor containing values gathered from input_tensor. - The shape of the gathered tensor is [match_results.shape[0]] + - input_tensor.shape[1:]. - """ - input_tensor = tf.concat([tf.stack([ignored_value, unmatched_value]), - input_tensor], axis=0) - gather_indices = tf.maximum(self.match_results + 2, 0) - gathered_tensor = self._gather_op(input_tensor, gather_indices) - return gathered_tensor - - -class Matcher(object): - """Abstract base class for matcher. - """ - __metaclass__ = ABCMeta - - def __init__(self, use_matmul_gather=False): - """Constructs a Matcher. - - Args: - use_matmul_gather: Force constructed match objects to use matrix - multiplication based gather instead of standard tf.gather. - (Default: False). - """ - self._use_matmul_gather = use_matmul_gather - - def match(self, similarity_matrix, scope=None, **params): - """Computes matches among row and column indices and returns the result. - - Computes matches among the row and column indices based on the similarity - matrix and optional arguments. - - Args: - similarity_matrix: Float tensor of shape [N, M] with pairwise similarity - where higher value means more similar. - scope: Op scope name. Defaults to 'Match' if None. - **params: Additional keyword arguments for specific implementations of - the Matcher. - - Returns: - A Match object with the results of matching. - """ - with tf.name_scope(scope, 'Match', [similarity_matrix, params]) as scope: - return Match(self._match(similarity_matrix, **params), - self._use_matmul_gather) - - @abstractmethod - def _match(self, similarity_matrix, **params): - """Method to be overridden by implementations. - - Args: - similarity_matrix: Float tensor of shape [N, M] with pairwise similarity - where higher value means more similar. - **params: Additional keyword arguments for specific implementations of - the Matcher. - - Returns: - match_results: Integer tensor of shape [M]: match_results[i]>=0 means - that column i is matched to row match_results[i], match_results[i]=-1 - means that the column is not matched. match_results[i]=-2 means that - the column is ignored (usually this happens when there is a very weak - match which one neither wants as positive nor negative example). - """ - pass diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/matcher_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/matcher_test.py deleted file mode 100644 index 05607834a..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/matcher_test.py +++ /dev/null @@ -1,192 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.matcher.""" -import numpy as np -import tensorflow as tf - -from object_detection.core import matcher - - -class MatchTest(tf.test.TestCase): - - def test_get_correct_matched_columnIndices(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - expected_column_indices = [0, 1, 3, 5] - matched_column_indices = match.matched_column_indices() - self.assertEquals(matched_column_indices.dtype, tf.int32) - with self.test_session() as sess: - matched_column_indices = sess.run(matched_column_indices) - self.assertAllEqual(matched_column_indices, expected_column_indices) - - def test_get_correct_counts(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - exp_num_matched_columns = 4 - exp_num_unmatched_columns = 2 - exp_num_ignored_columns = 1 - num_matched_columns = match.num_matched_columns() - num_unmatched_columns = match.num_unmatched_columns() - num_ignored_columns = match.num_ignored_columns() - self.assertEquals(num_matched_columns.dtype, tf.int32) - self.assertEquals(num_unmatched_columns.dtype, tf.int32) - self.assertEquals(num_ignored_columns.dtype, tf.int32) - with self.test_session() as sess: - (num_matched_columns_out, num_unmatched_columns_out, - num_ignored_columns_out) = sess.run( - [num_matched_columns, num_unmatched_columns, num_ignored_columns]) - self.assertAllEqual(num_matched_columns_out, exp_num_matched_columns) - self.assertAllEqual(num_unmatched_columns_out, exp_num_unmatched_columns) - self.assertAllEqual(num_ignored_columns_out, exp_num_ignored_columns) - - def testGetCorrectUnmatchedColumnIndices(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - expected_column_indices = [2, 4] - unmatched_column_indices = match.unmatched_column_indices() - self.assertEquals(unmatched_column_indices.dtype, tf.int32) - with self.test_session() as sess: - unmatched_column_indices = sess.run(unmatched_column_indices) - self.assertAllEqual(unmatched_column_indices, expected_column_indices) - - def testGetCorrectMatchedRowIndices(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - expected_row_indices = [3, 1, 0, 5] - matched_row_indices = match.matched_row_indices() - self.assertEquals(matched_row_indices.dtype, tf.int32) - with self.test_session() as sess: - matched_row_inds = sess.run(matched_row_indices) - self.assertAllEqual(matched_row_inds, expected_row_indices) - - def test_get_correct_ignored_column_indices(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - expected_column_indices = [6] - ignored_column_indices = match.ignored_column_indices() - self.assertEquals(ignored_column_indices.dtype, tf.int32) - with self.test_session() as sess: - ignored_column_indices = sess.run(ignored_column_indices) - self.assertAllEqual(ignored_column_indices, expected_column_indices) - - def test_get_correct_matched_column_indicator(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - expected_column_indicator = [True, True, False, True, False, True, False] - matched_column_indicator = match.matched_column_indicator() - self.assertEquals(matched_column_indicator.dtype, tf.bool) - with self.test_session() as sess: - matched_column_indicator = sess.run(matched_column_indicator) - self.assertAllEqual(matched_column_indicator, expected_column_indicator) - - def test_get_correct_unmatched_column_indicator(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - expected_column_indicator = [False, False, True, False, True, False, False] - unmatched_column_indicator = match.unmatched_column_indicator() - self.assertEquals(unmatched_column_indicator.dtype, tf.bool) - with self.test_session() as sess: - unmatched_column_indicator = sess.run(unmatched_column_indicator) - self.assertAllEqual(unmatched_column_indicator, expected_column_indicator) - - def test_get_correct_ignored_column_indicator(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - expected_column_indicator = [False, False, False, False, False, False, True] - ignored_column_indicator = match.ignored_column_indicator() - self.assertEquals(ignored_column_indicator.dtype, tf.bool) - with self.test_session() as sess: - ignored_column_indicator = sess.run(ignored_column_indicator) - self.assertAllEqual(ignored_column_indicator, expected_column_indicator) - - def test_get_correct_unmatched_ignored_column_indices(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - match = matcher.Match(match_results) - expected_column_indices = [2, 4, 6] - unmatched_ignored_column_indices = (match. - unmatched_or_ignored_column_indices()) - self.assertEquals(unmatched_ignored_column_indices.dtype, tf.int32) - with self.test_session() as sess: - unmatched_ignored_column_indices = sess.run( - unmatched_ignored_column_indices) - self.assertAllEqual(unmatched_ignored_column_indices, - expected_column_indices) - - def test_all_columns_accounted_for(self): - # Note: deliberately setting to small number so not always - # all possibilities appear (matched, unmatched, ignored) - num_matches = 10 - match_results = tf.random_uniform( - [num_matches], minval=-2, maxval=5, dtype=tf.int32) - match = matcher.Match(match_results) - matched_column_indices = match.matched_column_indices() - unmatched_column_indices = match.unmatched_column_indices() - ignored_column_indices = match.ignored_column_indices() - with self.test_session() as sess: - matched, unmatched, ignored = sess.run([ - matched_column_indices, unmatched_column_indices, - ignored_column_indices - ]) - all_indices = np.hstack((matched, unmatched, ignored)) - all_indices_sorted = np.sort(all_indices) - self.assertAllEqual(all_indices_sorted, - np.arange(num_matches, dtype=np.int32)) - - def test_scalar_gather_based_on_match(self): - match_results = tf.constant([3, 1, -1, 0, -1, 5, -2]) - input_tensor = tf.constant([0, 1, 2, 3, 4, 5, 6, 7], dtype=tf.float32) - expected_gathered_tensor = [3, 1, 100, 0, 100, 5, 200] - match = matcher.Match(match_results) - gathered_tensor = match.gather_based_on_match(input_tensor, - unmatched_value=100., - ignored_value=200.) - self.assertEquals(gathered_tensor.dtype, tf.float32) - with self.test_session(): - gathered_tensor_out = gathered_tensor.eval() - self.assertAllEqual(expected_gathered_tensor, gathered_tensor_out) - - def test_multidimensional_gather_based_on_match(self): - match_results = tf.constant([1, -1, -2]) - input_tensor = tf.constant([[0, 0.5, 0, 0.5], [0, 0, 0.5, 0.5]], - dtype=tf.float32) - expected_gathered_tensor = [[0, 0, 0.5, 0.5], [0, 0, 0, 0], [0, 0, 0, 0]] - match = matcher.Match(match_results) - gathered_tensor = match.gather_based_on_match(input_tensor, - unmatched_value=tf.zeros(4), - ignored_value=tf.zeros(4)) - self.assertEquals(gathered_tensor.dtype, tf.float32) - with self.test_session(): - gathered_tensor_out = gathered_tensor.eval() - self.assertAllEqual(expected_gathered_tensor, gathered_tensor_out) - - def test_multidimensional_gather_based_on_match_with_matmul_gather_op(self): - match_results = tf.constant([1, -1, -2]) - input_tensor = tf.constant([[0, 0.5, 0, 0.5], [0, 0, 0.5, 0.5]], - dtype=tf.float32) - expected_gathered_tensor = [[0, 0, 0.5, 0.5], [0, 0, 0, 0], [0, 0, 0, 0]] - match = matcher.Match(match_results, use_matmul_gather=True) - gathered_tensor = match.gather_based_on_match(input_tensor, - unmatched_value=tf.zeros(4), - ignored_value=tf.zeros(4)) - self.assertEquals(gathered_tensor.dtype, tf.float32) - with self.test_session() as sess: - self.assertTrue( - all([op.name is not 'Gather' for op in sess.graph.get_operations()])) - gathered_tensor_out = gathered_tensor.eval() - self.assertAllEqual(expected_gathered_tensor, gathered_tensor_out) - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/minibatch_sampler.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/minibatch_sampler.py deleted file mode 100644 index dc622221a..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/minibatch_sampler.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Base minibatch sampler module. - -The job of the minibatch_sampler is to subsample a minibatch based on some -criterion. - -The main function call is: - subsample(indicator, batch_size, **params). -Indicator is a 1d boolean tensor where True denotes which examples can be -sampled. It returns a boolean indicator where True denotes an example has been -sampled.. - -Subclasses should implement the Subsample function and can make use of the -@staticmethod SubsampleIndicator. -""" - -from abc import ABCMeta -from abc import abstractmethod - -import tensorflow as tf - -from object_detection.utils import ops - - -class MinibatchSampler(object): - """Abstract base class for subsampling minibatches.""" - __metaclass__ = ABCMeta - - def __init__(self): - """Constructs a minibatch sampler.""" - pass - - @abstractmethod - def subsample(self, indicator, batch_size, **params): - """Returns subsample of entries in indicator. - - Args: - indicator: boolean tensor of shape [N] whose True entries can be sampled. - batch_size: desired batch size. - **params: additional keyword arguments for specific implementations of - the MinibatchSampler. - - Returns: - sample_indicator: boolean tensor of shape [N] whose True entries have been - sampled. If sum(indicator) >= batch_size, sum(is_sampled) = batch_size - """ - pass - - @staticmethod - def subsample_indicator(indicator, num_samples): - """Subsample indicator vector. - - Given a boolean indicator vector with M elements set to `True`, the function - assigns all but `num_samples` of these previously `True` elements to - `False`. If `num_samples` is greater than M, the original indicator vector - is returned. - - Args: - indicator: a 1-dimensional boolean tensor indicating which elements - are allowed to be sampled and which are not. - num_samples: int32 scalar tensor - - Returns: - a boolean tensor with the same shape as input (indicator) tensor - """ - indices = tf.where(indicator) - indices = tf.random_shuffle(indices) - indices = tf.reshape(indices, [-1]) - - num_samples = tf.minimum(tf.size(indices), num_samples) - selected_indices = tf.slice(indices, [0], tf.reshape(num_samples, [1])) - - selected_indicator = ops.indices_to_dense_vector(selected_indices, - tf.shape(indicator)[0]) - - return tf.equal(selected_indicator, 1) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/minibatch_sampler_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/minibatch_sampler_test.py deleted file mode 100644 index 7420ae5d0..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/minibatch_sampler_test.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for google3.research.vale.object_detection.minibatch_sampler.""" - -import numpy as np -import tensorflow as tf - -from object_detection.core import minibatch_sampler - - -class MinibatchSamplerTest(tf.test.TestCase): - - def test_subsample_indicator_when_more_true_elements_than_num_samples(self): - np_indicator = [True, False, True, False, True, True, False] - indicator = tf.constant(np_indicator) - samples = minibatch_sampler.MinibatchSampler.subsample_indicator( - indicator, 3) - with self.test_session() as sess: - samples_out = sess.run(samples) - self.assertTrue(np.sum(samples_out), 3) - self.assertAllEqual(samples_out, - np.logical_and(samples_out, np_indicator)) - - def test_subsample_when_more_true_elements_than_num_samples_no_shape(self): - np_indicator = [True, False, True, False, True, True, False] - indicator = tf.placeholder(tf.bool) - feed_dict = {indicator: np_indicator} - - samples = minibatch_sampler.MinibatchSampler.subsample_indicator( - indicator, 3) - with self.test_session() as sess: - samples_out = sess.run(samples, feed_dict=feed_dict) - self.assertTrue(np.sum(samples_out), 3) - self.assertAllEqual(samples_out, - np.logical_and(samples_out, np_indicator)) - - def test_subsample_indicator_when_less_true_elements_than_num_samples(self): - np_indicator = [True, False, True, False, True, True, False] - indicator = tf.constant(np_indicator) - samples = minibatch_sampler.MinibatchSampler.subsample_indicator( - indicator, 5) - with self.test_session() as sess: - samples_out = sess.run(samples) - self.assertTrue(np.sum(samples_out), 4) - self.assertAllEqual(samples_out, - np.logical_and(samples_out, np_indicator)) - - def test_subsample_indicator_when_num_samples_is_zero(self): - np_indicator = [True, False, True, False, True, True, False] - indicator = tf.constant(np_indicator) - samples_none = minibatch_sampler.MinibatchSampler.subsample_indicator( - indicator, 0) - with self.test_session() as sess: - samples_none_out = sess.run(samples_none) - self.assertAllEqual( - np.zeros_like(samples_none_out, dtype=bool), - samples_none_out) - - def test_subsample_indicator_when_indicator_all_false(self): - indicator_empty = tf.zeros([0], dtype=tf.bool) - samples_empty = minibatch_sampler.MinibatchSampler.subsample_indicator( - indicator_empty, 4) - with self.test_session() as sess: - samples_empty_out = sess.run(samples_empty) - self.assertEqual(0, samples_empty_out.size) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/model.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/model.py deleted file mode 100644 index 081136f9c..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/model.py +++ /dev/null @@ -1,305 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Abstract detection model. - -This file defines a generic base class for detection models. Programs that are -designed to work with arbitrary detection models should only depend on this -class. We intend for the functions in this class to follow tensor-in/tensor-out -design, thus all functions have tensors or lists/dictionaries holding tensors as -inputs and outputs. - -Abstractly, detection models predict output tensors given input images -which can be passed to a loss function at training time or passed to a -postprocessing function at eval time. The computation graphs at a high level -consequently look as follows: - -Training time: -inputs (images tensor) -> preprocess -> predict -> loss -> outputs (loss tensor) - -Evaluation time: -inputs (images tensor) -> preprocess -> predict -> postprocess - -> outputs (boxes tensor, scores tensor, classes tensor, num_detections tensor) - -DetectionModels must thus implement four functions (1) preprocess, (2) predict, -(3) postprocess and (4) loss. DetectionModels should make no assumptions about -the input size or aspect ratio --- they are responsible for doing any -resize/reshaping necessary (see docstring for the preprocess function). -Output classes are always integers in the range [0, num_classes). Any mapping -of these integers to semantic labels is to be handled outside of this class. - -Images are resized in the `preprocess` method. All of `preprocess`, `predict`, -and `postprocess` should be reentrant. - -The `preprocess` method runs `image_resizer_fn` that returns resized_images and -`true_image_shapes`. Since `image_resizer_fn` can pad the images with zeros, -true_image_shapes indicate the slices that contain the image without padding. -This is useful for padding images to be a fixed size for batching. - -The `postprocess` method uses the true image shapes to clip predictions that lie -outside of images. - -By default, DetectionModels produce bounding box detections; However, we support -a handful of auxiliary annotations associated with each bounding box, namely, -instance masks and keypoints. -""" -from abc import ABCMeta -from abc import abstractmethod - -from object_detection.core import standard_fields as fields - - -class DetectionModel(object): - """Abstract base class for detection models.""" - __metaclass__ = ABCMeta - - def __init__(self, num_classes): - """Constructor. - - Args: - num_classes: number of classes. Note that num_classes *does not* include - background categories that might be implicitly predicted in various - implementations. - """ - self._num_classes = num_classes - self._groundtruth_lists = {} - - @property - def num_classes(self): - return self._num_classes - - def groundtruth_lists(self, field): - """Access list of groundtruth tensors. - - Args: - field: a string key, options are - fields.BoxListFields.{boxes,classes,masks,keypoints} - - Returns: - a list of tensors holding groundtruth information (see also - provide_groundtruth function below), with one entry for each image in the - batch. - Raises: - RuntimeError: if the field has not been provided via provide_groundtruth. - """ - if field not in self._groundtruth_lists: - raise RuntimeError('Groundtruth tensor %s has not been provided', field) - return self._groundtruth_lists[field] - - def groundtruth_has_field(self, field): - """Determines whether the groundtruth includes the given field. - - Args: - field: a string key, options are - fields.BoxListFields.{boxes,classes,masks,keypoints} - - Returns: - True if the groundtruth includes the given field, False otherwise. - """ - return field in self._groundtruth_lists - - @abstractmethod - def preprocess(self, inputs): - """Input preprocessing. - - To be overridden by implementations. - - This function is responsible for any scaling/shifting of input values that - is necessary prior to running the detector on an input image. - It is also responsible for any resizing, padding that might be necessary - as images are assumed to arrive in arbitrary sizes. While this function - could conceivably be part of the predict method (below), it is often - convenient to keep these separate --- for example, we may want to preprocess - on one device, place onto a queue, and let another device (e.g., the GPU) - handle prediction. - - A few important notes about the preprocess function: - + We assume that this operation does not have any trainable variables nor - does it affect the groundtruth annotations in any way (thus data - augmentation operations such as random cropping should be performed - externally). - + There is no assumption that the batchsize in this function is the same as - the batch size in the predict function. In fact, we recommend calling the - preprocess function prior to calling any batching operations (which should - happen outside of the model) and thus assuming that batch sizes are equal - to 1 in the preprocess function. - + There is also no explicit assumption that the output resolutions - must be fixed across inputs --- this is to support "fully convolutional" - settings in which input images can have different shapes/resolutions. - - Args: - inputs: a [batch, height_in, width_in, channels] float32 tensor - representing a batch of images with values between 0 and 255.0. - - Returns: - preprocessed_inputs: a [batch, height_out, width_out, channels] float32 - tensor representing a batch of images. - true_image_shapes: int32 tensor of shape [batch, 3] where each row is - of the form [height, width, channels] indicating the shapes - of true images in the resized images, as resized images can be padded - with zeros. - """ - pass - - @abstractmethod - def predict(self, preprocessed_inputs, true_image_shapes): - """Predict prediction tensors from inputs tensor. - - Outputs of this function can be passed to loss or postprocess functions. - - Args: - preprocessed_inputs: a [batch, height, width, channels] float32 tensor - representing a batch of images. - true_image_shapes: int32 tensor of shape [batch, 3] where each row is - of the form [height, width, channels] indicating the shapes - of true images in the resized images, as resized images can be padded - with zeros. - - Returns: - prediction_dict: a dictionary holding prediction tensors to be - passed to the Loss or Postprocess functions. - """ - pass - - @abstractmethod - def postprocess(self, prediction_dict, true_image_shapes, **params): - """Convert predicted output tensors to final detections. - - Outputs adhere to the following conventions: - * Classes are integers in [0, num_classes); background classes are removed - and the first non-background class is mapped to 0. If the model produces - class-agnostic detections, then no output is produced for classes. - * Boxes are to be interpreted as being in [y_min, x_min, y_max, x_max] - format and normalized relative to the image window. - * `num_detections` is provided for settings where detections are padded to a - fixed number of boxes. - * We do not specifically assume any kind of probabilistic interpretation - of the scores --- the only important thing is their relative ordering. - Thus implementations of the postprocess function are free to output - logits, probabilities, calibrated probabilities, or anything else. - - Args: - prediction_dict: a dictionary holding prediction tensors. - true_image_shapes: int32 tensor of shape [batch, 3] where each row is - of the form [height, width, channels] indicating the shapes - of true images in the resized images, as resized images can be padded - with zeros. - **params: Additional keyword arguments for specific implementations of - DetectionModel. - - Returns: - detections: a dictionary containing the following fields - detection_boxes: [batch, max_detections, 4] - detection_scores: [batch, max_detections] - detection_classes: [batch, max_detections] - (If a model is producing class-agnostic detections, this field may be - missing) - instance_masks: [batch, max_detections, image_height, image_width] - (optional) - keypoints: [batch, max_detections, num_keypoints, 2] (optional) - num_detections: [batch] - """ - pass - - @abstractmethod - def loss(self, prediction_dict, true_image_shapes): - """Compute scalar loss tensors with respect to provided groundtruth. - - Calling this function requires that groundtruth tensors have been - provided via the provide_groundtruth function. - - Args: - prediction_dict: a dictionary holding predicted tensors - true_image_shapes: int32 tensor of shape [batch, 3] where each row is - of the form [height, width, channels] indicating the shapes - of true images in the resized images, as resized images can be padded - with zeros. - - Returns: - a dictionary mapping strings (loss names) to scalar tensors representing - loss values. - """ - pass - - def provide_groundtruth(self, - groundtruth_boxes_list, - groundtruth_classes_list, - groundtruth_masks_list=None, - groundtruth_keypoints_list=None, - groundtruth_weights_list=None, - groundtruth_is_crowd_list=None): - """Provide groundtruth tensors. - - Args: - groundtruth_boxes_list: a list of 2-D tf.float32 tensors of shape - [num_boxes, 4] containing coordinates of the groundtruth boxes. - Groundtruth boxes are provided in [y_min, x_min, y_max, x_max] - format and assumed to be normalized and clipped - relative to the image window with y_min <= y_max and x_min <= x_max. - groundtruth_classes_list: a list of 2-D tf.float32 one-hot (or k-hot) - tensors of shape [num_boxes, num_classes] containing the class targets - with the 0th index assumed to map to the first non-background class. - groundtruth_masks_list: a list of 3-D tf.float32 tensors of - shape [num_boxes, height_in, width_in] containing instance - masks with values in {0, 1}. If None, no masks are provided. - Mask resolution `height_in`x`width_in` must agree with the resolution - of the input image tensor provided to the `preprocess` function. - groundtruth_keypoints_list: a list of 3-D tf.float32 tensors of - shape [num_boxes, num_keypoints, 2] containing keypoints. - Keypoints are assumed to be provided in normalized coordinates and - missing keypoints should be encoded as NaN. - groundtruth_weights_list: A list of 1-D tf.float32 tensors of shape - [num_boxes] containing weights for groundtruth boxes. - groundtruth_is_crowd_list: A list of 1-D tf.bool tensors of shape - [num_boxes] containing is_crowd annotations - """ - self._groundtruth_lists[fields.BoxListFields.boxes] = groundtruth_boxes_list - self._groundtruth_lists[ - fields.BoxListFields.classes] = groundtruth_classes_list - if groundtruth_weights_list: - self._groundtruth_lists[fields.BoxListFields. - weights] = groundtruth_weights_list - if groundtruth_masks_list: - self._groundtruth_lists[ - fields.BoxListFields.masks] = groundtruth_masks_list - if groundtruth_keypoints_list: - self._groundtruth_lists[ - fields.BoxListFields.keypoints] = groundtruth_keypoints_list - if groundtruth_is_crowd_list: - self._groundtruth_lists[ - fields.BoxListFields.is_crowd] = groundtruth_is_crowd_list - - @abstractmethod - def restore_map(self, fine_tune_checkpoint_type='detection'): - """Returns a map of variables to load from a foreign checkpoint. - - Returns a map of variable names to load from a checkpoint to variables in - the model graph. This enables the model to initialize based on weights from - another task. For example, the feature extractor variables from a - classification model can be used to bootstrap training of an object - detector. When loading from an object detection model, the checkpoint model - should have the same parameters as this detection model with exception of - the num_classes parameter. - - Args: - fine_tune_checkpoint_type: whether to restore from a full detection - checkpoint (with compatible variable names) or to restore from a - classification checkpoint for initialization prior to training. - Valid values: `detection`, `classification`. Default 'detection'. - - Returns: - A dict mapping variable names (to load from a checkpoint) to variables in - the model graph. - """ - pass diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/post_processing.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/post_processing.py deleted file mode 100644 index bbc61f66f..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/post_processing.py +++ /dev/null @@ -1,425 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Post-processing operations on detected boxes.""" - -import tensorflow as tf - -from object_detection.core import box_list -from object_detection.core import box_list_ops -from object_detection.core import standard_fields as fields -from object_detection.utils import shape_utils - - -def multiclass_non_max_suppression(boxes, - scores, - score_thresh, - iou_thresh, - max_size_per_class, - max_total_size=0, - clip_window=None, - change_coordinate_frame=False, - masks=None, - boundaries=None, - additional_fields=None, - scope=None): - """Multi-class version of non maximum suppression. - - This op greedily selects a subset of detection bounding boxes, pruning - away boxes that have high IOU (intersection over union) overlap (> thresh) - with already selected boxes. It operates independently for each class for - which scores are provided (via the scores field of the input box_list), - pruning boxes with score less than a provided threshold prior to - applying NMS. - - Please note that this operation is performed on *all* classes, therefore any - background classes should be removed prior to calling this function. - - Args: - boxes: A [k, q, 4] float32 tensor containing k detections. `q` can be either - number of classes or 1 depending on whether a separate box is predicted - per class. - scores: A [k, num_classes] float32 tensor containing the scores for each of - the k detections. - score_thresh: scalar threshold for score (low scoring boxes are removed). - iou_thresh: scalar threshold for IOU (new boxes that have high IOU overlap - with previously selected boxes are removed). - max_size_per_class: maximum number of retained boxes per class. - max_total_size: maximum number of boxes retained over all classes. By - default returns all boxes retained after capping boxes per class. - clip_window: A float32 tensor of the form [y_min, x_min, y_max, x_max] - representing the window to clip and normalize boxes to before performing - non-max suppression. - change_coordinate_frame: Whether to normalize coordinates after clipping - relative to clip_window (this can only be set to True if a clip_window - is provided) - masks: (optional) a [k, q, mask_height, mask_width] float32 tensor - containing box masks. `q` can be either number of classes or 1 depending - on whether a separate mask is predicted per class. - boundaries: (optional) a [k, q, boundary_height, boundary_width] float32 - tensor containing box boundaries. `q` can be either number of classes or 1 - depending on whether a separate boundary is predicted per class. - additional_fields: (optional) If not None, a dictionary that maps keys to - tensors whose first dimensions are all of size `k`. After non-maximum - suppression, all tensors corresponding to the selected boxes will be - added to resulting BoxList. - scope: name scope. - - Returns: - a BoxList holding M boxes with a rank-1 scores field representing - corresponding scores for each box with scores sorted in decreasing order - and a rank-1 classes field representing a class label for each box. - - Raises: - ValueError: if iou_thresh is not in [0, 1] or if input boxlist does not have - a valid scores field. - """ - if not 0 <= iou_thresh <= 1.0: - raise ValueError('iou_thresh must be between 0 and 1') - if scores.shape.ndims != 2: - raise ValueError('scores field must be of rank 2') - if scores.shape[1].value is None: - raise ValueError('scores must have statically defined second ' - 'dimension') - if boxes.shape.ndims != 3: - raise ValueError('boxes must be of rank 3.') - if not (boxes.shape[1].value == scores.shape[1].value or - boxes.shape[1].value == 1): - raise ValueError('second dimension of boxes must be either 1 or equal ' - 'to the second dimension of scores') - if boxes.shape[2].value != 4: - raise ValueError('last dimension of boxes must be of size 4.') - if change_coordinate_frame and clip_window is None: - raise ValueError('if change_coordinate_frame is True, then a clip_window' - 'must be specified.') - - with tf.name_scope(scope, 'MultiClassNonMaxSuppression'): - num_boxes = tf.shape(boxes)[0] - num_scores = tf.shape(scores)[0] - num_classes = scores.get_shape()[1] - - length_assert = tf.Assert( - tf.equal(num_boxes, num_scores), - ['Incorrect scores field length: actual vs expected.', - num_scores, num_boxes]) - - selected_boxes_list = [] - per_class_boxes_list = tf.unstack(boxes, axis=1) - if masks is not None: - per_class_masks_list = tf.unstack(masks, axis=1) - if boundaries is not None: - per_class_boundaries_list = tf.unstack(boundaries, axis=1) - boxes_ids = (range(num_classes) if len(per_class_boxes_list) > 1 - else [0] * num_classes.value) - for class_idx, boxes_idx in zip(range(num_classes), boxes_ids): - per_class_boxes = per_class_boxes_list[boxes_idx] - boxlist_and_class_scores = box_list.BoxList(per_class_boxes) - with tf.control_dependencies([length_assert]): - class_scores = tf.reshape( - tf.slice(scores, [0, class_idx], tf.stack([num_scores, 1])), [-1]) - boxlist_and_class_scores.add_field(fields.BoxListFields.scores, - class_scores) - if masks is not None: - per_class_masks = per_class_masks_list[boxes_idx] - boxlist_and_class_scores.add_field(fields.BoxListFields.masks, - per_class_masks) - if boundaries is not None: - per_class_boundaries = per_class_boundaries_list[boxes_idx] - boxlist_and_class_scores.add_field(fields.BoxListFields.boundaries, - per_class_boundaries) - if additional_fields is not None: - for key, tensor in additional_fields.items(): - boxlist_and_class_scores.add_field(key, tensor) - boxlist_filtered = box_list_ops.filter_greater_than( - boxlist_and_class_scores, score_thresh) - if clip_window is not None: - boxlist_filtered = box_list_ops.clip_to_window( - boxlist_filtered, clip_window) - if change_coordinate_frame: - boxlist_filtered = box_list_ops.change_coordinate_frame( - boxlist_filtered, clip_window) - max_selection_size = tf.minimum(max_size_per_class, - boxlist_filtered.num_boxes()) - selected_indices = tf.image.non_max_suppression( - boxlist_filtered.get(), - boxlist_filtered.get_field(fields.BoxListFields.scores), - max_selection_size, - iou_threshold=iou_thresh) - nms_result = box_list_ops.gather(boxlist_filtered, selected_indices) - nms_result.add_field( - fields.BoxListFields.classes, (tf.zeros_like( - nms_result.get_field(fields.BoxListFields.scores)) + class_idx)) - selected_boxes_list.append(nms_result) - selected_boxes = box_list_ops.concatenate(selected_boxes_list) - sorted_boxes = box_list_ops.sort_by_field(selected_boxes, - fields.BoxListFields.scores) - if max_total_size: - max_total_size = tf.minimum(max_total_size, - sorted_boxes.num_boxes()) - sorted_boxes = box_list_ops.gather(sorted_boxes, - tf.range(max_total_size)) - return sorted_boxes - - -def batch_multiclass_non_max_suppression(boxes, - scores, - score_thresh, - iou_thresh, - max_size_per_class, - max_total_size=0, - clip_window=None, - change_coordinate_frame=False, - num_valid_boxes=None, - masks=None, - additional_fields=None, - scope=None, - parallel_iterations=32): - """Multi-class version of non maximum suppression that operates on a batch. - - This op is similar to `multiclass_non_max_suppression` but operates on a batch - of boxes and scores. See documentation for `multiclass_non_max_suppression` - for details. - - Args: - boxes: A [batch_size, num_anchors, q, 4] float32 tensor containing - detections. If `q` is 1 then same boxes are used for all classes - otherwise, if `q` is equal to number of classes, class-specific boxes - are used. - scores: A [batch_size, num_anchors, num_classes] float32 tensor containing - the scores for each of the `num_anchors` detections. - score_thresh: scalar threshold for score (low scoring boxes are removed). - iou_thresh: scalar threshold for IOU (new boxes that have high IOU overlap - with previously selected boxes are removed). - max_size_per_class: maximum number of retained boxes per class. - max_total_size: maximum number of boxes retained over all classes. By - default returns all boxes retained after capping boxes per class. - clip_window: A float32 tensor of shape [batch_size, 4] where each entry is - of the form [y_min, x_min, y_max, x_max] representing the window to clip - boxes to before performing non-max suppression. This argument can also be - a tensor of shape [4] in which case, the same clip window is applied to - all images in the batch. If clip_widow is None, all boxes are used to - perform non-max suppression. - change_coordinate_frame: Whether to normalize coordinates after clipping - relative to clip_window (this can only be set to True if a clip_window - is provided) - num_valid_boxes: (optional) a Tensor of type `int32`. A 1-D tensor of shape - [batch_size] representing the number of valid boxes to be considered - for each image in the batch. This parameter allows for ignoring zero - paddings. - masks: (optional) a [batch_size, num_anchors, q, mask_height, mask_width] - float32 tensor containing box masks. `q` can be either number of classes - or 1 depending on whether a separate mask is predicted per class. - additional_fields: (optional) If not None, a dictionary that maps keys to - tensors whose dimensions are [batch_size, num_anchors, ...]. - scope: tf scope name. - parallel_iterations: (optional) number of batch items to process in - parallel. - - Returns: - 'nmsed_boxes': A [batch_size, max_detections, 4] float32 tensor - containing the non-max suppressed boxes. - 'nmsed_scores': A [batch_size, max_detections] float32 tensor containing - the scores for the boxes. - 'nmsed_classes': A [batch_size, max_detections] float32 tensor - containing the class for boxes. - 'nmsed_masks': (optional) a - [batch_size, max_detections, mask_height, mask_width] float32 tensor - containing masks for each selected box. This is set to None if input - `masks` is None. - 'nmsed_additional_fields': (optional) a dictionary of - [batch_size, max_detections, ...] float32 tensors corresponding to the - tensors specified in the input `additional_fields`. This is not returned - if input `additional_fields` is None. - 'num_detections': A [batch_size] int32 tensor indicating the number of - valid detections per batch item. Only the top num_detections[i] entries in - nms_boxes[i], nms_scores[i] and nms_class[i] are valid. The rest of the - entries are zero paddings. - - Raises: - ValueError: if `q` in boxes.shape is not 1 or not equal to number of - classes as inferred from scores.shape. - """ - q = boxes.shape[2].value - num_classes = scores.shape[2].value - if q != 1 and q != num_classes: - raise ValueError('third dimension of boxes must be either 1 or equal ' - 'to the third dimension of scores') - if change_coordinate_frame and clip_window is None: - raise ValueError('if change_coordinate_frame is True, then a clip_window' - 'must be specified.') - original_masks = masks - original_additional_fields = additional_fields - with tf.name_scope(scope, 'BatchMultiClassNonMaxSuppression'): - boxes_shape = boxes.shape - batch_size = boxes_shape[0].value - num_anchors = boxes_shape[1].value - - if batch_size is None: - batch_size = tf.shape(boxes)[0] - if num_anchors is None: - num_anchors = tf.shape(boxes)[1] - - # If num valid boxes aren't provided, create one and mark all boxes as - # valid. - if num_valid_boxes is None: - num_valid_boxes = tf.ones([batch_size], dtype=tf.int32) * num_anchors - - # If masks aren't provided, create dummy masks so we can only have one copy - # of _single_image_nms_fn and discard the dummy masks after map_fn. - if masks is None: - masks_shape = tf.stack([batch_size, num_anchors, 1, 0, 0]) - masks = tf.zeros(masks_shape) - - if clip_window is None: - clip_window = tf.stack([ - tf.reduce_min(boxes[:, :, :, 0]), - tf.reduce_min(boxes[:, :, :, 1]), - tf.reduce_max(boxes[:, :, :, 2]), - tf.reduce_max(boxes[:, :, :, 3]) - ]) - if clip_window.shape.ndims == 1: - clip_window = tf.tile(tf.expand_dims(clip_window, 0), [batch_size, 1]) - - if additional_fields is None: - additional_fields = {} - - def _single_image_nms_fn(args): - """Runs NMS on a single image and returns padded output. - - Args: - args: A list of tensors consisting of the following: - per_image_boxes - A [num_anchors, q, 4] float32 tensor containing - detections. If `q` is 1 then same boxes are used for all classes - otherwise, if `q` is equal to number of classes, class-specific - boxes are used. - per_image_scores - A [num_anchors, num_classes] float32 tensor - containing the scores for each of the `num_anchors` detections. - per_image_masks - A [num_anchors, q, mask_height, mask_width] float32 - tensor containing box masks. `q` can be either number of classes - or 1 depending on whether a separate mask is predicted per class. - per_image_clip_window - A 1D float32 tensor of the form - [ymin, xmin, ymax, xmax] representing the window to clip the boxes - to. - per_image_additional_fields - (optional) A variable number of float32 - tensors each with size [num_anchors, ...]. - per_image_num_valid_boxes - A tensor of type `int32`. A 1-D tensor of - shape [batch_size] representing the number of valid boxes to be - considered for each image in the batch. This parameter allows for - ignoring zero paddings. - - Returns: - 'nmsed_boxes': A [max_detections, 4] float32 tensor containing the - non-max suppressed boxes. - 'nmsed_scores': A [max_detections] float32 tensor containing the scores - for the boxes. - 'nmsed_classes': A [max_detections] float32 tensor containing the class - for boxes. - 'nmsed_masks': (optional) a [max_detections, mask_height, mask_width] - float32 tensor containing masks for each selected box. This is set to - None if input `masks` is None. - 'nmsed_additional_fields': (optional) A variable number of float32 - tensors each with size [max_detections, ...] corresponding to the - input `per_image_additional_fields`. - 'num_detections': A [batch_size] int32 tensor indicating the number of - valid detections per batch item. Only the top num_detections[i] - entries in nms_boxes[i], nms_scores[i] and nms_class[i] are valid. The - rest of the entries are zero paddings. - """ - per_image_boxes = args[0] - per_image_scores = args[1] - per_image_masks = args[2] - per_image_clip_window = args[3] - per_image_additional_fields = { - key: value - for key, value in zip(additional_fields, args[4:-1]) - } - per_image_num_valid_boxes = args[-1] - per_image_boxes = tf.reshape( - tf.slice(per_image_boxes, 3 * [0], - tf.stack([per_image_num_valid_boxes, -1, -1])), [-1, q, 4]) - per_image_scores = tf.reshape( - tf.slice(per_image_scores, [0, 0], - tf.stack([per_image_num_valid_boxes, -1])), - [-1, num_classes]) - per_image_masks = tf.reshape( - tf.slice(per_image_masks, 4 * [0], - tf.stack([per_image_num_valid_boxes, -1, -1, -1])), - [-1, q, per_image_masks.shape[2].value, - per_image_masks.shape[3].value]) - if per_image_additional_fields is not None: - for key, tensor in per_image_additional_fields.items(): - additional_field_shape = tensor.get_shape() - additional_field_dim = len(additional_field_shape) - per_image_additional_fields[key] = tf.reshape( - tf.slice(per_image_additional_fields[key], - additional_field_dim * [0], - tf.stack([per_image_num_valid_boxes] + - (additional_field_dim - 1) * [-1])), - [-1] + [dim.value for dim in additional_field_shape[1:]]) - nmsed_boxlist = multiclass_non_max_suppression( - per_image_boxes, - per_image_scores, - score_thresh, - iou_thresh, - max_size_per_class, - max_total_size, - clip_window=per_image_clip_window, - change_coordinate_frame=change_coordinate_frame, - masks=per_image_masks, - additional_fields=per_image_additional_fields) - padded_boxlist = box_list_ops.pad_or_clip_box_list(nmsed_boxlist, - max_total_size) - num_detections = nmsed_boxlist.num_boxes() - nmsed_boxes = padded_boxlist.get() - nmsed_scores = padded_boxlist.get_field(fields.BoxListFields.scores) - nmsed_classes = padded_boxlist.get_field(fields.BoxListFields.classes) - nmsed_masks = padded_boxlist.get_field(fields.BoxListFields.masks) - nmsed_additional_fields = [ - padded_boxlist.get_field(key) for key in per_image_additional_fields - ] - return ([nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks] + - nmsed_additional_fields + [num_detections]) - - num_additional_fields = 0 - if additional_fields is not None: - num_additional_fields = len(additional_fields) - num_nmsed_outputs = 4 + num_additional_fields - - batch_outputs = shape_utils.static_or_dynamic_map_fn( - _single_image_nms_fn, - elems=([boxes, scores, masks, clip_window] + - list(additional_fields.values()) + [num_valid_boxes]), - dtype=(num_nmsed_outputs * [tf.float32] + [tf.int32]), - parallel_iterations=parallel_iterations) - - batch_nmsed_boxes = batch_outputs[0] - batch_nmsed_scores = batch_outputs[1] - batch_nmsed_classes = batch_outputs[2] - batch_nmsed_masks = batch_outputs[3] - batch_nmsed_additional_fields = { - key: value - for key, value in zip(additional_fields, batch_outputs[4:-1]) - } - batch_num_detections = batch_outputs[-1] - - if original_masks is None: - batch_nmsed_masks = None - - if original_additional_fields is None: - batch_nmsed_additional_fields = None - - return (batch_nmsed_boxes, batch_nmsed_scores, batch_nmsed_classes, - batch_nmsed_masks, batch_nmsed_additional_fields, - batch_num_detections) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/post_processing_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/post_processing_test.py deleted file mode 100644 index 967413996..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/post_processing_test.py +++ /dev/null @@ -1,1078 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for tensorflow_models.object_detection.core.post_processing.""" -import numpy as np -import tensorflow as tf -from object_detection.core import post_processing -from object_detection.core import standard_fields as fields - - -class MulticlassNonMaxSuppressionTest(tf.test.TestCase): - - def test_with_invalid_scores_size(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]]], tf.float32) - scores = tf.constant([[.9], [.75], [.6], [.95], [.5]]) - iou_thresh = .5 - score_thresh = 0.6 - max_output_size = 3 - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size) - with self.test_session() as sess: - with self.assertRaisesWithPredicateMatch( - tf.errors.InvalidArgumentError, 'Incorrect scores field length'): - sess.run(nms.get()) - - def test_multiclass_nms_select_with_shared_boxes(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]], - [[0, 1000, 1, 1002]], - [[0, 1000, 1, 1002.1]]], tf.float32) - scores = tf.constant([[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 1000, 1, 1002], - [0, 100, 1, 101]] - exp_nms_scores = [.95, .9, .85, .3] - exp_nms_classes = [0, 0, 1, 0] - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size) - with self.test_session() as sess: - nms_corners_output, nms_scores_output, nms_classes_output = sess.run( - [nms.get(), nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes)]) - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - - def test_multiclass_nms_select_with_shared_boxes_given_keypoints(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]], - [[0, 1000, 1, 1002]], - [[0, 1000, 1, 1002.1]]], tf.float32) - scores = tf.constant([[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]) - num_keypoints = 6 - keypoints = tf.tile( - tf.reshape(tf.range(8), [8, 1, 1]), - [1, num_keypoints, 2]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 1000, 1, 1002], - [0, 100, 1, 101]] - exp_nms_scores = [.95, .9, .85, .3] - exp_nms_classes = [0, 0, 1, 0] - exp_nms_keypoints_tensor = tf.tile( - tf.reshape(tf.constant([3, 0, 6, 5], dtype=tf.float32), [4, 1, 1]), - [1, num_keypoints, 2]) - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size, - additional_fields={ - fields.BoxListFields.keypoints: keypoints}) - - with self.test_session() as sess: - (nms_corners_output, - nms_scores_output, - nms_classes_output, - nms_keypoints, - exp_nms_keypoints) = sess.run([ - nms.get(), - nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes), - nms.get_field(fields.BoxListFields.keypoints), - exp_nms_keypoints_tensor - ]) - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - self.assertAllEqual(nms_keypoints, exp_nms_keypoints) - - def test_multiclass_nms_with_shared_boxes_given_keypoint_heatmaps(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]], - [[0, 1000, 1, 1002]], - [[0, 1000, 1, 1002.1]]], tf.float32) - - scores = tf.constant([[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]) - - num_boxes = tf.shape(boxes)[0] - heatmap_height = 5 - heatmap_width = 5 - num_keypoints = 17 - keypoint_heatmaps = tf.ones( - [num_boxes, heatmap_height, heatmap_width, num_keypoints], - dtype=tf.float32) - - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - exp_nms_corners = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 1000, 1, 1002], - [0, 100, 1, 101]] - - exp_nms_scores = [.95, .9, .85, .3] - exp_nms_classes = [0, 0, 1, 0] - exp_nms_keypoint_heatmaps = np.ones( - (4, heatmap_height, heatmap_width, num_keypoints), dtype=np.float32) - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size, - additional_fields={ - fields.BoxListFields.keypoint_heatmaps: keypoint_heatmaps}) - - with self.test_session() as sess: - (nms_corners_output, - nms_scores_output, - nms_classes_output, - nms_keypoint_heatmaps) = sess.run( - [nms.get(), - nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes), - nms.get_field(fields.BoxListFields.keypoint_heatmaps)]) - - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - self.assertAllEqual(nms_keypoint_heatmaps, exp_nms_keypoint_heatmaps) - - def test_multiclass_nms_with_additional_fields(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]], - [[0, 1000, 1, 1002]], - [[0, 1000, 1, 1002.1]]], tf.float32) - - scores = tf.constant([[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]) - - coarse_boxes_key = 'coarse_boxes' - coarse_boxes = tf.constant([[0.1, 0.1, 1.1, 1.1], - [0.1, 0.2, 1.1, 1.2], - [0.1, -0.2, 1.1, 1.0], - [0.1, 10.1, 1.1, 11.1], - [0.1, 10.2, 1.1, 11.2], - [0.1, 100.1, 1.1, 101.1], - [0.1, 1000.1, 1.1, 1002.1], - [0.1, 1000.1, 1.1, 1002.2]], tf.float32) - - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = np.array([[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 1000, 1, 1002], - [0, 100, 1, 101]], dtype=np.float32) - - exp_nms_coarse_corners = np.array([[0.1, 10.1, 1.1, 11.1], - [0.1, 0.1, 1.1, 1.1], - [0.1, 1000.1, 1.1, 1002.1], - [0.1, 100.1, 1.1, 101.1]], - dtype=np.float32) - - exp_nms_scores = [.95, .9, .85, .3] - exp_nms_classes = [0, 0, 1, 0] - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size, - additional_fields={coarse_boxes_key: coarse_boxes}) - - with self.test_session() as sess: - (nms_corners_output, - nms_scores_output, - nms_classes_output, - nms_coarse_corners) = sess.run( - [nms.get(), - nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes), - nms.get_field(coarse_boxes_key)]) - - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - self.assertAllEqual(nms_coarse_corners, exp_nms_coarse_corners) - - def test_multiclass_nms_select_with_shared_boxes_given_masks(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]], - [[0, 1000, 1, 1002]], - [[0, 1000, 1, 1002.1]]], tf.float32) - scores = tf.constant([[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]) - num_classes = 2 - mask_height = 3 - mask_width = 3 - masks = tf.tile( - tf.reshape(tf.range(8), [8, 1, 1, 1]), - [1, num_classes, mask_height, mask_width]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 1000, 1, 1002], - [0, 100, 1, 101]] - exp_nms_scores = [.95, .9, .85, .3] - exp_nms_classes = [0, 0, 1, 0] - exp_nms_masks_tensor = tf.tile( - tf.reshape(tf.constant([3, 0, 6, 5], dtype=tf.float32), [4, 1, 1]), - [1, mask_height, mask_width]) - - nms = post_processing.multiclass_non_max_suppression(boxes, scores, - score_thresh, - iou_thresh, - max_output_size, - masks=masks) - with self.test_session() as sess: - (nms_corners_output, - nms_scores_output, - nms_classes_output, - nms_masks, - exp_nms_masks) = sess.run([nms.get(), - nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes), - nms.get_field(fields.BoxListFields.masks), - exp_nms_masks_tensor]) - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - self.assertAllEqual(nms_masks, exp_nms_masks) - - def test_multiclass_nms_select_with_clip_window(self): - boxes = tf.constant([[[0, 0, 10, 10]], - [[1, 1, 11, 11]]], tf.float32) - scores = tf.constant([[.9], [.75]]) - clip_window = tf.constant([5, 4, 8, 7], tf.float32) - score_thresh = 0.0 - iou_thresh = 0.5 - max_output_size = 100 - - exp_nms_corners = [[5, 4, 8, 7]] - exp_nms_scores = [.9] - exp_nms_classes = [0] - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size, - clip_window=clip_window) - with self.test_session() as sess: - nms_corners_output, nms_scores_output, nms_classes_output = sess.run( - [nms.get(), nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes)]) - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - - def test_multiclass_nms_select_with_clip_window_change_coordinate_frame(self): - boxes = tf.constant([[[0, 0, 10, 10]], - [[1, 1, 11, 11]]], tf.float32) - scores = tf.constant([[.9], [.75]]) - clip_window = tf.constant([5, 4, 8, 7], tf.float32) - score_thresh = 0.0 - iou_thresh = 0.5 - max_output_size = 100 - - exp_nms_corners = [[0, 0, 1, 1]] - exp_nms_scores = [.9] - exp_nms_classes = [0] - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size, - clip_window=clip_window, change_coordinate_frame=True) - with self.test_session() as sess: - nms_corners_output, nms_scores_output, nms_classes_output = sess.run( - [nms.get(), nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes)]) - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - - def test_multiclass_nms_select_with_per_class_cap(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]], - [[0, 1000, 1, 1002]], - [[0, 1000, 1, 1002.1]]], tf.float32) - scores = tf.constant([[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]) - score_thresh = 0.1 - iou_thresh = .5 - max_size_per_class = 2 - - exp_nms_corners = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 1000, 1, 1002]] - exp_nms_scores = [.95, .9, .85] - exp_nms_classes = [0, 0, 1] - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_size_per_class) - with self.test_session() as sess: - nms_corners_output, nms_scores_output, nms_classes_output = sess.run( - [nms.get(), nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes)]) - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - - def test_multiclass_nms_select_with_total_cap(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]], - [[0, 1000, 1, 1002]], - [[0, 1000, 1, 1002.1]]], tf.float32) - scores = tf.constant([[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]) - score_thresh = 0.1 - iou_thresh = .5 - max_size_per_class = 4 - max_total_size = 2 - - exp_nms_corners = [[0, 10, 1, 11], - [0, 0, 1, 1]] - exp_nms_scores = [.95, .9] - exp_nms_classes = [0, 0] - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_size_per_class, - max_total_size) - with self.test_session() as sess: - nms_corners_output, nms_scores_output, nms_classes_output = sess.run( - [nms.get(), nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes)]) - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - - def test_multiclass_nms_threshold_then_select_with_shared_boxes(self): - boxes = tf.constant([[[0, 0, 1, 1]], - [[0, 0.1, 1, 1.1]], - [[0, -0.1, 1, 0.9]], - [[0, 10, 1, 11]], - [[0, 10.1, 1, 11.1]], - [[0, 100, 1, 101]], - [[0, 1000, 1, 1002]], - [[0, 1000, 1, 1002.1]]], tf.float32) - scores = tf.constant([[.9], [.75], [.6], [.95], [.5], [.3], [.01], [.01]]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 3 - - exp_nms = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 100, 1, 101]] - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size) - with self.test_session() as sess: - nms_output = sess.run(nms.get()) - self.assertAllClose(nms_output, exp_nms) - - def test_multiclass_nms_select_with_separate_boxes(self): - boxes = tf.constant([[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]], - [[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]], - tf.float32) - scores = tf.constant([[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = [[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 999, 2, 1004], - [0, 100, 1, 101]] - exp_nms_scores = [.95, .9, .85, .3] - exp_nms_classes = [0, 0, 1, 0] - - nms = post_processing.multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, max_output_size) - with self.test_session() as sess: - nms_corners_output, nms_scores_output, nms_classes_output = sess.run( - [nms.get(), nms.get_field(fields.BoxListFields.scores), - nms.get_field(fields.BoxListFields.classes)]) - self.assertAllClose(nms_corners_output, exp_nms_corners) - self.assertAllClose(nms_scores_output, exp_nms_scores) - self.assertAllClose(nms_classes_output, exp_nms_classes) - - def test_batch_multiclass_nms_with_batch_size_1(self): - boxes = tf.constant([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]], - [[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]], - tf.float32) - scores = tf.constant([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0], - [.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = [[[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 999, 2, 1004], - [0, 100, 1, 101]]] - exp_nms_scores = [[.95, .9, .85, .3]] - exp_nms_classes = [[0, 0, 1, 0]] - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size) - - self.assertIsNone(nmsed_masks) - self.assertIsNone(nmsed_additional_fields) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - num_detections]) - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - self.assertEqual(num_detections, [4]) - - def test_batch_multiclass_nms_with_batch_size_2(self): - boxes = tf.constant([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]]], - [[[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]], - tf.float32) - scores = tf.constant([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0]], - [[.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = np.array([[[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[0, 999, 2, 1004], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101], - [0, 0, 0, 0]]]) - exp_nms_scores = np.array([[.95, .9, 0, 0], - [.85, .5, .3, 0]]) - exp_nms_classes = np.array([[0, 0, 0, 0], - [1, 0, 0, 0]]) - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size) - - self.assertIsNone(nmsed_masks) - self.assertIsNone(nmsed_additional_fields) - # Check static shapes - self.assertAllEqual(nmsed_boxes.shape.as_list(), - exp_nms_corners.shape) - self.assertAllEqual(nmsed_scores.shape.as_list(), - exp_nms_scores.shape) - self.assertAllEqual(nmsed_classes.shape.as_list(), - exp_nms_classes.shape) - self.assertEqual(num_detections.shape.as_list(), [2]) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - num_detections]) - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - self.assertAllClose(num_detections, [2, 3]) - - def test_batch_multiclass_nms_with_per_batch_clip_window(self): - boxes = tf.constant([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]]], - [[[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]], - tf.float32) - scores = tf.constant([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0]], - [[.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - clip_window = tf.constant([0., 0., 200., 200.]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = np.array([[[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[0, 10.1, 1, 11.1], - [0, 100, 1, 101], - [0, 0, 0, 0], - [0, 0, 0, 0]]]) - exp_nms_scores = np.array([[.95, .9, 0, 0], - [.5, .3, 0, 0]]) - exp_nms_classes = np.array([[0, 0, 0, 0], - [0, 0, 0, 0]]) - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size, - clip_window=clip_window) - - self.assertIsNone(nmsed_masks) - self.assertIsNone(nmsed_additional_fields) - # Check static shapes - self.assertAllEqual(nmsed_boxes.shape.as_list(), - exp_nms_corners.shape) - self.assertAllEqual(nmsed_scores.shape.as_list(), - exp_nms_scores.shape) - self.assertAllEqual(nmsed_classes.shape.as_list(), - exp_nms_classes.shape) - self.assertEqual(num_detections.shape.as_list(), [2]) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - num_detections]) - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - self.assertAllClose(num_detections, [2, 2]) - - def test_batch_multiclass_nms_with_per_image_clip_window(self): - boxes = tf.constant([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]]], - [[[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]], - tf.float32) - scores = tf.constant([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0]], - [[.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - clip_window = tf.constant([[0., 0., 5., 5.], - [0., 0., 200., 200.]]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = np.array([[[0, 0, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[0, 10.1, 1, 11.1], - [0, 100, 1, 101], - [0, 0, 0, 0], - [0, 0, 0, 0]]]) - exp_nms_scores = np.array([[.9, 0., 0., 0.], - [.5, .3, 0, 0]]) - exp_nms_classes = np.array([[0, 0, 0, 0], - [0, 0, 0, 0]]) - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size, - clip_window=clip_window) - - self.assertIsNone(nmsed_masks) - self.assertIsNone(nmsed_additional_fields) - # Check static shapes - self.assertAllEqual(nmsed_boxes.shape.as_list(), - exp_nms_corners.shape) - self.assertAllEqual(nmsed_scores.shape.as_list(), - exp_nms_scores.shape) - self.assertAllEqual(nmsed_classes.shape.as_list(), - exp_nms_classes.shape) - self.assertEqual(num_detections.shape.as_list(), [2]) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - num_detections]) - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - self.assertAllClose(num_detections, [1, 2]) - - def test_batch_multiclass_nms_with_masks(self): - boxes = tf.constant([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]]], - [[[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]], - tf.float32) - scores = tf.constant([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0]], - [[.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - masks = tf.constant([[[[[0, 1], [2, 3]], [[1, 2], [3, 4]]], - [[[2, 3], [4, 5]], [[3, 4], [5, 6]]], - [[[4, 5], [6, 7]], [[5, 6], [7, 8]]], - [[[6, 7], [8, 9]], [[7, 8], [9, 10]]]], - [[[[8, 9], [10, 11]], [[9, 10], [11, 12]]], - [[[10, 11], [12, 13]], [[11, 12], [13, 14]]], - [[[12, 13], [14, 15]], [[13, 14], [15, 16]]], - [[[14, 15], [16, 17]], [[15, 16], [17, 18]]]]], - tf.float32) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = np.array([[[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[0, 999, 2, 1004], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101], - [0, 0, 0, 0]]]) - exp_nms_scores = np.array([[.95, .9, 0, 0], - [.85, .5, .3, 0]]) - exp_nms_classes = np.array([[0, 0, 0, 0], - [1, 0, 0, 0]]) - exp_nms_masks = np.array([[[[6, 7], [8, 9]], - [[0, 1], [2, 3]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]], - [[[13, 14], [15, 16]], - [[8, 9], [10, 11]], - [[10, 11], [12, 13]], - [[0, 0], [0, 0]]]]) - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size, - masks=masks) - - self.assertIsNone(nmsed_additional_fields) - # Check static shapes - self.assertAllEqual(nmsed_boxes.shape.as_list(), exp_nms_corners.shape) - self.assertAllEqual(nmsed_scores.shape.as_list(), exp_nms_scores.shape) - self.assertAllEqual(nmsed_classes.shape.as_list(), exp_nms_classes.shape) - self.assertAllEqual(nmsed_masks.shape.as_list(), exp_nms_masks.shape) - self.assertEqual(num_detections.shape.as_list(), [2]) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - nmsed_masks, num_detections]) - - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - self.assertAllClose(num_detections, [2, 3]) - self.assertAllClose(nmsed_masks, exp_nms_masks) - - def test_batch_multiclass_nms_with_additional_fields(self): - boxes = tf.constant([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]]], - [[[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]], - tf.float32) - scores = tf.constant([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0]], - [[.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - additional_fields = { - 'keypoints': tf.constant( - [[[[6, 7], [8, 9]], - [[0, 1], [2, 3]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]], - [[[13, 14], [15, 16]], - [[8, 9], [10, 11]], - [[10, 11], [12, 13]], - [[0, 0], [0, 0]]]], - tf.float32) - } - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = np.array([[[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[0, 999, 2, 1004], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101], - [0, 0, 0, 0]]]) - exp_nms_scores = np.array([[.95, .9, 0, 0], - [.85, .5, .3, 0]]) - exp_nms_classes = np.array([[0, 0, 0, 0], - [1, 0, 0, 0]]) - exp_nms_additional_fields = { - 'keypoints': np.array([[[[0, 0], [0, 0]], - [[6, 7], [8, 9]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]], - [[[10, 11], [12, 13]], - [[13, 14], [15, 16]], - [[8, 9], [10, 11]], - [[0, 0], [0, 0]]]]) - } - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size, - additional_fields=additional_fields) - - self.assertIsNone(nmsed_masks) - # Check static shapes - self.assertAllEqual(nmsed_boxes.shape.as_list(), exp_nms_corners.shape) - self.assertAllEqual(nmsed_scores.shape.as_list(), exp_nms_scores.shape) - self.assertAllEqual(nmsed_classes.shape.as_list(), exp_nms_classes.shape) - self.assertEqual(len(nmsed_additional_fields), - len(exp_nms_additional_fields)) - for key in exp_nms_additional_fields: - self.assertAllEqual(nmsed_additional_fields[key].shape.as_list(), - exp_nms_additional_fields[key].shape) - self.assertEqual(num_detections.shape.as_list(), [2]) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_additional_fields, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - nmsed_additional_fields, num_detections]) - - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - for key in exp_nms_additional_fields: - self.assertAllClose(nmsed_additional_fields[key], - exp_nms_additional_fields[key]) - self.assertAllClose(num_detections, [2, 3]) - - def test_batch_multiclass_nms_with_dynamic_batch_size(self): - boxes_placeholder = tf.placeholder(tf.float32, shape=(None, None, 2, 4)) - scores_placeholder = tf.placeholder(tf.float32, shape=(None, None, 2)) - masks_placeholder = tf.placeholder(tf.float32, shape=(None, None, 2, 2, 2)) - - boxes = np.array([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]]], - [[[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]]) - scores = np.array([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0]], - [[.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - masks = np.array([[[[[0, 1], [2, 3]], [[1, 2], [3, 4]]], - [[[2, 3], [4, 5]], [[3, 4], [5, 6]]], - [[[4, 5], [6, 7]], [[5, 6], [7, 8]]], - [[[6, 7], [8, 9]], [[7, 8], [9, 10]]]], - [[[[8, 9], [10, 11]], [[9, 10], [11, 12]]], - [[[10, 11], [12, 13]], [[11, 12], [13, 14]]], - [[[12, 13], [14, 15]], [[13, 14], [15, 16]]], - [[[14, 15], [16, 17]], [[15, 16], [17, 18]]]]]) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = np.array([[[0, 10, 1, 11], - [0, 0, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[0, 999, 2, 1004], - [0, 10.1, 1, 11.1], - [0, 100, 1, 101], - [0, 0, 0, 0]]]) - exp_nms_scores = np.array([[.95, .9, 0, 0], - [.85, .5, .3, 0]]) - exp_nms_classes = np.array([[0, 0, 0, 0], - [1, 0, 0, 0]]) - exp_nms_masks = np.array([[[[6, 7], [8, 9]], - [[0, 1], [2, 3]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]], - [[[13, 14], [15, 16]], - [[8, 9], [10, 11]], - [[10, 11], [12, 13]], - [[0, 0], [0, 0]]]]) - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes_placeholder, scores_placeholder, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size, - masks=masks_placeholder) - - self.assertIsNone(nmsed_additional_fields) - # Check static shapes - self.assertAllEqual(nmsed_boxes.shape.as_list(), [None, 4, 4]) - self.assertAllEqual(nmsed_scores.shape.as_list(), [None, 4]) - self.assertAllEqual(nmsed_classes.shape.as_list(), [None, 4]) - self.assertAllEqual(nmsed_masks.shape.as_list(), [None, 4, 2, 2]) - self.assertEqual(num_detections.shape.as_list(), [None]) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - nmsed_masks, num_detections], - feed_dict={boxes_placeholder: boxes, - scores_placeholder: scores, - masks_placeholder: masks}) - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - self.assertAllClose(num_detections, [2, 3]) - self.assertAllClose(nmsed_masks, exp_nms_masks) - - def test_batch_multiclass_nms_with_masks_and_num_valid_boxes(self): - boxes = tf.constant([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]]], - [[[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]], - tf.float32) - scores = tf.constant([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0]], - [[.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - masks = tf.constant([[[[[0, 1], [2, 3]], [[1, 2], [3, 4]]], - [[[2, 3], [4, 5]], [[3, 4], [5, 6]]], - [[[4, 5], [6, 7]], [[5, 6], [7, 8]]], - [[[6, 7], [8, 9]], [[7, 8], [9, 10]]]], - [[[[8, 9], [10, 11]], [[9, 10], [11, 12]]], - [[[10, 11], [12, 13]], [[11, 12], [13, 14]]], - [[[12, 13], [14, 15]], [[13, 14], [15, 16]]], - [[[14, 15], [16, 17]], [[15, 16], [17, 18]]]]], - tf.float32) - num_valid_boxes = tf.constant([1, 1], tf.int32) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = [[[0, 0, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[0, 10.1, 1, 11.1], - [0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0]]] - exp_nms_scores = [[.9, 0, 0, 0], - [.5, 0, 0, 0]] - exp_nms_classes = [[0, 0, 0, 0], - [0, 0, 0, 0]] - exp_nms_masks = [[[[0, 1], [2, 3]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]], - [[[8, 9], [10, 11]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]]] - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size, - num_valid_boxes=num_valid_boxes, masks=masks) - - self.assertIsNone(nmsed_additional_fields) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - nmsed_masks, num_detections]) - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - self.assertAllClose(num_detections, [1, 1]) - self.assertAllClose(nmsed_masks, exp_nms_masks) - - def test_batch_multiclass_nms_with_additional_fields_and_num_valid_boxes( - self): - boxes = tf.constant([[[[0, 0, 1, 1], [0, 0, 4, 5]], - [[0, 0.1, 1, 1.1], [0, 0.1, 2, 1.1]], - [[0, -0.1, 1, 0.9], [0, -0.1, 1, 0.9]], - [[0, 10, 1, 11], [0, 10, 1, 11]]], - [[[0, 10.1, 1, 11.1], [0, 10.1, 1, 11.1]], - [[0, 100, 1, 101], [0, 100, 1, 101]], - [[0, 1000, 1, 1002], [0, 999, 2, 1004]], - [[0, 1000, 1, 1002.1], [0, 999, 2, 1002.7]]]], - tf.float32) - scores = tf.constant([[[.9, 0.01], [.75, 0.05], - [.6, 0.01], [.95, 0]], - [[.5, 0.01], [.3, 0.01], - [.01, .85], [.01, .5]]]) - additional_fields = { - 'keypoints': tf.constant( - [[[[6, 7], [8, 9]], - [[0, 1], [2, 3]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]], - [[[13, 14], [15, 16]], - [[8, 9], [10, 11]], - [[10, 11], [12, 13]], - [[0, 0], [0, 0]]]], - tf.float32) - } - num_valid_boxes = tf.constant([1, 1], tf.int32) - score_thresh = 0.1 - iou_thresh = .5 - max_output_size = 4 - - exp_nms_corners = [[[0, 0, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0]], - [[0, 10.1, 1, 11.1], - [0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0]]] - exp_nms_scores = [[.9, 0, 0, 0], - [.5, 0, 0, 0]] - exp_nms_classes = [[0, 0, 0, 0], - [0, 0, 0, 0]] - exp_nms_additional_fields = { - 'keypoints': np.array([[[[6, 7], [8, 9]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]], - [[[13, 14], [15, 16]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]], - [[0, 0], [0, 0]]]]) - } - - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_masks, - nmsed_additional_fields, num_detections - ) = post_processing.batch_multiclass_non_max_suppression( - boxes, scores, score_thresh, iou_thresh, - max_size_per_class=max_output_size, max_total_size=max_output_size, - num_valid_boxes=num_valid_boxes, - additional_fields=additional_fields) - - self.assertIsNone(nmsed_masks) - - with self.test_session() as sess: - (nmsed_boxes, nmsed_scores, nmsed_classes, nmsed_additional_fields, - num_detections) = sess.run([nmsed_boxes, nmsed_scores, nmsed_classes, - nmsed_additional_fields, num_detections]) - - self.assertAllClose(nmsed_boxes, exp_nms_corners) - self.assertAllClose(nmsed_scores, exp_nms_scores) - self.assertAllClose(nmsed_classes, exp_nms_classes) - for key in exp_nms_additional_fields: - self.assertAllClose(nmsed_additional_fields[key], - exp_nms_additional_fields[key]) - self.assertAllClose(num_detections, [1, 1]) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/prefetcher.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/prefetcher.py deleted file mode 100644 index e690c599f..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/prefetcher.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Provides functions to prefetch tensors to feed into models.""" -import tensorflow as tf - - -def prefetch(tensor_dict, capacity): - """Creates a prefetch queue for tensors. - - Creates a FIFO queue to asynchronously enqueue tensor_dicts and returns a - dequeue op that evaluates to a tensor_dict. This function is useful in - prefetching preprocessed tensors so that the data is readily available for - consumers. - - Example input pipeline when you don't need batching: - ---------------------------------------------------- - key, string_tensor = slim.parallel_reader.parallel_read(...) - tensor_dict = decoder.decode(string_tensor) - tensor_dict = preprocessor.preprocess(tensor_dict, ...) - prefetch_queue = prefetcher.prefetch(tensor_dict, capacity=20) - tensor_dict = prefetch_queue.dequeue() - outputs = Model(tensor_dict) - ... - ---------------------------------------------------- - - For input pipelines with batching, refer to core/batcher.py - - Args: - tensor_dict: a dictionary of tensors to prefetch. - capacity: the size of the prefetch queue. - - Returns: - a FIFO prefetcher queue - """ - names = list(tensor_dict.keys()) - dtypes = [t.dtype for t in tensor_dict.values()] - shapes = [t.get_shape() for t in tensor_dict.values()] - prefetch_queue = tf.PaddingFIFOQueue(capacity, dtypes=dtypes, - shapes=shapes, - names=names, - name='prefetch_queue') - enqueue_op = prefetch_queue.enqueue(tensor_dict) - tf.train.queue_runner.add_queue_runner(tf.train.queue_runner.QueueRunner( - prefetch_queue, [enqueue_op])) - tf.summary.scalar('queue/%s/fraction_of_%d_full' % (prefetch_queue.name, - capacity), - tf.to_float(prefetch_queue.size()) * (1. / capacity)) - return prefetch_queue diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/prefetcher_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/prefetcher_test.py deleted file mode 100644 index 63f557e33..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/prefetcher_test.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.prefetcher.""" -import tensorflow as tf - -from object_detection.core import prefetcher - -slim = tf.contrib.slim - - -class PrefetcherTest(tf.test.TestCase): - - def test_prefetch_tensors_with_fully_defined_shapes(self): - with self.test_session() as sess: - batch_size = 10 - image_size = 32 - num_batches = 5 - examples = tf.Variable(tf.constant(0, dtype=tf.int64)) - counter = examples.count_up_to(num_batches) - image = tf.random_normal([batch_size, image_size, - image_size, 3], - dtype=tf.float32, - name='images') - label = tf.random_uniform([batch_size, 1], 0, 10, - dtype=tf.int32, name='labels') - - prefetch_queue = prefetcher.prefetch(tensor_dict={'counter': counter, - 'image': image, - 'label': label}, - capacity=100) - tensor_dict = prefetch_queue.dequeue() - - self.assertAllEqual(tensor_dict['image'].get_shape().as_list(), - [batch_size, image_size, image_size, 3]) - self.assertAllEqual(tensor_dict['label'].get_shape().as_list(), - [batch_size, 1]) - - tf.initialize_all_variables().run() - with slim.queues.QueueRunners(sess): - for _ in range(num_batches): - results = sess.run(tensor_dict) - self.assertEquals(results['image'].shape, - (batch_size, image_size, image_size, 3)) - self.assertEquals(results['label'].shape, (batch_size, 1)) - with self.assertRaises(tf.errors.OutOfRangeError): - sess.run(tensor_dict) - - def test_prefetch_tensors_with_partially_defined_shapes(self): - with self.test_session() as sess: - batch_size = 10 - image_size = 32 - num_batches = 5 - examples = tf.Variable(tf.constant(0, dtype=tf.int64)) - counter = examples.count_up_to(num_batches) - image = tf.random_normal([batch_size, - tf.Variable(image_size), - tf.Variable(image_size), 3], - dtype=tf.float32, - name='image') - image.set_shape([batch_size, None, None, 3]) - label = tf.random_uniform([batch_size, tf.Variable(1)], 0, - 10, dtype=tf.int32, name='label') - label.set_shape([batch_size, None]) - - prefetch_queue = prefetcher.prefetch(tensor_dict={'counter': counter, - 'image': image, - 'label': label}, - capacity=100) - tensor_dict = prefetch_queue.dequeue() - - self.assertAllEqual(tensor_dict['image'].get_shape().as_list(), - [batch_size, None, None, 3]) - self.assertAllEqual(tensor_dict['label'].get_shape().as_list(), - [batch_size, None]) - - tf.initialize_all_variables().run() - with slim.queues.QueueRunners(sess): - for _ in range(num_batches): - results = sess.run(tensor_dict) - self.assertEquals(results['image'].shape, - (batch_size, image_size, image_size, 3)) - self.assertEquals(results['label'].shape, (batch_size, 1)) - with self.assertRaises(tf.errors.OutOfRangeError): - sess.run(tensor_dict) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor.py deleted file mode 100644 index 0fcdfcc69..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor.py +++ /dev/null @@ -1,3176 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Preprocess images and bounding boxes for detection. - -We perform two sets of operations in preprocessing stage: -(a) operations that are applied to both training and testing data, -(b) operations that are applied only to training data for the purpose of - data augmentation. - -A preprocessing function receives a set of inputs, -e.g. an image and bounding boxes, -performs an operation on them, and returns them. -Some examples are: randomly cropping the image, randomly mirroring the image, - randomly changing the brightness, contrast, hue and - randomly jittering the bounding boxes. - -The preprocess function receives a tensor_dict which is a dictionary that maps -different field names to their tensors. For example, -tensor_dict[fields.InputDataFields.image] holds the image tensor. -The image is a rank 4 tensor: [1, height, width, channels] with -dtype=tf.float32. The groundtruth_boxes is a rank 2 tensor: [N, 4] where -in each row there is a box with [ymin xmin ymax xmax]. -Boxes are in normalized coordinates meaning -their coordinate values range in [0, 1] - -To preprocess multiple images with the same operations in cases where -nondeterministic operations are used, a preprocessor_cache.PreprocessorCache -object can be passed into the preprocess function or individual operations. -All nondeterministic operations except random_jitter_boxes support caching. -E.g. -Let tensor_dict{1,2,3,4,5} be copies of the same inputs. -Let preprocess_options contain nondeterministic operation(s) excluding -random_jitter_boxes. - -cache1 = preprocessor_cache.PreprocessorCache() -cache2 = preprocessor_cache.PreprocessorCache() -a = preprocess(tensor_dict1, preprocess_options, preprocess_vars_cache=cache1) -b = preprocess(tensor_dict2, preprocess_options, preprocess_vars_cache=cache1) -c = preprocess(tensor_dict3, preprocess_options, preprocess_vars_cache=cache2) -d = preprocess(tensor_dict4, preprocess_options, preprocess_vars_cache=cache2) -e = preprocess(tensor_dict5, preprocess_options) - -Then correspondings tensors of object pairs (a,b) and (c,d) -are guaranteed to be equal element-wise, but the equality of any other object -pair cannot be determined. - -Important Note: In tensor_dict, images is a rank 4 tensor, but preprocessing -functions receive a rank 3 tensor for processing the image. Thus, inside the -preprocess function we squeeze the image to become a rank 3 tensor and then -we pass it to the functions. At the end of the preprocess we expand the image -back to rank 4. -""" - -import functools -import inspect -import sys -import tensorflow as tf - -from tensorflow.python.ops import control_flow_ops - -from object_detection.core import box_list -from object_detection.core import box_list_ops -from object_detection.core import keypoint_ops -from object_detection.core import preprocessor_cache -from object_detection.core import standard_fields as fields -from object_detection.utils import shape_utils - - -def _apply_with_random_selector(x, - func, - num_cases, - preprocess_vars_cache=None, - key=''): - """Computes func(x, sel), with sel sampled from [0...num_cases-1]. - - If both preprocess_vars_cache AND key are the same between two calls, sel will - be the same value in both calls. - - Args: - x: input Tensor. - func: Python function to apply. - num_cases: Python int32, number of cases to sample sel from. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - key: variable identifier for preprocess_vars_cache. - - Returns: - The result of func(x, sel), where func receives the value of the - selector as a python integer, but sel is sampled dynamically. - """ - generator_func = functools.partial( - tf.random_uniform, [], maxval=num_cases, dtype=tf.int32) - rand_sel = _get_or_create_preprocess_rand_vars( - generator_func, preprocessor_cache.PreprocessorCache.SELECTOR, - preprocess_vars_cache, key) - - # Pass the real x only to one of the func calls. - return control_flow_ops.merge([func( - control_flow_ops.switch(x, tf.equal(rand_sel, case))[1], case) - for case in range(num_cases)])[0] - - -def _apply_with_random_selector_tuples(x, - func, - num_cases, - preprocess_vars_cache=None, - key=''): - """Computes func(x, sel), with sel sampled from [0...num_cases-1]. - - If both preprocess_vars_cache AND key are the same between two calls, sel will - be the same value in both calls. - - Args: - x: A tuple of input tensors. - func: Python function to apply. - num_cases: Python int32, number of cases to sample sel from. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - key: variable identifier for preprocess_vars_cache. - - Returns: - The result of func(x, sel), where func receives the value of the - selector as a python integer, but sel is sampled dynamically. - """ - num_inputs = len(x) - generator_func = functools.partial( - tf.random_uniform, [], maxval=num_cases, dtype=tf.int32) - rand_sel = _get_or_create_preprocess_rand_vars( - generator_func, preprocessor_cache.PreprocessorCache.SELECTOR_TUPLES, - preprocess_vars_cache, key) - - # Pass the real x only to one of the func calls. - tuples = [list() for t in x] - for case in range(num_cases): - new_x = [control_flow_ops.switch(t, tf.equal(rand_sel, case))[1] for t in x] - output = func(tuple(new_x), case) - for j in range(num_inputs): - tuples[j].append(output[j]) - - for i in range(num_inputs): - tuples[i] = control_flow_ops.merge(tuples[i])[0] - return tuple(tuples) - - -def _get_or_create_preprocess_rand_vars(generator_func, - function_id, - preprocess_vars_cache, - key=''): - """Returns a tensor stored in preprocess_vars_cache or using generator_func. - - If the tensor was previously generated and appears in the PreprocessorCache, - the previously generated tensor will be returned. Otherwise, a new tensor - is generated using generator_func and stored in the cache. - - Args: - generator_func: A 0-argument function that generates a tensor. - function_id: identifier for the preprocessing function used. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - key: identifier for the variable stored. - Returns: - The generated tensor. - """ - if preprocess_vars_cache is not None: - var = preprocess_vars_cache.get(function_id, key) - if var is None: - var = generator_func() - preprocess_vars_cache.update(function_id, key, var) - else: - var = generator_func() - return var - - -def _random_integer(minval, maxval, seed): - """Returns a random 0-D tensor between minval and maxval. - - Args: - minval: minimum value of the random tensor. - maxval: maximum value of the random tensor. - seed: random seed. - - Returns: - A random 0-D tensor between minval and maxval. - """ - return tf.random_uniform( - [], minval=minval, maxval=maxval, dtype=tf.int32, seed=seed) - - -# TODO(mttang): This method is needed because the current -# tf.image.rgb_to_grayscale method does not support quantization. Replace with -# tf.image.rgb_to_grayscale after quantization support is added. -def _rgb_to_grayscale(images, name=None): - """Converts one or more images from RGB to Grayscale. - - Outputs a tensor of the same `DType` and rank as `images`. The size of the - last dimension of the output is 1, containing the Grayscale value of the - pixels. - - Args: - images: The RGB tensor to convert. Last dimension must have size 3 and - should contain RGB values. - name: A name for the operation (optional). - - Returns: - The converted grayscale image(s). - """ - with tf.name_scope(name, 'rgb_to_grayscale', [images]) as name: - images = tf.convert_to_tensor(images, name='images') - # Remember original dtype to so we can convert back if needed - orig_dtype = images.dtype - flt_image = tf.image.convert_image_dtype(images, tf.float32) - - # Reference for converting between RGB and grayscale. - # https://en.wikipedia.org/wiki/Luma_%28video%29 - rgb_weights = [0.2989, 0.5870, 0.1140] - rank_1 = tf.expand_dims(tf.rank(images) - 1, 0) - gray_float = tf.reduce_sum( - flt_image * rgb_weights, rank_1, keep_dims=True) - gray_float.set_shape(images.get_shape()[:-1].concatenate([1])) - return tf.image.convert_image_dtype(gray_float, orig_dtype, name=name) - - -def normalize_image(image, original_minval, original_maxval, target_minval, - target_maxval): - """Normalizes pixel values in the image. - - Moves the pixel values from the current [original_minval, original_maxval] - range to a the [target_minval, target_maxval] range. - - Args: - image: rank 3 float32 tensor containing 1 - image -> [height, width, channels]. - original_minval: current image minimum value. - original_maxval: current image maximum value. - target_minval: target image minimum value. - target_maxval: target image maximum value. - - Returns: - image: image which is the same shape as input image. - """ - with tf.name_scope('NormalizeImage', values=[image]): - original_minval = float(original_minval) - original_maxval = float(original_maxval) - target_minval = float(target_minval) - target_maxval = float(target_maxval) - image = tf.to_float(image) - image = tf.subtract(image, original_minval) - image = tf.multiply(image, (target_maxval - target_minval) / - (original_maxval - original_minval)) - image = tf.add(image, target_minval) - return image - - -def retain_boxes_above_threshold(boxes, - labels, - label_scores, - multiclass_scores=None, - masks=None, - keypoints=None, - threshold=0.0): - """Retains boxes whose label score is above a given threshold. - - If the label score for a box is missing (represented by NaN), the box is - retained. The boxes that don't pass the threshold will not appear in the - returned tensor. - - Args: - boxes: float32 tensor of shape [num_instance, 4] representing boxes - location in normalized coordinates. - labels: rank 1 int32 tensor of shape [num_instance] containing the object - classes. - label_scores: float32 tensor of shape [num_instance] representing the - score for each box. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks are of - the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x normalized - coordinates. - threshold: scalar python float. - - Returns: - retained_boxes: [num_retained_instance, 4] - retianed_labels: [num_retained_instance] - retained_label_scores: [num_retained_instance] - - If multiclass_scores, masks, or keypoints are not None, the function also - returns: - - retained_multiclass_scores: [num_retained_instance, num_classes] - retained_masks: [num_retained_instance, height, width] - retained_keypoints: [num_retained_instance, num_keypoints, 2] - """ - with tf.name_scope('RetainBoxesAboveThreshold', - values=[boxes, labels, label_scores]): - indices = tf.where( - tf.logical_or(label_scores > threshold, tf.is_nan(label_scores))) - indices = tf.squeeze(indices, axis=1) - retained_boxes = tf.gather(boxes, indices) - retained_labels = tf.gather(labels, indices) - retained_label_scores = tf.gather(label_scores, indices) - result = [retained_boxes, retained_labels, retained_label_scores] - - if multiclass_scores is not None: - retained_multiclass_scores = tf.gather(multiclass_scores, indices) - result.append(retained_multiclass_scores) - - if masks is not None: - retained_masks = tf.gather(masks, indices) - result.append(retained_masks) - - if keypoints is not None: - retained_keypoints = tf.gather(keypoints, indices) - result.append(retained_keypoints) - - return result - - -def _flip_boxes_left_right(boxes): - """Left-right flip the boxes. - - Args: - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - - Returns: - Flipped boxes. - """ - ymin, xmin, ymax, xmax = tf.split(value=boxes, num_or_size_splits=4, axis=1) - flipped_xmin = tf.subtract(1.0, xmax) - flipped_xmax = tf.subtract(1.0, xmin) - flipped_boxes = tf.concat([ymin, flipped_xmin, ymax, flipped_xmax], 1) - return flipped_boxes - - -def _flip_boxes_up_down(boxes): - """Up-down flip the boxes. - - Args: - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - - Returns: - Flipped boxes. - """ - ymin, xmin, ymax, xmax = tf.split(value=boxes, num_or_size_splits=4, axis=1) - flipped_ymin = tf.subtract(1.0, ymax) - flipped_ymax = tf.subtract(1.0, ymin) - flipped_boxes = tf.concat([flipped_ymin, xmin, flipped_ymax, xmax], 1) - return flipped_boxes - - -def _rot90_boxes(boxes): - """Rotate boxes counter-clockwise by 90 degrees. - - Args: - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - - Returns: - Rotated boxes. - """ - ymin, xmin, ymax, xmax = tf.split(value=boxes, num_or_size_splits=4, axis=1) - rotated_ymin = tf.subtract(1.0, xmax) - rotated_ymax = tf.subtract(1.0, xmin) - rotated_xmin = ymin - rotated_xmax = ymax - rotated_boxes = tf.concat( - [rotated_ymin, rotated_xmin, rotated_ymax, rotated_xmax], 1) - return rotated_boxes - - -def _flip_masks_left_right(masks): - """Left-right flip masks. - - Args: - masks: rank 3 float32 tensor with shape - [num_instances, height, width] representing instance masks. - - Returns: - flipped masks: rank 3 float32 tensor with shape - [num_instances, height, width] representing instance masks. - """ - return masks[:, :, ::-1] - - -def _flip_masks_up_down(masks): - """Up-down flip masks. - - Args: - masks: rank 3 float32 tensor with shape - [num_instances, height, width] representing instance masks. - - Returns: - flipped masks: rank 3 float32 tensor with shape - [num_instances, height, width] representing instance masks. - """ - return masks[:, ::-1, :] - - -def _rot90_masks(masks): - """Rotate masks counter-clockwise by 90 degrees. - - Args: - masks: rank 3 float32 tensor with shape - [num_instances, height, width] representing instance masks. - - Returns: - rotated masks: rank 3 float32 tensor with shape - [num_instances, height, width] representing instance masks. - """ - masks = tf.transpose(masks, [0, 2, 1]) - return masks[:, ::-1, :] - - -def random_horizontal_flip(image, - boxes=None, - masks=None, - keypoints=None, - keypoint_flip_permutation=None, - seed=None, - preprocess_vars_cache=None): - """Randomly flips the image and detections horizontally. - - The probability of flipping the image is 50%. - - Args: - image: rank 3 float32 tensor with shape [height, width, channels]. - boxes: (optional) rank 2 float32 tensor with shape [N, 4] - containing the bounding boxes. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - keypoint_flip_permutation: rank 1 int32 tensor containing the keypoint flip - permutation. - seed: random seed - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - - If boxes, masks, keypoints, and keypoint_flip_permutation are not None, - the function also returns the following tensors. - - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - - Raises: - ValueError: if keypoints are provided but keypoint_flip_permutation is not. - """ - - def _flip_image(image): - # flip image - image_flipped = tf.image.flip_left_right(image) - return image_flipped - - if keypoints is not None and keypoint_flip_permutation is None: - raise ValueError( - 'keypoints are provided but keypoints_flip_permutation is not provided') - - with tf.name_scope('RandomHorizontalFlip', values=[image, boxes]): - result = [] - # random variable defining whether to do flip or not - generator_func = functools.partial(tf.random_uniform, [], seed=seed) - do_a_flip_random = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.HORIZONTAL_FLIP, - preprocess_vars_cache) - do_a_flip_random = tf.greater(do_a_flip_random, 0.5) - - # flip image - image = tf.cond(do_a_flip_random, lambda: _flip_image(image), lambda: image) - result.append(image) - - # flip boxes - if boxes is not None: - boxes = tf.cond(do_a_flip_random, lambda: _flip_boxes_left_right(boxes), - lambda: boxes) - result.append(boxes) - - # flip masks - if masks is not None: - masks = tf.cond(do_a_flip_random, lambda: _flip_masks_left_right(masks), - lambda: masks) - result.append(masks) - - # flip keypoints - if keypoints is not None and keypoint_flip_permutation is not None: - permutation = keypoint_flip_permutation - keypoints = tf.cond( - do_a_flip_random, - lambda: keypoint_ops.flip_horizontal(keypoints, 0.5, permutation), - lambda: keypoints) - result.append(keypoints) - - return tuple(result) - - -def random_vertical_flip(image, - boxes=None, - masks=None, - keypoints=None, - keypoint_flip_permutation=None, - seed=None, - preprocess_vars_cache=None): - """Randomly flips the image and detections vertically. - - The probability of flipping the image is 50%. - - Args: - image: rank 3 float32 tensor with shape [height, width, channels]. - boxes: (optional) rank 2 float32 tensor with shape [N, 4] - containing the bounding boxes. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - keypoint_flip_permutation: rank 1 int32 tensor containing the keypoint flip - permutation. - seed: random seed - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - - If boxes, masks, keypoints, and keypoint_flip_permutation are not None, - the function also returns the following tensors. - - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - - Raises: - ValueError: if keypoints are provided but keypoint_flip_permutation is not. - """ - - def _flip_image(image): - # flip image - image_flipped = tf.image.flip_up_down(image) - return image_flipped - - if keypoints is not None and keypoint_flip_permutation is None: - raise ValueError( - 'keypoints are provided but keypoints_flip_permutation is not provided') - - with tf.name_scope('RandomVerticalFlip', values=[image, boxes]): - result = [] - # random variable defining whether to do flip or not - generator_func = functools.partial(tf.random_uniform, [], seed=seed) - do_a_flip_random = _get_or_create_preprocess_rand_vars( - generator_func, preprocessor_cache.PreprocessorCache.VERTICAL_FLIP, - preprocess_vars_cache) - do_a_flip_random = tf.greater(do_a_flip_random, 0.5) - - # flip image - image = tf.cond(do_a_flip_random, lambda: _flip_image(image), lambda: image) - result.append(image) - - # flip boxes - if boxes is not None: - boxes = tf.cond(do_a_flip_random, lambda: _flip_boxes_up_down(boxes), - lambda: boxes) - result.append(boxes) - - # flip masks - if masks is not None: - masks = tf.cond(do_a_flip_random, lambda: _flip_masks_up_down(masks), - lambda: masks) - result.append(masks) - - # flip keypoints - if keypoints is not None and keypoint_flip_permutation is not None: - permutation = keypoint_flip_permutation - keypoints = tf.cond( - do_a_flip_random, - lambda: keypoint_ops.flip_vertical(keypoints, 0.5, permutation), - lambda: keypoints) - result.append(keypoints) - - return tuple(result) - - -def random_rotation90(image, - boxes=None, - masks=None, - keypoints=None, - seed=None, - preprocess_vars_cache=None): - """Randomly rotates the image and detections 90 degrees counter-clockwise. - - The probability of rotating the image is 50%. This can be combined with - random_horizontal_flip and random_vertical_flip to produce an output with a - uniform distribution of the eight possible 90 degree rotation / reflection - combinations. - - Args: - image: rank 3 float32 tensor with shape [height, width, channels]. - boxes: (optional) rank 2 float32 tensor with shape [N, 4] - containing the bounding boxes. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - seed: random seed - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - - If boxes, masks, and keypoints, are not None, - the function also returns the following tensors. - - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - """ - - def _rot90_image(image): - # flip image - image_rotated = tf.image.rot90(image) - return image_rotated - - with tf.name_scope('RandomRotation90', values=[image, boxes]): - result = [] - - # random variable defining whether to rotate by 90 degrees or not - generator_func = functools.partial(tf.random_uniform, [], seed=seed) - do_a_rot90_random = _get_or_create_preprocess_rand_vars( - generator_func, preprocessor_cache.PreprocessorCache.ROTATION90, - preprocess_vars_cache) - do_a_rot90_random = tf.greater(do_a_rot90_random, 0.5) - - # flip image - image = tf.cond(do_a_rot90_random, lambda: _rot90_image(image), - lambda: image) - result.append(image) - - # flip boxes - if boxes is not None: - boxes = tf.cond(do_a_rot90_random, lambda: _rot90_boxes(boxes), - lambda: boxes) - result.append(boxes) - - # flip masks - if masks is not None: - masks = tf.cond(do_a_rot90_random, lambda: _rot90_masks(masks), - lambda: masks) - result.append(masks) - - # flip keypoints - if keypoints is not None: - keypoints = tf.cond( - do_a_rot90_random, - lambda: keypoint_ops.rot90(keypoints), - lambda: keypoints) - result.append(keypoints) - - return tuple(result) - - -def random_pixel_value_scale(image, - minval=0.9, - maxval=1.1, - seed=None, - preprocess_vars_cache=None): - """Scales each value in the pixels of the image. - - This function scales each pixel independent of the other ones. - For each value in image tensor, draws a random number between - minval and maxval and multiples the values with them. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 255]. - minval: lower ratio of scaling pixel values. - maxval: upper ratio of scaling pixel values. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - """ - with tf.name_scope('RandomPixelValueScale', values=[image]): - generator_func = functools.partial( - tf.random_uniform, tf.shape(image), - minval=minval, maxval=maxval, - dtype=tf.float32, seed=seed) - color_coef = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.PIXEL_VALUE_SCALE, - preprocess_vars_cache) - - image = tf.multiply(image, color_coef) - image = tf.clip_by_value(image, 0.0, 255.0) - - return image - - -def random_image_scale(image, - masks=None, - min_scale_ratio=0.5, - max_scale_ratio=2.0, - seed=None, - preprocess_vars_cache=None): - """Scales the image size. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels]. - masks: (optional) rank 3 float32 tensor containing masks with - size [height, width, num_masks]. The value is set to None if there are no - masks. - min_scale_ratio: minimum scaling ratio. - max_scale_ratio: maximum scaling ratio. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same rank as input image. - masks: If masks is not none, resized masks which are the same rank as input - masks will be returned. - """ - with tf.name_scope('RandomImageScale', values=[image]): - result = [] - image_shape = tf.shape(image) - image_height = image_shape[0] - image_width = image_shape[1] - generator_func = functools.partial( - tf.random_uniform, [], - minval=min_scale_ratio, maxval=max_scale_ratio, - dtype=tf.float32, seed=seed) - size_coef = _get_or_create_preprocess_rand_vars( - generator_func, preprocessor_cache.PreprocessorCache.IMAGE_SCALE, - preprocess_vars_cache) - - image_newysize = tf.to_int32( - tf.multiply(tf.to_float(image_height), size_coef)) - image_newxsize = tf.to_int32( - tf.multiply(tf.to_float(image_width), size_coef)) - image = tf.image.resize_images( - image, [image_newysize, image_newxsize], align_corners=True) - result.append(image) - if masks: - masks = tf.image.resize_nearest_neighbor( - masks, [image_newysize, image_newxsize], align_corners=True) - result.append(masks) - return tuple(result) - - -def random_rgb_to_gray(image, - probability=0.1, - seed=None, - preprocess_vars_cache=None): - """Changes the image from RGB to Grayscale with the given probability. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 255]. - probability: the probability of returning a grayscale image. - The probability should be a number between [0, 1]. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - """ - def _image_to_gray(image): - image_gray1 = _rgb_to_grayscale(image) - image_gray3 = tf.image.grayscale_to_rgb(image_gray1) - return image_gray3 - - with tf.name_scope('RandomRGBtoGray', values=[image]): - # random variable defining whether to change to grayscale or not - generator_func = functools.partial(tf.random_uniform, [], seed=seed) - do_gray_random = _get_or_create_preprocess_rand_vars( - generator_func, preprocessor_cache.PreprocessorCache.RGB_TO_GRAY, - preprocess_vars_cache) - - image = tf.cond( - tf.greater(do_gray_random, probability), lambda: image, - lambda: _image_to_gray(image)) - - return image - - -def random_adjust_brightness(image, - max_delta=0.2, - seed=None, - preprocess_vars_cache=None): - """Randomly adjusts brightness. - - Makes sure the output image is still between 0 and 255. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 255]. - max_delta: how much to change the brightness. A value between [0, 1). - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - boxes: boxes which is the same shape as input boxes. - """ - with tf.name_scope('RandomAdjustBrightness', values=[image]): - generator_func = functools.partial(tf.random_uniform, [], - -max_delta, max_delta, seed=seed) - delta = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.ADJUST_BRIGHTNESS, - preprocess_vars_cache) - - image = tf.image.adjust_brightness(image / 255, delta) * 255 - image = tf.clip_by_value(image, clip_value_min=0.0, clip_value_max=255.0) - return image - - -def random_adjust_contrast(image, - min_delta=0.8, - max_delta=1.25, - seed=None, - preprocess_vars_cache=None): - """Randomly adjusts contrast. - - Makes sure the output image is still between 0 and 255. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 255]. - min_delta: see max_delta. - max_delta: how much to change the contrast. Contrast will change with a - value between min_delta and max_delta. This value will be - multiplied to the current contrast of the image. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - """ - with tf.name_scope('RandomAdjustContrast', values=[image]): - generator_func = functools.partial(tf.random_uniform, [], - min_delta, max_delta, seed=seed) - contrast_factor = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.ADJUST_CONTRAST, - preprocess_vars_cache) - image = tf.image.adjust_contrast(image / 255, contrast_factor) * 255 - image = tf.clip_by_value(image, clip_value_min=0.0, clip_value_max=255.0) - return image - - -def random_adjust_hue(image, - max_delta=0.02, - seed=None, - preprocess_vars_cache=None): - """Randomly adjusts hue. - - Makes sure the output image is still between 0 and 255. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 255]. - max_delta: change hue randomly with a value between 0 and max_delta. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - """ - with tf.name_scope('RandomAdjustHue', values=[image]): - generator_func = functools.partial(tf.random_uniform, [], - -max_delta, max_delta, seed=seed) - delta = _get_or_create_preprocess_rand_vars( - generator_func, preprocessor_cache.PreprocessorCache.ADJUST_HUE, - preprocess_vars_cache) - image = tf.image.adjust_hue(image / 255, delta) * 255 - image = tf.clip_by_value(image, clip_value_min=0.0, clip_value_max=255.0) - return image - - -def random_adjust_saturation(image, - min_delta=0.8, - max_delta=1.25, - seed=None, - preprocess_vars_cache=None): - """Randomly adjusts saturation. - - Makes sure the output image is still between 0 and 255. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 255]. - min_delta: see max_delta. - max_delta: how much to change the saturation. Saturation will change with a - value between min_delta and max_delta. This value will be - multiplied to the current saturation of the image. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - """ - with tf.name_scope('RandomAdjustSaturation', values=[image]): - generator_func = functools.partial(tf.random_uniform, [], - min_delta, max_delta, seed=seed) - saturation_factor = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.ADJUST_SATURATION, - preprocess_vars_cache) - image = tf.image.adjust_saturation(image / 255, saturation_factor) * 255 - image = tf.clip_by_value(image, clip_value_min=0.0, clip_value_max=255.0) - return image - - -def random_distort_color(image, color_ordering=0, preprocess_vars_cache=None): - """Randomly distorts color. - - Randomly distorts color using a combination of brightness, hue, contrast and - saturation changes. Makes sure the output image is still between 0 and 255. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 255]. - color_ordering: Python int, a type of distortion (valid values: 0, 1). - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same shape as input image. - - Raises: - ValueError: if color_ordering is not in {0, 1}. - """ - with tf.name_scope('RandomDistortColor', values=[image]): - if color_ordering == 0: - image = random_adjust_brightness( - image, max_delta=32. / 255., - preprocess_vars_cache=preprocess_vars_cache) - image = random_adjust_saturation( - image, min_delta=0.5, max_delta=1.5, - preprocess_vars_cache=preprocess_vars_cache) - image = random_adjust_hue( - image, max_delta=0.2, - preprocess_vars_cache=preprocess_vars_cache) - image = random_adjust_contrast( - image, min_delta=0.5, max_delta=1.5, - preprocess_vars_cache=preprocess_vars_cache) - - elif color_ordering == 1: - image = random_adjust_brightness( - image, max_delta=32. / 255., - preprocess_vars_cache=preprocess_vars_cache) - image = random_adjust_contrast( - image, min_delta=0.5, max_delta=1.5, - preprocess_vars_cache=preprocess_vars_cache) - image = random_adjust_saturation( - image, min_delta=0.5, max_delta=1.5, - preprocess_vars_cache=preprocess_vars_cache) - image = random_adjust_hue( - image, max_delta=0.2, - preprocess_vars_cache=preprocess_vars_cache) - else: - raise ValueError('color_ordering must be in {0, 1}') - return image - - -def random_jitter_boxes(boxes, ratio=0.05, seed=None): - """Randomly jitter boxes in image. - - Args: - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - ratio: The ratio of the box width and height that the corners can jitter. - For example if the width is 100 pixels and ratio is 0.05, - the corners can jitter up to 5 pixels in the x direction. - seed: random seed. - - Returns: - boxes: boxes which is the same shape as input boxes. - """ - def random_jitter_box(box, ratio, seed): - """Randomly jitter box. - - Args: - box: bounding box [1, 1, 4]. - ratio: max ratio between jittered box and original box, - a number between [0, 0.5]. - seed: random seed. - - Returns: - jittered_box: jittered box. - """ - rand_numbers = tf.random_uniform( - [1, 1, 4], minval=-ratio, maxval=ratio, dtype=tf.float32, seed=seed) - box_width = tf.subtract(box[0, 0, 3], box[0, 0, 1]) - box_height = tf.subtract(box[0, 0, 2], box[0, 0, 0]) - hw_coefs = tf.stack([box_height, box_width, box_height, box_width]) - hw_rand_coefs = tf.multiply(hw_coefs, rand_numbers) - jittered_box = tf.add(box, hw_rand_coefs) - jittered_box = tf.clip_by_value(jittered_box, 0.0, 1.0) - return jittered_box - - with tf.name_scope('RandomJitterBoxes', values=[boxes]): - # boxes are [N, 4]. Lets first make them [N, 1, 1, 4] - boxes_shape = tf.shape(boxes) - boxes = tf.expand_dims(boxes, 1) - boxes = tf.expand_dims(boxes, 2) - - distorted_boxes = tf.map_fn( - lambda x: random_jitter_box(x, ratio, seed), boxes, dtype=tf.float32) - - distorted_boxes = tf.reshape(distorted_boxes, boxes_shape) - - return distorted_boxes - - -def _strict_random_crop_image(image, - boxes, - labels, - label_scores=None, - multiclass_scores=None, - masks=None, - keypoints=None, - min_object_covered=1.0, - aspect_ratio_range=(0.75, 1.33), - area_range=(0.1, 1.0), - overlap_thresh=0.3, - preprocess_vars_cache=None): - """Performs random crop. - - Note: boxes will be clipped to the crop. Keypoint coordinates that are - outside the crop will be set to NaN, which is consistent with the original - keypoint encoding for non-existing keypoints. This function always crops - the image and is supposed to be used by `random_crop_image` function which - sometimes returns image unchanged. - - Args: - image: rank 3 float32 tensor containing 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes with shape - [num_instances, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - labels: rank 1 int32 tensor containing the object classes. - label_scores: (optional) float32 tensor of shape [num_instances] - representing the score for each box. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - min_object_covered: the cropped image must cover at least this fraction of - at least one of the input bounding boxes. - aspect_ratio_range: allowed range for aspect ratio of cropped image. - area_range: allowed range for area ratio between cropped image and the - original image. - overlap_thresh: minimum overlap thresh with new cropped - image to keep the box. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same rank as input image. - boxes: boxes which is the same rank as input boxes. - Boxes are in normalized form. - labels: new labels. - - If label_scores, multiclass_scores, masks, or keypoints is not None, the - function also returns: - label_scores: rank 1 float32 tensor with shape [num_instances]. - multiclass_scores: rank 2 float32 tensor with shape - [num_instances, num_classes] - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - """ - with tf.name_scope('RandomCropImage', values=[image, boxes]): - image_shape = tf.shape(image) - - # boxes are [N, 4]. Lets first make them [N, 1, 4]. - boxes_expanded = tf.expand_dims( - tf.clip_by_value( - boxes, clip_value_min=0.0, clip_value_max=1.0), 1) - - generator_func = functools.partial( - tf.image.sample_distorted_bounding_box, - image_shape, - bounding_boxes=boxes_expanded, - min_object_covered=min_object_covered, - aspect_ratio_range=aspect_ratio_range, - area_range=area_range, - max_attempts=100, - use_image_if_no_bounding_boxes=True) - - # for ssd cropping, each value of min_object_covered has its own - # cached random variable - sample_distorted_bounding_box = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.STRICT_CROP_IMAGE, - preprocess_vars_cache, key=min_object_covered) - - im_box_begin, im_box_size, im_box = sample_distorted_bounding_box - - new_image = tf.slice(image, im_box_begin, im_box_size) - new_image.set_shape([None, None, image.get_shape()[2]]) - - # [1, 4] - im_box_rank2 = tf.squeeze(im_box, squeeze_dims=[0]) - # [4] - im_box_rank1 = tf.squeeze(im_box) - - boxlist = box_list.BoxList(boxes) - boxlist.add_field('labels', labels) - - if label_scores is not None: - boxlist.add_field('label_scores', label_scores) - - if multiclass_scores is not None: - boxlist.add_field('multiclass_scores', multiclass_scores) - - im_boxlist = box_list.BoxList(im_box_rank2) - - # remove boxes that are outside cropped image - boxlist, inside_window_ids = box_list_ops.prune_completely_outside_window( - boxlist, im_box_rank1) - - # remove boxes that are outside image - overlapping_boxlist, keep_ids = box_list_ops.prune_non_overlapping_boxes( - boxlist, im_boxlist, overlap_thresh) - - # change the coordinate of the remaining boxes - new_labels = overlapping_boxlist.get_field('labels') - new_boxlist = box_list_ops.change_coordinate_frame(overlapping_boxlist, - im_box_rank1) - new_boxes = new_boxlist.get() - new_boxes = tf.clip_by_value( - new_boxes, clip_value_min=0.0, clip_value_max=1.0) - - result = [new_image, new_boxes, new_labels] - - if label_scores is not None: - new_label_scores = overlapping_boxlist.get_field('label_scores') - result.append(new_label_scores) - - if multiclass_scores is not None: - new_multiclass_scores = overlapping_boxlist.get_field('multiclass_scores') - result.append(new_multiclass_scores) - - if masks is not None: - masks_of_boxes_inside_window = tf.gather(masks, inside_window_ids) - masks_of_boxes_completely_inside_window = tf.gather( - masks_of_boxes_inside_window, keep_ids) - masks_box_begin = [0, im_box_begin[0], im_box_begin[1]] - masks_box_size = [-1, im_box_size[0], im_box_size[1]] - new_masks = tf.slice( - masks_of_boxes_completely_inside_window, - masks_box_begin, masks_box_size) - result.append(new_masks) - - if keypoints is not None: - keypoints_of_boxes_inside_window = tf.gather(keypoints, inside_window_ids) - keypoints_of_boxes_completely_inside_window = tf.gather( - keypoints_of_boxes_inside_window, keep_ids) - new_keypoints = keypoint_ops.change_coordinate_frame( - keypoints_of_boxes_completely_inside_window, im_box_rank1) - new_keypoints = keypoint_ops.prune_outside_window(new_keypoints, - [0.0, 0.0, 1.0, 1.0]) - result.append(new_keypoints) - - return tuple(result) - - -def random_crop_image(image, - boxes, - labels, - label_scores=None, - multiclass_scores=None, - masks=None, - keypoints=None, - min_object_covered=1.0, - aspect_ratio_range=(0.75, 1.33), - area_range=(0.1, 1.0), - overlap_thresh=0.3, - random_coef=0.0, - seed=None, - preprocess_vars_cache=None): - """Randomly crops the image. - - Given the input image and its bounding boxes, this op randomly - crops a subimage. Given a user-provided set of input constraints, - the crop window is resampled until it satisfies these constraints. - If within 100 trials it is unable to find a valid crop, the original - image is returned. See the Args section for a description of the input - constraints. Both input boxes and returned Boxes are in normalized - form (e.g., lie in the unit square [0, 1]). - This function will return the original image with probability random_coef. - - Note: boxes will be clipped to the crop. Keypoint coordinates that are - outside the crop will be set to NaN, which is consistent with the original - keypoint encoding for non-existing keypoints. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes with shape - [num_instances, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - labels: rank 1 int32 tensor containing the object classes. - label_scores: (optional) float32 tensor of shape [num_instances]. - representing the score for each box. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - min_object_covered: the cropped image must cover at least this fraction of - at least one of the input bounding boxes. - aspect_ratio_range: allowed range for aspect ratio of cropped image. - area_range: allowed range for area ratio between cropped image and the - original image. - overlap_thresh: minimum overlap thresh with new cropped - image to keep the box. - random_coef: a random coefficient that defines the chance of getting the - original image. If random_coef is 0, we will always get the - cropped image, and if it is 1.0, we will always get the - original image. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: Image shape will be [new_height, new_width, channels]. - boxes: boxes which is the same rank as input boxes. Boxes are in normalized - form. - labels: new labels. - - If label_scores, multiclass_scores, masks, or keypoints is not None, the - function also returns: - label_scores: rank 1 float32 tensor with shape [num_instances]. - multiclass_scores: rank 2 float32 tensor with shape - [num_instances, num_classes] - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - """ - - def strict_random_crop_image_fn(): - return _strict_random_crop_image( - image, - boxes, - labels, - label_scores=label_scores, - multiclass_scores=multiclass_scores, - masks=masks, - keypoints=keypoints, - min_object_covered=min_object_covered, - aspect_ratio_range=aspect_ratio_range, - area_range=area_range, - overlap_thresh=overlap_thresh, - preprocess_vars_cache=preprocess_vars_cache) - - # avoids tf.cond to make faster RCNN training on borg. See b/140057645. - if random_coef < sys.float_info.min: - result = strict_random_crop_image_fn() - else: - generator_func = functools.partial(tf.random_uniform, [], seed=seed) - do_a_crop_random = _get_or_create_preprocess_rand_vars( - generator_func, preprocessor_cache.PreprocessorCache.CROP_IMAGE, - preprocess_vars_cache) - do_a_crop_random = tf.greater(do_a_crop_random, random_coef) - - outputs = [image, boxes, labels] - - if label_scores is not None: - outputs.append(label_scores) - if multiclass_scores is not None: - outputs.append(multiclass_scores) - if masks is not None: - outputs.append(masks) - if keypoints is not None: - outputs.append(keypoints) - - result = tf.cond(do_a_crop_random, strict_random_crop_image_fn, - lambda: tuple(outputs)) - return result - - -def random_pad_image(image, - boxes, - min_image_size=None, - max_image_size=None, - pad_color=None, - seed=None, - preprocess_vars_cache=None): - """Randomly pads the image. - - This function randomly pads the image with zeros. The final size of the - padded image will be between min_image_size and max_image_size. - if min_image_size is smaller than the input image size, min_image_size will - be set to the input image size. The same for max_image_size. The input image - will be located at a uniformly random location inside the padded image. - The relative location of the boxes to the original image will remain the same. - - Args: - image: rank 3 float32 tensor containing 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - min_image_size: a tensor of size [min_height, min_width], type tf.int32. - If passed as None, will be set to image size - [height, width]. - max_image_size: a tensor of size [max_height, max_width], type tf.int32. - If passed as None, will be set to twice the - image [height * 2, width * 2]. - pad_color: padding color. A rank 1 tensor of [3] with dtype=tf.float32. - if set as None, it will be set to average color of the input - image. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: Image shape will be [new_height, new_width, channels]. - boxes: boxes which is the same rank as input boxes. Boxes are in normalized - form. - """ - if pad_color is None: - pad_color = tf.reduce_mean(image, axis=[0, 1]) - - image_shape = tf.shape(image) - image_height = image_shape[0] - image_width = image_shape[1] - - if max_image_size is None: - max_image_size = tf.stack([image_height * 2, image_width * 2]) - max_image_size = tf.maximum(max_image_size, - tf.stack([image_height, image_width])) - - if min_image_size is None: - min_image_size = tf.stack([image_height, image_width]) - min_image_size = tf.maximum(min_image_size, - tf.stack([image_height, image_width])) - - target_height = tf.cond( - max_image_size[0] > min_image_size[0], - lambda: _random_integer(min_image_size[0], max_image_size[0], seed), - lambda: max_image_size[0]) - - target_width = tf.cond( - max_image_size[1] > min_image_size[1], - lambda: _random_integer(min_image_size[1], max_image_size[1], seed), - lambda: max_image_size[1]) - - offset_height = tf.cond( - target_height > image_height, - lambda: _random_integer(0, target_height - image_height, seed), - lambda: tf.constant(0, dtype=tf.int32)) - - offset_width = tf.cond( - target_width > image_width, - lambda: _random_integer(0, target_width - image_width, seed), - lambda: tf.constant(0, dtype=tf.int32)) - - gen_func = lambda: (target_height, target_width, offset_height, offset_width) - params = _get_or_create_preprocess_rand_vars( - gen_func, preprocessor_cache.PreprocessorCache.PAD_IMAGE, - preprocess_vars_cache) - target_height, target_width, offset_height, offset_width = params - - new_image = tf.image.pad_to_bounding_box( - image, - offset_height=offset_height, - offset_width=offset_width, - target_height=target_height, - target_width=target_width) - - # Setting color of the padded pixels - image_ones = tf.ones_like(image) - image_ones_padded = tf.image.pad_to_bounding_box( - image_ones, - offset_height=offset_height, - offset_width=offset_width, - target_height=target_height, - target_width=target_width) - image_color_padded = (1.0 - image_ones_padded) * pad_color - new_image += image_color_padded - - # setting boxes - new_window = tf.to_float( - tf.stack([ - -offset_height, -offset_width, target_height - offset_height, - target_width - offset_width - ])) - new_window /= tf.to_float( - tf.stack([image_height, image_width, image_height, image_width])) - boxlist = box_list.BoxList(boxes) - new_boxlist = box_list_ops.change_coordinate_frame(boxlist, new_window) - new_boxes = new_boxlist.get() - - return new_image, new_boxes - - -def random_crop_pad_image(image, - boxes, - labels, - label_scores=None, - multiclass_scores=None, - min_object_covered=1.0, - aspect_ratio_range=(0.75, 1.33), - area_range=(0.1, 1.0), - overlap_thresh=0.3, - random_coef=0.0, - min_padded_size_ratio=(1.0, 1.0), - max_padded_size_ratio=(2.0, 2.0), - pad_color=None, - seed=None, - preprocess_vars_cache=None): - """Randomly crops and pads the image. - - Given an input image and its bounding boxes, this op first randomly crops - the image and then randomly pads the image with background values. Parameters - min_padded_size_ratio and max_padded_size_ratio, determine the range of the - final output image size. Specifically, the final image size will have a size - in the range of min_padded_size_ratio * tf.shape(image) and - max_padded_size_ratio * tf.shape(image). Note that these ratios are with - respect to the size of the original image, so we can't capture the same - effect easily by independently applying RandomCropImage - followed by RandomPadImage. - - Args: - image: rank 3 float32 tensor containing 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - labels: rank 1 int32 tensor containing the object classes. - label_scores: rank 1 float32 containing the label scores. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - min_object_covered: the cropped image must cover at least this fraction of - at least one of the input bounding boxes. - aspect_ratio_range: allowed range for aspect ratio of cropped image. - area_range: allowed range for area ratio between cropped image and the - original image. - overlap_thresh: minimum overlap thresh with new cropped - image to keep the box. - random_coef: a random coefficient that defines the chance of getting the - original image. If random_coef is 0, we will always get the - cropped image, and if it is 1.0, we will always get the - original image. - min_padded_size_ratio: min ratio of padded image height and width to the - input image's height and width. - max_padded_size_ratio: max ratio of padded image height and width to the - input image's height and width. - pad_color: padding color. A rank 1 tensor of [3] with dtype=tf.float32. - if set as None, it will be set to average color of the randomly - cropped image. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - padded_image: padded image. - padded_boxes: boxes which is the same rank as input boxes. Boxes are in - normalized form. - cropped_labels: cropped labels. - if label_scores is not None also returns: - cropped_label_scores: cropped label scores. - if multiclass_scores is not None also returns: - cropped_multiclass_scores: cropped_multiclass_scores. - - """ - image_size = tf.shape(image) - image_height = image_size[0] - image_width = image_size[1] - result = random_crop_image( - image=image, - boxes=boxes, - labels=labels, - label_scores=label_scores, - multiclass_scores=multiclass_scores, - min_object_covered=min_object_covered, - aspect_ratio_range=aspect_ratio_range, - area_range=area_range, - overlap_thresh=overlap_thresh, - random_coef=random_coef, - seed=seed, - preprocess_vars_cache=preprocess_vars_cache) - - cropped_image, cropped_boxes, cropped_labels = result[:3] - - min_image_size = tf.to_int32( - tf.to_float(tf.stack([image_height, image_width])) * - min_padded_size_ratio) - max_image_size = tf.to_int32( - tf.to_float(tf.stack([image_height, image_width])) * - max_padded_size_ratio) - - padded_image, padded_boxes = random_pad_image( - cropped_image, - cropped_boxes, - min_image_size=min_image_size, - max_image_size=max_image_size, - pad_color=pad_color, - seed=seed, - preprocess_vars_cache=preprocess_vars_cache) - - cropped_padded_output = (padded_image, padded_boxes, cropped_labels) - - index = 3 - if label_scores is not None: - cropped_label_scores = result[index] - cropped_padded_output += (cropped_label_scores,) - index += 1 - - if multiclass_scores is not None: - cropped_multiclass_scores = result[index] - cropped_padded_output += (cropped_multiclass_scores,) - - return cropped_padded_output - - -def random_crop_to_aspect_ratio(image, - boxes, - labels, - label_scores=None, - multiclass_scores=None, - masks=None, - keypoints=None, - aspect_ratio=1.0, - overlap_thresh=0.3, - seed=None, - preprocess_vars_cache=None): - """Randomly crops an image to the specified aspect ratio. - - Randomly crops the a portion of the image such that the crop is of the - specified aspect ratio, and the crop is as large as possible. If the specified - aspect ratio is larger than the aspect ratio of the image, this op will - randomly remove rows from the top and bottom of the image. If the specified - aspect ratio is less than the aspect ratio of the image, this op will randomly - remove cols from the left and right of the image. If the specified aspect - ratio is the same as the aspect ratio of the image, this op will return the - image. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - labels: rank 1 int32 tensor containing the object classes. - label_scores: (optional) float32 tensor of shape [num_instances] - representing the score for each box. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - aspect_ratio: the aspect ratio of cropped image. - overlap_thresh: minimum overlap thresh with new cropped - image to keep the box. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same rank as input image. - boxes: boxes which is the same rank as input boxes. - Boxes are in normalized form. - labels: new labels. - - If label_scores, masks, keypoints, or multiclass_scores is not None, the - function also returns: - label_scores: rank 1 float32 tensor with shape [num_instances]. - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - multiclass_scores: rank 2 float32 tensor with shape - [num_instances, num_classes] - - Raises: - ValueError: If image is not a 3D tensor. - """ - if len(image.get_shape()) != 3: - raise ValueError('Image should be 3D tensor') - - with tf.name_scope('RandomCropToAspectRatio', values=[image]): - image_shape = tf.shape(image) - orig_height = image_shape[0] - orig_width = image_shape[1] - orig_aspect_ratio = tf.to_float(orig_width) / tf.to_float(orig_height) - new_aspect_ratio = tf.constant(aspect_ratio, dtype=tf.float32) - def target_height_fn(): - return tf.to_int32(tf.round(tf.to_float(orig_width) / new_aspect_ratio)) - - target_height = tf.cond(orig_aspect_ratio >= new_aspect_ratio, - lambda: orig_height, target_height_fn) - - def target_width_fn(): - return tf.to_int32(tf.round(tf.to_float(orig_height) * new_aspect_ratio)) - - target_width = tf.cond(orig_aspect_ratio <= new_aspect_ratio, - lambda: orig_width, target_width_fn) - - # either offset_height = 0 and offset_width is randomly chosen from - # [0, offset_width - target_width), or else offset_width = 0 and - # offset_height is randomly chosen from [0, offset_height - target_height) - offset_height = _random_integer(0, orig_height - target_height + 1, seed) - offset_width = _random_integer(0, orig_width - target_width + 1, seed) - - generator_func = lambda: (offset_height, offset_width) - offset_height, offset_width = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.CROP_TO_ASPECT_RATIO, - preprocess_vars_cache) - - new_image = tf.image.crop_to_bounding_box( - image, offset_height, offset_width, target_height, target_width) - - im_box = tf.stack([ - tf.to_float(offset_height) / tf.to_float(orig_height), - tf.to_float(offset_width) / tf.to_float(orig_width), - tf.to_float(offset_height + target_height) / tf.to_float(orig_height), - tf.to_float(offset_width + target_width) / tf.to_float(orig_width) - ]) - - boxlist = box_list.BoxList(boxes) - boxlist.add_field('labels', labels) - - if label_scores is not None: - boxlist.add_field('label_scores', label_scores) - - if multiclass_scores is not None: - boxlist.add_field('multiclass_scores', multiclass_scores) - - im_boxlist = box_list.BoxList(tf.expand_dims(im_box, 0)) - - # remove boxes whose overlap with the image is less than overlap_thresh - overlapping_boxlist, keep_ids = box_list_ops.prune_non_overlapping_boxes( - boxlist, im_boxlist, overlap_thresh) - - # change the coordinate of the remaining boxes - new_labels = overlapping_boxlist.get_field('labels') - new_boxlist = box_list_ops.change_coordinate_frame(overlapping_boxlist, - im_box) - new_boxlist = box_list_ops.clip_to_window(new_boxlist, - tf.constant([0.0, 0.0, 1.0, 1.0], - tf.float32)) - new_boxes = new_boxlist.get() - - result = [new_image, new_boxes, new_labels] - - if label_scores is not None: - new_label_scores = overlapping_boxlist.get_field('label_scores') - result.append(new_label_scores) - - if multiclass_scores is not None: - new_multiclass_scores = overlapping_boxlist.get_field('multiclass_scores') - result.append(new_multiclass_scores) - - if masks is not None: - masks_inside_window = tf.gather(masks, keep_ids) - masks_box_begin = tf.stack([0, offset_height, offset_width]) - masks_box_size = tf.stack([-1, target_height, target_width]) - new_masks = tf.slice(masks_inside_window, masks_box_begin, masks_box_size) - result.append(new_masks) - - if keypoints is not None: - keypoints_inside_window = tf.gather(keypoints, keep_ids) - new_keypoints = keypoint_ops.change_coordinate_frame( - keypoints_inside_window, im_box) - new_keypoints = keypoint_ops.prune_outside_window(new_keypoints, - [0.0, 0.0, 1.0, 1.0]) - result.append(new_keypoints) - - return tuple(result) - - -def random_pad_to_aspect_ratio(image, - boxes, - masks=None, - keypoints=None, - aspect_ratio=1.0, - min_padded_size_ratio=(1.0, 1.0), - max_padded_size_ratio=(2.0, 2.0), - seed=None, - preprocess_vars_cache=None): - """Randomly zero pads an image to the specified aspect ratio. - - Pads the image so that the resulting image will have the specified aspect - ratio without scaling less than the min_padded_size_ratio or more than the - max_padded_size_ratio. If the min_padded_size_ratio or max_padded_size_ratio - is lower than what is possible to maintain the aspect ratio, then this method - will use the least padding to achieve the specified aspect ratio. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - aspect_ratio: aspect ratio of the final image. - min_padded_size_ratio: min ratio of padded image height and width to the - input image's height and width. - max_padded_size_ratio: max ratio of padded image height and width to the - input image's height and width. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same rank as input image. - boxes: boxes which is the same rank as input boxes. - Boxes are in normalized form. - labels: new labels. - - If masks, or keypoints is not None, the function also returns: - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - - Raises: - ValueError: If image is not a 3D tensor. - """ - if len(image.get_shape()) != 3: - raise ValueError('Image should be 3D tensor') - - with tf.name_scope('RandomPadToAspectRatio', values=[image]): - image_shape = tf.shape(image) - image_height = tf.to_float(image_shape[0]) - image_width = tf.to_float(image_shape[1]) - image_aspect_ratio = image_width / image_height - new_aspect_ratio = tf.constant(aspect_ratio, dtype=tf.float32) - target_height = tf.cond( - image_aspect_ratio <= new_aspect_ratio, - lambda: image_height, - lambda: image_width / new_aspect_ratio) - target_width = tf.cond( - image_aspect_ratio >= new_aspect_ratio, - lambda: image_width, - lambda: image_height * new_aspect_ratio) - - min_height = tf.maximum( - min_padded_size_ratio[0] * image_height, target_height) - min_width = tf.maximum( - min_padded_size_ratio[1] * image_width, target_width) - max_height = tf.maximum( - max_padded_size_ratio[0] * image_height, target_height) - max_width = tf.maximum( - max_padded_size_ratio[1] * image_width, target_width) - - max_scale = tf.minimum(max_height / target_height, max_width / target_width) - min_scale = tf.minimum( - max_scale, - tf.maximum(min_height / target_height, min_width / target_width)) - - generator_func = functools.partial(tf.random_uniform, [], - min_scale, max_scale, seed=seed) - scale = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.PAD_TO_ASPECT_RATIO, - preprocess_vars_cache) - - target_height = tf.round(scale * target_height) - target_width = tf.round(scale * target_width) - - new_image = tf.image.pad_to_bounding_box( - image, 0, 0, tf.to_int32(target_height), tf.to_int32(target_width)) - - im_box = tf.stack([ - 0.0, - 0.0, - target_height / image_height, - target_width / image_width - ]) - boxlist = box_list.BoxList(boxes) - new_boxlist = box_list_ops.change_coordinate_frame(boxlist, im_box) - new_boxes = new_boxlist.get() - - result = [new_image, new_boxes] - - if masks is not None: - new_masks = tf.expand_dims(masks, -1) - new_masks = tf.image.pad_to_bounding_box(new_masks, 0, 0, - tf.to_int32(target_height), - tf.to_int32(target_width)) - new_masks = tf.squeeze(new_masks, [-1]) - result.append(new_masks) - - if keypoints is not None: - new_keypoints = keypoint_ops.change_coordinate_frame(keypoints, im_box) - result.append(new_keypoints) - - return tuple(result) - - -def random_black_patches(image, - max_black_patches=10, - probability=0.5, - size_to_image_ratio=0.1, - random_seed=None, - preprocess_vars_cache=None): - """Randomly adds some black patches to the image. - - This op adds up to max_black_patches square black patches of a fixed size - to the image where size is specified via the size_to_image_ratio parameter. - - Args: - image: rank 3 float32 tensor containing 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - max_black_patches: number of times that the function tries to add a - black box to the image. - probability: at each try, what is the chance of adding a box. - size_to_image_ratio: Determines the ratio of the size of the black patches - to the size of the image. - box_size = size_to_image_ratio * - min(image_width, image_height) - random_seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image - """ - def add_black_patch_to_image(image, idx): - """Function for adding one patch to the image. - - Args: - image: image - idx: counter for number of patches that could have been added - - Returns: - image with a randomly added black box - """ - image_shape = tf.shape(image) - image_height = image_shape[0] - image_width = image_shape[1] - box_size = tf.to_int32( - tf.multiply( - tf.minimum(tf.to_float(image_height), tf.to_float(image_width)), - size_to_image_ratio)) - - generator_func = functools.partial(tf.random_uniform, [], minval=0.0, - maxval=(1.0 - size_to_image_ratio), - seed=random_seed) - normalized_y_min = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.ADD_BLACK_PATCH, - preprocess_vars_cache, key=str(idx) + 'y') - normalized_x_min = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.ADD_BLACK_PATCH, - preprocess_vars_cache, key=str(idx) + 'x') - - y_min = tf.to_int32(normalized_y_min * tf.to_float(image_height)) - x_min = tf.to_int32(normalized_x_min * tf.to_float(image_width)) - black_box = tf.ones([box_size, box_size, 3], dtype=tf.float32) - mask = 1.0 - tf.image.pad_to_bounding_box(black_box, y_min, x_min, - image_height, image_width) - image = tf.multiply(image, mask) - return image - - with tf.name_scope('RandomBlackPatchInImage', values=[image]): - for idx in range(max_black_patches): - generator_func = functools.partial(tf.random_uniform, [], - minval=0.0, maxval=1.0, - dtype=tf.float32, seed=random_seed) - random_prob = _get_or_create_preprocess_rand_vars( - generator_func, - preprocessor_cache.PreprocessorCache.BLACK_PATCHES, - preprocess_vars_cache, key=idx) - image = tf.cond( - tf.greater(random_prob, probability), lambda: image, - functools.partial(add_black_patch_to_image, image=image, idx=idx)) - return image - - -def image_to_float(image): - """Used in Faster R-CNN. Casts image pixel values to float. - - Args: - image: input image which might be in tf.uint8 or sth else format - - Returns: - image: image in tf.float32 format. - """ - with tf.name_scope('ImageToFloat', values=[image]): - image = tf.to_float(image) - return image - - -def random_resize_method(image, target_size, preprocess_vars_cache=None): - """Uses a random resize method to resize the image to target size. - - Args: - image: a rank 3 tensor. - target_size: a list of [target_height, target_width] - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - resized image. - """ - - resized_image = _apply_with_random_selector( - image, - lambda x, method: tf.image.resize_images(x, target_size, method), - num_cases=4, - preprocess_vars_cache=preprocess_vars_cache, - key=preprocessor_cache.PreprocessorCache.RESIZE_METHOD) - - return resized_image - - -def _compute_new_static_size(image, min_dimension, max_dimension): - """Compute new static shape for resize_to_range method.""" - image_shape = image.get_shape().as_list() - orig_height = image_shape[0] - orig_width = image_shape[1] - num_channels = image_shape[2] - orig_min_dim = min(orig_height, orig_width) - # Calculates the larger of the possible sizes - large_scale_factor = min_dimension / float(orig_min_dim) - # Scaling orig_(height|width) by large_scale_factor will make the smaller - # dimension equal to min_dimension, save for floating point rounding errors. - # For reasonably-sized images, taking the nearest integer will reliably - # eliminate this error. - large_height = int(round(orig_height * large_scale_factor)) - large_width = int(round(orig_width * large_scale_factor)) - large_size = [large_height, large_width] - if max_dimension: - # Calculates the smaller of the possible sizes, use that if the larger - # is too big. - orig_max_dim = max(orig_height, orig_width) - small_scale_factor = max_dimension / float(orig_max_dim) - # Scaling orig_(height|width) by small_scale_factor will make the larger - # dimension equal to max_dimension, save for floating point rounding - # errors. For reasonably-sized images, taking the nearest integer will - # reliably eliminate this error. - small_height = int(round(orig_height * small_scale_factor)) - small_width = int(round(orig_width * small_scale_factor)) - small_size = [small_height, small_width] - new_size = large_size - if max(large_size) > max_dimension: - new_size = small_size - else: - new_size = large_size - return tf.constant(new_size + [num_channels]) - - -def _compute_new_dynamic_size(image, min_dimension, max_dimension): - """Compute new dynamic shape for resize_to_range method.""" - image_shape = tf.shape(image) - orig_height = tf.to_float(image_shape[0]) - orig_width = tf.to_float(image_shape[1]) - num_channels = image_shape[2] - orig_min_dim = tf.minimum(orig_height, orig_width) - # Calculates the larger of the possible sizes - min_dimension = tf.constant(min_dimension, dtype=tf.float32) - large_scale_factor = min_dimension / orig_min_dim - # Scaling orig_(height|width) by large_scale_factor will make the smaller - # dimension equal to min_dimension, save for floating point rounding errors. - # For reasonably-sized images, taking the nearest integer will reliably - # eliminate this error. - large_height = tf.to_int32(tf.round(orig_height * large_scale_factor)) - large_width = tf.to_int32(tf.round(orig_width * large_scale_factor)) - large_size = tf.stack([large_height, large_width]) - if max_dimension: - # Calculates the smaller of the possible sizes, use that if the larger - # is too big. - orig_max_dim = tf.maximum(orig_height, orig_width) - max_dimension = tf.constant(max_dimension, dtype=tf.float32) - small_scale_factor = max_dimension / orig_max_dim - # Scaling orig_(height|width) by small_scale_factor will make the larger - # dimension equal to max_dimension, save for floating point rounding - # errors. For reasonably-sized images, taking the nearest integer will - # reliably eliminate this error. - small_height = tf.to_int32(tf.round(orig_height * small_scale_factor)) - small_width = tf.to_int32(tf.round(orig_width * small_scale_factor)) - small_size = tf.stack([small_height, small_width]) - new_size = tf.cond( - tf.to_float(tf.reduce_max(large_size)) > max_dimension, - lambda: small_size, lambda: large_size) - else: - new_size = large_size - return tf.stack(tf.unstack(new_size) + [num_channels]) - - -def resize_to_range(image, - masks=None, - min_dimension=None, - max_dimension=None, - method=tf.image.ResizeMethod.BILINEAR, - align_corners=False, - pad_to_max_dimension=False, - per_channel_pad_value=(0, 0, 0)): - """Resizes an image so its dimensions are within the provided value. - - The output size can be described by two cases: - 1. If the image can be rescaled so its minimum dimension is equal to the - provided value without the other dimension exceeding max_dimension, - then do so. - 2. Otherwise, resize so the largest dimension is equal to max_dimension. - - Args: - image: A 3D tensor of shape [height, width, channels] - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. - min_dimension: (optional) (scalar) desired size of the smaller image - dimension. - max_dimension: (optional) (scalar) maximum allowed size - of the larger image dimension. - method: (optional) interpolation method used in resizing. Defaults to - BILINEAR. - align_corners: bool. If true, exactly align all 4 corners of the input - and output. Defaults to False. - pad_to_max_dimension: Whether to resize the image and pad it with zeros - so the resulting image is of the spatial size - [max_dimension, max_dimension]. If masks are included they are padded - similarly. - per_channel_pad_value: A tuple of per-channel scalar value to use for - padding. By default pads zeros. - - Returns: - Note that the position of the resized_image_shape changes based on whether - masks are present. - resized_image: A 3D tensor of shape [new_height, new_width, channels], - where the image has been resized (with bilinear interpolation) so that - min(new_height, new_width) == min_dimension or - max(new_height, new_width) == max_dimension. - resized_masks: If masks is not None, also outputs masks. A 3D tensor of - shape [num_instances, new_height, new_width]. - resized_image_shape: A 1D tensor of shape [3] containing shape of the - resized image. - - Raises: - ValueError: if the image is not a 3D tensor. - """ - if len(image.get_shape()) != 3: - raise ValueError('Image should be 3D tensor') - - with tf.name_scope('ResizeToRange', values=[image, min_dimension]): - if image.get_shape().is_fully_defined(): - new_size = _compute_new_static_size(image, min_dimension, max_dimension) - else: - new_size = _compute_new_dynamic_size(image, min_dimension, max_dimension) - new_image = tf.image.resize_images( - image, new_size[:-1], method=method, align_corners=align_corners) - - if pad_to_max_dimension: - channels = tf.unstack(new_image, axis=2) - if len(channels) != len(per_channel_pad_value): - raise ValueError('Number of channels must be equal to the length of ' - 'per-channel pad value.') - new_image = tf.stack( - [ - tf.pad( - channels[i], [[0, max_dimension - new_size[0]], - [0, max_dimension - new_size[1]]], - constant_values=per_channel_pad_value[i]) - for i in range(len(channels)) - ], - axis=2) - new_image.set_shape([max_dimension, max_dimension, 3]) - - result = [new_image] - if masks is not None: - new_masks = tf.expand_dims(masks, 3) - new_masks = tf.image.resize_images( - new_masks, - new_size[:-1], - method=tf.image.ResizeMethod.NEAREST_NEIGHBOR, - align_corners=align_corners) - new_masks = tf.squeeze(new_masks, 3) - if pad_to_max_dimension: - new_masks = tf.image.pad_to_bounding_box( - new_masks, 0, 0, max_dimension, max_dimension) - result.append(new_masks) - - result.append(new_size) - return result - - -# TODO(alirezafathi): Make sure the static shapes are preserved. -def resize_to_min_dimension(image, masks=None, min_dimension=600): - """Resizes image and masks given the min size maintaining the aspect ratio. - - If one of the image dimensions is smaller that min_dimension, it will scale - the image such that its smallest dimension is equal to min_dimension. - Otherwise, will keep the image size as is. - - Args: - image: a tensor of size [height, width, channels]. - masks: (optional) a tensors of size [num_instances, height, width]. - min_dimension: minimum image dimension. - - Returns: - Note that the position of the resized_image_shape changes based on whether - masks are present. - resized_image: A tensor of size [new_height, new_width, channels]. - resized_masks: If masks is not None, also outputs masks. A 3D tensor of - shape [num_instances, new_height, new_width] - resized_image_shape: A 1D tensor of shape [3] containing the shape of the - resized image. - - Raises: - ValueError: if the image is not a 3D tensor. - """ - if len(image.get_shape()) != 3: - raise ValueError('Image should be 3D tensor') - - with tf.name_scope('ResizeGivenMinDimension', values=[image, min_dimension]): - image_height = tf.shape(image)[0] - image_width = tf.shape(image)[1] - num_channels = tf.shape(image)[2] - min_image_dimension = tf.minimum(image_height, image_width) - min_target_dimension = tf.maximum(min_image_dimension, min_dimension) - target_ratio = tf.to_float(min_target_dimension) / tf.to_float( - min_image_dimension) - target_height = tf.to_int32(tf.to_float(image_height) * target_ratio) - target_width = tf.to_int32(tf.to_float(image_width) * target_ratio) - image = tf.image.resize_bilinear( - tf.expand_dims(image, axis=0), - size=[target_height, target_width], - align_corners=True) - result = [tf.squeeze(image, axis=0)] - - if masks is not None: - masks = tf.image.resize_nearest_neighbor( - tf.expand_dims(masks, axis=3), - size=[target_height, target_width], - align_corners=True) - result.append(tf.squeeze(masks, axis=3)) - - result.append(tf.stack([target_height, target_width, num_channels])) - return result - - -def scale_boxes_to_pixel_coordinates(image, boxes, keypoints=None): - """Scales boxes from normalized to pixel coordinates. - - Args: - image: A 3D float32 tensor of shape [height, width, channels]. - boxes: A 2D float32 tensor of shape [num_boxes, 4] containing the bounding - boxes in normalized coordinates. Each row is of the form - [ymin, xmin, ymax, xmax]. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x normalized - coordinates. - - Returns: - image: unchanged input image. - scaled_boxes: a 2D float32 tensor of shape [num_boxes, 4] containing the - bounding boxes in pixel coordinates. - scaled_keypoints: a 3D float32 tensor with shape - [num_instances, num_keypoints, 2] containing the keypoints in pixel - coordinates. - """ - boxlist = box_list.BoxList(boxes) - image_height = tf.shape(image)[0] - image_width = tf.shape(image)[1] - scaled_boxes = box_list_ops.scale(boxlist, image_height, image_width).get() - result = [image, scaled_boxes] - if keypoints is not None: - scaled_keypoints = keypoint_ops.scale(keypoints, image_height, image_width) - result.append(scaled_keypoints) - return tuple(result) - - -# TODO(alirezafathi): Investigate if instead the function should return None if -# masks is None. -# pylint: disable=g-doc-return-or-yield -def resize_image(image, - masks=None, - new_height=600, - new_width=1024, - method=tf.image.ResizeMethod.BILINEAR, - align_corners=False): - """Resizes images to the given height and width. - - Args: - image: A 3D tensor of shape [height, width, channels] - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. - new_height: (optional) (scalar) desired height of the image. - new_width: (optional) (scalar) desired width of the image. - method: (optional) interpolation method used in resizing. Defaults to - BILINEAR. - align_corners: bool. If true, exactly align all 4 corners of the input - and output. Defaults to False. - - Returns: - Note that the position of the resized_image_shape changes based on whether - masks are present. - resized_image: A tensor of size [new_height, new_width, channels]. - resized_masks: If masks is not None, also outputs masks. A 3D tensor of - shape [num_instances, new_height, new_width] - resized_image_shape: A 1D tensor of shape [3] containing the shape of the - resized image. - """ - with tf.name_scope( - 'ResizeImage', - values=[image, new_height, new_width, method, align_corners]): - new_image = tf.image.resize_images( - image, tf.stack([new_height, new_width]), - method=method, - align_corners=align_corners) - image_shape = shape_utils.combined_static_and_dynamic_shape(image) - result = [new_image] - if masks is not None: - num_instances = tf.shape(masks)[0] - new_size = tf.stack([new_height, new_width]) - def resize_masks_branch(): - new_masks = tf.expand_dims(masks, 3) - new_masks = tf.image.resize_nearest_neighbor( - new_masks, new_size, align_corners=align_corners) - new_masks = tf.squeeze(new_masks, axis=3) - return new_masks - - def reshape_masks_branch(): - # The shape function will be computed for both branches of the - # condition, regardless of which branch is actually taken. Make sure - # that we don't trigger an assertion in the shape function when trying - # to reshape a non empty tensor into an empty one. - new_masks = tf.reshape(masks, [-1, new_size[0], new_size[1]]) - return new_masks - - masks = tf.cond(num_instances > 0, resize_masks_branch, - reshape_masks_branch) - result.append(masks) - - result.append(tf.stack([new_height, new_width, image_shape[2]])) - return result - - -def subtract_channel_mean(image, means=None): - """Normalizes an image by subtracting a mean from each channel. - - Args: - image: A 3D tensor of shape [height, width, channels] - means: float list containing a mean for each channel - Returns: - normalized_images: a tensor of shape [height, width, channels] - Raises: - ValueError: if images is not a 4D tensor or if the number of means is not - equal to the number of channels. - """ - with tf.name_scope('SubtractChannelMean', values=[image, means]): - if len(image.get_shape()) != 3: - raise ValueError('Input must be of size [height, width, channels]') - if len(means) != image.get_shape()[-1]: - raise ValueError('len(means) must match the number of channels') - return image - [[means]] - - -def one_hot_encoding(labels, num_classes=None): - """One-hot encodes the multiclass labels. - - Example usage: - labels = tf.constant([1, 4], dtype=tf.int32) - one_hot = OneHotEncoding(labels, num_classes=5) - one_hot.eval() # evaluates to [0, 1, 0, 0, 1] - - Args: - labels: A tensor of shape [None] corresponding to the labels. - num_classes: Number of classes in the dataset. - Returns: - onehot_labels: a tensor of shape [num_classes] corresponding to the one hot - encoding of the labels. - Raises: - ValueError: if num_classes is not specified. - """ - with tf.name_scope('OneHotEncoding', values=[labels]): - if num_classes is None: - raise ValueError('num_classes must be specified') - - labels = tf.one_hot(labels, num_classes, 1, 0) - return tf.reduce_max(labels, 0) - - -def rgb_to_gray(image): - """Converts a 3 channel RGB image to a 1 channel grayscale image. - - Args: - image: Rank 3 float32 tensor containing 1 image -> [height, width, 3] - with pixel values varying between [0, 1]. - - Returns: - image: A single channel grayscale image -> [image, height, 1]. - """ - return _rgb_to_grayscale(image) - - -def ssd_random_crop(image, - boxes, - labels, - label_scores=None, - multiclass_scores=None, - masks=None, - keypoints=None, - min_object_covered=(0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0), - aspect_ratio_range=((0.5, 2.0),) * 7, - area_range=((0.1, 1.0),) * 7, - overlap_thresh=(0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0), - random_coef=(0.15,) * 7, - seed=None, - preprocess_vars_cache=None): - """Random crop preprocessing with default parameters as in SSD paper. - - Liu et al., SSD: Single shot multibox detector. - For further information on random crop preprocessing refer to RandomCrop - function above. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - labels: rank 1 int32 tensor containing the object classes. - label_scores: rank 1 float32 tensor containing the scores. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - min_object_covered: the cropped image must cover at least this fraction of - at least one of the input bounding boxes. - aspect_ratio_range: allowed range for aspect ratio of cropped image. - area_range: allowed range for area ratio between cropped image and the - original image. - overlap_thresh: minimum overlap thresh with new cropped - image to keep the box. - random_coef: a random coefficient that defines the chance of getting the - original image. If random_coef is 0, we will always get the - cropped image, and if it is 1.0, we will always get the - original image. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same rank as input image. - boxes: boxes which is the same rank as input boxes. - Boxes are in normalized form. - labels: new labels. - - If label_scores, multiclass_scores, masks, or keypoints is not None, the - function also returns: - label_scores: rank 1 float32 tensor with shape [num_instances]. - multiclass_scores: rank 2 float32 tensor with shape - [num_instances, num_classes] - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - """ - - def random_crop_selector(selected_result, index): - """Applies random_crop_image to selected result. - - Args: - selected_result: A tuple containing image, boxes, labels, keypoints (if - not None), and masks (if not None). - index: The index that was randomly selected. - - Returns: A tuple containing image, boxes, labels, keypoints (if not None), - and masks (if not None). - """ - - i = 3 - image, boxes, labels = selected_result[:i] - selected_label_scores = None - selected_multiclass_scores = None - selected_masks = None - selected_keypoints = None - if label_scores is not None: - selected_label_scores = selected_result[i] - i += 1 - if multiclass_scores is not None: - selected_multiclass_scores = selected_result[i] - i += 1 - if masks is not None: - selected_masks = selected_result[i] - i += 1 - if keypoints is not None: - selected_keypoints = selected_result[i] - - return random_crop_image( - image=image, - boxes=boxes, - labels=labels, - label_scores=selected_label_scores, - multiclass_scores=selected_multiclass_scores, - masks=selected_masks, - keypoints=selected_keypoints, - min_object_covered=min_object_covered[index], - aspect_ratio_range=aspect_ratio_range[index], - area_range=area_range[index], - overlap_thresh=overlap_thresh[index], - random_coef=random_coef[index], - seed=seed, - preprocess_vars_cache=preprocess_vars_cache) - - result = _apply_with_random_selector_tuples( - tuple( - t for t in (image, boxes, labels, label_scores, multiclass_scores, - masks, keypoints) if t is not None), - random_crop_selector, - num_cases=len(min_object_covered), - preprocess_vars_cache=preprocess_vars_cache, - key=preprocessor_cache.PreprocessorCache.SSD_CROP_SELECTOR_ID) - return result - - -def ssd_random_crop_pad(image, - boxes, - labels, - label_scores=None, - multiclass_scores=None, - min_object_covered=(0.1, 0.3, 0.5, 0.7, 0.9, 1.0), - aspect_ratio_range=((0.5, 2.0),) * 6, - area_range=((0.1, 1.0),) * 6, - overlap_thresh=(0.1, 0.3, 0.5, 0.7, 0.9, 1.0), - random_coef=(0.15,) * 6, - min_padded_size_ratio=((1.0, 1.0),) * 6, - max_padded_size_ratio=((2.0, 2.0),) * 6, - pad_color=(None,) * 6, - seed=None, - preprocess_vars_cache=None): - """Random crop preprocessing with default parameters as in SSD paper. - - Liu et al., SSD: Single shot multibox detector. - For further information on random crop preprocessing refer to RandomCrop - function above. - - Args: - image: rank 3 float32 tensor containing 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - labels: rank 1 int32 tensor containing the object classes. - label_scores: float32 tensor of shape [num_instances] representing the - score for each box. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - min_object_covered: the cropped image must cover at least this fraction of - at least one of the input bounding boxes. - aspect_ratio_range: allowed range for aspect ratio of cropped image. - area_range: allowed range for area ratio between cropped image and the - original image. - overlap_thresh: minimum overlap thresh with new cropped - image to keep the box. - random_coef: a random coefficient that defines the chance of getting the - original image. If random_coef is 0, we will always get the - cropped image, and if it is 1.0, we will always get the - original image. - min_padded_size_ratio: min ratio of padded image height and width to the - input image's height and width. - max_padded_size_ratio: max ratio of padded image height and width to the - input image's height and width. - pad_color: padding color. A rank 1 tensor of [3] with dtype=tf.float32. - if set as None, it will be set to average color of the randomly - cropped image. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: Image shape will be [new_height, new_width, channels]. - boxes: boxes which is the same rank as input boxes. Boxes are in normalized - form. - new_labels: new labels. - new_label_scores: new label scores. - """ - - def random_crop_pad_selector(image_boxes_labels, index): - """Random crop preprocessing helper.""" - i = 3 - image, boxes, labels = image_boxes_labels[:i] - selected_label_scores = None - selected_multiclass_scores = None - if label_scores is not None: - selected_label_scores = image_boxes_labels[i] - i += 1 - if multiclass_scores is not None: - selected_multiclass_scores = image_boxes_labels[i] - - return random_crop_pad_image( - image, - boxes, - labels, - label_scores=selected_label_scores, - multiclass_scores=selected_multiclass_scores, - min_object_covered=min_object_covered[index], - aspect_ratio_range=aspect_ratio_range[index], - area_range=area_range[index], - overlap_thresh=overlap_thresh[index], - random_coef=random_coef[index], - min_padded_size_ratio=min_padded_size_ratio[index], - max_padded_size_ratio=max_padded_size_ratio[index], - pad_color=pad_color[index], - seed=seed, - preprocess_vars_cache=preprocess_vars_cache) - - return _apply_with_random_selector_tuples( - tuple(t for t in (image, boxes, labels, label_scores, multiclass_scores) - if t is not None), - random_crop_pad_selector, - num_cases=len(min_object_covered), - preprocess_vars_cache=preprocess_vars_cache, - key=preprocessor_cache.PreprocessorCache.SSD_CROP_PAD_SELECTOR_ID) - - -def ssd_random_crop_fixed_aspect_ratio( - image, - boxes, - labels, - label_scores=None, - multiclass_scores=None, - masks=None, - keypoints=None, - min_object_covered=(0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0), - aspect_ratio=1.0, - area_range=((0.1, 1.0),) * 7, - overlap_thresh=(0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0), - random_coef=(0.15,) * 7, - seed=None, - preprocess_vars_cache=None): - """Random crop preprocessing with default parameters as in SSD paper. - - Liu et al., SSD: Single shot multibox detector. - For further information on random crop preprocessing refer to RandomCrop - function above. - - The only difference is that the aspect ratio of the crops are fixed. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - labels: rank 1 int32 tensor containing the object classes. - label_scores: (optional) float32 tensor of shape [num_instances] - representing the score for each box. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - min_object_covered: the cropped image must cover at least this fraction of - at least one of the input bounding boxes. - aspect_ratio: aspect ratio of the cropped image. - area_range: allowed range for area ratio between cropped image and the - original image. - overlap_thresh: minimum overlap thresh with new cropped - image to keep the box. - random_coef: a random coefficient that defines the chance of getting the - original image. If random_coef is 0, we will always get the - cropped image, and if it is 1.0, we will always get the - original image. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same rank as input image. - boxes: boxes which is the same rank as input boxes. - Boxes are in normalized form. - labels: new labels. - - If mulitclass_scores, masks, or keypoints is not None, the function also - returns: - - multiclass_scores: rank 2 float32 tensor with shape - [num_instances, num_classes] - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - """ - aspect_ratio_range = ((aspect_ratio, aspect_ratio),) * len(area_range) - - crop_result = ssd_random_crop( - image, - boxes, - labels, - label_scores=label_scores, - multiclass_scores=multiclass_scores, - masks=masks, - keypoints=keypoints, - min_object_covered=min_object_covered, - aspect_ratio_range=aspect_ratio_range, - area_range=area_range, - overlap_thresh=overlap_thresh, - random_coef=random_coef, - seed=seed, - preprocess_vars_cache=preprocess_vars_cache) - i = 3 - new_image, new_boxes, new_labels = crop_result[:i] - new_label_scores = None - new_multiclass_scores = None - new_masks = None - new_keypoints = None - if label_scores is not None: - new_label_scores = crop_result[i] - i += 1 - if multiclass_scores is not None: - new_multiclass_scores = crop_result[i] - i += 1 - if masks is not None: - new_masks = crop_result[i] - i += 1 - if keypoints is not None: - new_keypoints = crop_result[i] - - result = random_crop_to_aspect_ratio( - new_image, - new_boxes, - new_labels, - label_scores=new_label_scores, - multiclass_scores=new_multiclass_scores, - masks=new_masks, - keypoints=new_keypoints, - aspect_ratio=aspect_ratio, - seed=seed, - preprocess_vars_cache=preprocess_vars_cache) - - return result - - -def ssd_random_crop_pad_fixed_aspect_ratio( - image, - boxes, - labels, - label_scores=None, - multiclass_scores=None, - masks=None, - keypoints=None, - min_object_covered=(0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0), - aspect_ratio=1.0, - aspect_ratio_range=((0.5, 2.0),) * 7, - area_range=((0.1, 1.0),) * 7, - overlap_thresh=(0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0), - random_coef=(0.15,) * 7, - min_padded_size_ratio=(1.0, 1.0), - max_padded_size_ratio=(2.0, 2.0), - seed=None, - preprocess_vars_cache=None): - """Random crop and pad preprocessing with default parameters as in SSD paper. - - Liu et al., SSD: Single shot multibox detector. - For further information on random crop preprocessing refer to RandomCrop - function above. - - The only difference is that after the initial crop, images are zero-padded - to a fixed aspect ratio instead of being resized to that aspect ratio. - - Args: - image: rank 3 float32 tensor contains 1 image -> [height, width, channels] - with pixel values varying between [0, 1]. - boxes: rank 2 float32 tensor containing the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning their coordinates vary - between [0, 1]. - Each row is in the form of [ymin, xmin, ymax, xmax]. - labels: rank 1 int32 tensor containing the object classes. - label_scores: (optional) float32 tensor of shape [num_instances] - representing the score for each box. - multiclass_scores: (optional) float32 tensor of shape - [num_instances, num_classes] representing the score for each box for each - class. - masks: (optional) rank 3 float32 tensor with shape - [num_instances, height, width] containing instance masks. The masks - are of the same height, width as the input `image`. - keypoints: (optional) rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2]. The keypoints are in y-x - normalized coordinates. - min_object_covered: the cropped image must cover at least this fraction of - at least one of the input bounding boxes. - aspect_ratio: the final aspect ratio to pad to. - aspect_ratio_range: allowed range for aspect ratio of cropped image. - area_range: allowed range for area ratio between cropped image and the - original image. - overlap_thresh: minimum overlap thresh with new cropped - image to keep the box. - random_coef: a random coefficient that defines the chance of getting the - original image. If random_coef is 0, we will always get the - cropped image, and if it is 1.0, we will always get the - original image. - min_padded_size_ratio: min ratio of padded image height and width to the - input image's height and width. - max_padded_size_ratio: max ratio of padded image height and width to the - input image's height and width. - seed: random seed. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - image: image which is the same rank as input image. - boxes: boxes which is the same rank as input boxes. - Boxes are in normalized form. - labels: new labels. - - If multiclass_scores, masks, or keypoints is not None, the function also - returns: - - multiclass_scores: rank 2 with shape [num_instances, num_classes] - masks: rank 3 float32 tensor with shape [num_instances, height, width] - containing instance masks. - keypoints: rank 3 float32 tensor with shape - [num_instances, num_keypoints, 2] - """ - crop_result = ssd_random_crop( - image, - boxes, - labels, - label_scores=label_scores, - multiclass_scores=multiclass_scores, - masks=masks, - keypoints=keypoints, - min_object_covered=min_object_covered, - aspect_ratio_range=aspect_ratio_range, - area_range=area_range, - overlap_thresh=overlap_thresh, - random_coef=random_coef, - seed=seed, - preprocess_vars_cache=preprocess_vars_cache) - i = 3 - new_image, new_boxes, new_labels = crop_result[:i] - new_label_scores = None - new_multiclass_scores = None - new_masks = None - new_keypoints = None - if label_scores is not None: - new_label_scores = crop_result[i] - i += 1 - if multiclass_scores is not None: - new_multiclass_scores = crop_result[i] - i += 1 - if masks is not None: - new_masks = crop_result[i] - i += 1 - if keypoints is not None: - new_keypoints = crop_result[i] - - result = random_pad_to_aspect_ratio( - new_image, - new_boxes, - masks=new_masks, - keypoints=new_keypoints, - aspect_ratio=aspect_ratio, - min_padded_size_ratio=min_padded_size_ratio, - max_padded_size_ratio=max_padded_size_ratio, - seed=seed, - preprocess_vars_cache=preprocess_vars_cache) - - result = list(result) - i = 3 - result.insert(2, new_labels) - if new_label_scores is not None: - result.insert(i, new_label_scores) - i += 1 - if multiclass_scores is not None: - result.insert(i, new_multiclass_scores) - result = tuple(result) - - return result - - -def get_default_func_arg_map(include_label_scores=False, - include_multiclass_scores=False, - include_instance_masks=False, - include_keypoints=False): - """Returns the default mapping from a preprocessor function to its args. - - Args: - include_label_scores: If True, preprocessing functions will modify the - label scores, too. - include_multiclass_scores: If True, preprocessing functions will modify the - multiclass scores, too. - include_instance_masks: If True, preprocessing functions will modify the - instance masks, too. - include_keypoints: If True, preprocessing functions will modify the - keypoints, too. - - Returns: - A map from preprocessing functions to the arguments they receive. - """ - groundtruth_label_scores = None - if include_label_scores: - groundtruth_label_scores = (fields.InputDataFields.groundtruth_label_scores) - - multiclass_scores = None - if include_multiclass_scores: - multiclass_scores = (fields.InputDataFields.multiclass_scores) - - groundtruth_instance_masks = None - if include_instance_masks: - groundtruth_instance_masks = ( - fields.InputDataFields.groundtruth_instance_masks) - - groundtruth_keypoints = None - if include_keypoints: - groundtruth_keypoints = fields.InputDataFields.groundtruth_keypoints - - prep_func_arg_map = { - normalize_image: (fields.InputDataFields.image,), - random_horizontal_flip: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - groundtruth_instance_masks, - groundtruth_keypoints, - ), - random_vertical_flip: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - groundtruth_instance_masks, - groundtruth_keypoints, - ), - random_rotation90: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - groundtruth_instance_masks, - groundtruth_keypoints, - ), - random_pixel_value_scale: (fields.InputDataFields.image,), - random_image_scale: ( - fields.InputDataFields.image, - groundtruth_instance_masks, - ), - random_rgb_to_gray: (fields.InputDataFields.image,), - random_adjust_brightness: (fields.InputDataFields.image,), - random_adjust_contrast: (fields.InputDataFields.image,), - random_adjust_hue: (fields.InputDataFields.image,), - random_adjust_saturation: (fields.InputDataFields.image,), - random_distort_color: (fields.InputDataFields.image,), - random_jitter_boxes: (fields.InputDataFields.groundtruth_boxes,), - random_crop_image: (fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - fields.InputDataFields.groundtruth_classes, - groundtruth_label_scores, multiclass_scores, - groundtruth_instance_masks, groundtruth_keypoints), - random_pad_image: (fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes), - random_crop_pad_image: (fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - fields.InputDataFields.groundtruth_classes, - groundtruth_label_scores, - multiclass_scores), - random_crop_to_aspect_ratio: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - fields.InputDataFields.groundtruth_classes, - groundtruth_label_scores, - multiclass_scores, - groundtruth_instance_masks, - groundtruth_keypoints, - ), - random_pad_to_aspect_ratio: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - groundtruth_instance_masks, - groundtruth_keypoints, - ), - random_black_patches: (fields.InputDataFields.image,), - retain_boxes_above_threshold: ( - fields.InputDataFields.groundtruth_boxes, - fields.InputDataFields.groundtruth_classes, - groundtruth_label_scores, - multiclass_scores, - groundtruth_instance_masks, - groundtruth_keypoints, - ), - image_to_float: (fields.InputDataFields.image,), - random_resize_method: (fields.InputDataFields.image,), - resize_to_range: ( - fields.InputDataFields.image, - groundtruth_instance_masks, - ), - resize_to_min_dimension: ( - fields.InputDataFields.image, - groundtruth_instance_masks, - ), - scale_boxes_to_pixel_coordinates: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - groundtruth_keypoints, - ), - resize_image: ( - fields.InputDataFields.image, - groundtruth_instance_masks, - ), - subtract_channel_mean: (fields.InputDataFields.image,), - one_hot_encoding: (fields.InputDataFields.groundtruth_image_classes,), - rgb_to_gray: (fields.InputDataFields.image,), - ssd_random_crop: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - fields.InputDataFields.groundtruth_classes, - groundtruth_label_scores, - multiclass_scores, - groundtruth_instance_masks, - groundtruth_keypoints - ), - ssd_random_crop_pad: (fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - fields.InputDataFields.groundtruth_classes, - groundtruth_label_scores, - multiclass_scores), - ssd_random_crop_fixed_aspect_ratio: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - fields.InputDataFields.groundtruth_classes, groundtruth_label_scores, - multiclass_scores, groundtruth_instance_masks, groundtruth_keypoints), - ssd_random_crop_pad_fixed_aspect_ratio: ( - fields.InputDataFields.image, - fields.InputDataFields.groundtruth_boxes, - fields.InputDataFields.groundtruth_classes, - groundtruth_label_scores, - multiclass_scores, - groundtruth_instance_masks, - groundtruth_keypoints, - ), - } - - return prep_func_arg_map - - -def preprocess(tensor_dict, - preprocess_options, - func_arg_map=None, - preprocess_vars_cache=None): - """Preprocess images and bounding boxes. - - Various types of preprocessing (to be implemented) based on the - preprocess_options dictionary e.g. "crop image" (affects image and possibly - boxes), "white balance image" (affects only image), etc. If self._options - is None, no preprocessing is done. - - Args: - tensor_dict: dictionary that contains images, boxes, and can contain other - things as well. - images-> rank 4 float32 tensor contains - 1 image -> [1, height, width, 3]. - with pixel values varying between [0, 1] - boxes-> rank 2 float32 tensor containing - the bounding boxes -> [N, 4]. - Boxes are in normalized form meaning - their coordinates vary between [0, 1]. - Each row is in the form - of [ymin, xmin, ymax, xmax]. - preprocess_options: It is a list of tuples, where each tuple contains a - function and a dictionary that contains arguments and - their values. - func_arg_map: mapping from preprocessing functions to arguments that they - expect to receive and return. - preprocess_vars_cache: PreprocessorCache object that records previously - performed augmentations. Updated in-place. If this - function is called multiple times with the same - non-null cache, it will perform deterministically. - - Returns: - tensor_dict: which contains the preprocessed images, bounding boxes, etc. - - Raises: - ValueError: (a) If the functions passed to Preprocess - are not in func_arg_map. - (b) If the arguments that a function needs - do not exist in tensor_dict. - (c) If image in tensor_dict is not rank 4 - """ - if func_arg_map is None: - func_arg_map = get_default_func_arg_map() - - # changes the images to image (rank 4 to rank 3) since the functions - # receive rank 3 tensor for image - if fields.InputDataFields.image in tensor_dict: - images = tensor_dict[fields.InputDataFields.image] - if len(images.get_shape()) != 4: - raise ValueError('images in tensor_dict should be rank 4') - image = tf.squeeze(images, squeeze_dims=[0]) - tensor_dict[fields.InputDataFields.image] = image - - # Preprocess inputs based on preprocess_options - for option in preprocess_options: - func, params = option - if func not in func_arg_map: - raise ValueError('The function %s does not exist in func_arg_map' % - (func.__name__)) - arg_names = func_arg_map[func] - for a in arg_names: - if a is not None and a not in tensor_dict: - raise ValueError('The function %s requires argument %s' % - (func.__name__, a)) - - def get_arg(key): - return tensor_dict[key] if key is not None else None - - args = [get_arg(a) for a in arg_names] - if (preprocess_vars_cache is not None and - 'preprocess_vars_cache' in inspect.getargspec(func).args): - params['preprocess_vars_cache'] = preprocess_vars_cache - results = func(*args, **params) - if not isinstance(results, (list, tuple)): - results = (results,) - # Removes None args since the return values will not contain those. - arg_names = [arg_name for arg_name in arg_names if arg_name is not None] - for res, arg_name in zip(results, arg_names): - tensor_dict[arg_name] = res - - # changes the image to images (rank 3 to rank 4) to be compatible to what - # we received in the first place - if fields.InputDataFields.image in tensor_dict: - image = tensor_dict[fields.InputDataFields.image] - images = tf.expand_dims(image, 0) - tensor_dict[fields.InputDataFields.image] = images - - return tensor_dict diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor_cache.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor_cache.py deleted file mode 100644 index 2822a2bab..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor_cache.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Records previous preprocessing operations and allows them to be repeated. - -Used with object_detection.core.preprocessor. Passing a PreprocessorCache -into individual data augmentation functions or the general preprocess() function -will store all randomly generated variables in the PreprocessorCache. When -a preprocessor function is called multiple times with the same -PreprocessorCache object, that function will perform the same augmentation -on all calls. -""" - -from collections import defaultdict - - -class PreprocessorCache(object): - """Dictionary wrapper storing random variables generated during preprocessing. - """ - - # Constant keys representing different preprocessing functions - ROTATION90 = 'rotation90' - HORIZONTAL_FLIP = 'horizontal_flip' - VERTICAL_FLIP = 'vertical_flip' - PIXEL_VALUE_SCALE = 'pixel_value_scale' - IMAGE_SCALE = 'image_scale' - RGB_TO_GRAY = 'rgb_to_gray' - ADJUST_BRIGHTNESS = 'adjust_brightness' - ADJUST_CONTRAST = 'adjust_contrast' - ADJUST_HUE = 'adjust_hue' - ADJUST_SATURATION = 'adjust_saturation' - DISTORT_COLOR = 'distort_color' - STRICT_CROP_IMAGE = 'strict_crop_image' - CROP_IMAGE = 'crop_image' - PAD_IMAGE = 'pad_image' - CROP_TO_ASPECT_RATIO = 'crop_to_aspect_ratio' - RESIZE_METHOD = 'resize_method' - PAD_TO_ASPECT_RATIO = 'pad_to_aspect_ratio' - BLACK_PATCHES = 'black_patches' - ADD_BLACK_PATCH = 'add_black_patch' - SELECTOR = 'selector' - SELECTOR_TUPLES = 'selector_tuples' - SSD_CROP_SELECTOR_ID = 'ssd_crop_selector_id' - SSD_CROP_PAD_SELECTOR_ID = 'ssd_crop_pad_selector_id' - - # 23 permitted function ids - _VALID_FNS = [ROTATION90, HORIZONTAL_FLIP, VERTICAL_FLIP, PIXEL_VALUE_SCALE, - IMAGE_SCALE, RGB_TO_GRAY, ADJUST_BRIGHTNESS, ADJUST_CONTRAST, - ADJUST_HUE, ADJUST_SATURATION, DISTORT_COLOR, STRICT_CROP_IMAGE, - CROP_IMAGE, PAD_IMAGE, CROP_TO_ASPECT_RATIO, RESIZE_METHOD, - PAD_TO_ASPECT_RATIO, BLACK_PATCHES, ADD_BLACK_PATCH, SELECTOR, - SELECTOR_TUPLES, SSD_CROP_SELECTOR_ID, SSD_CROP_PAD_SELECTOR_ID] - - def __init__(self): - self._history = defaultdict(dict) - - def clear(self): - """Resets cache.""" - self._history = {} - - def get(self, function_id, key): - """Gets stored value given a function id and key. - - Args: - function_id: identifier for the preprocessing function used. - key: identifier for the variable stored. - Returns: - value: the corresponding value, expected to be a tensor or - nested structure of tensors. - Raises: - ValueError: if function_id is not one of the 23 valid function ids. - """ - if function_id not in self._VALID_FNS: - raise ValueError('Function id not recognized: %s.' % str(function_id)) - return self._history[function_id].get(key) - - def update(self, function_id, key, value): - """Adds a value to the dictionary. - - Args: - function_id: identifier for the preprocessing function used. - key: identifier for the variable stored. - value: the value to store, expected to be a tensor or nested structure - of tensors. - Raises: - ValueError: if function_id is not one of the 23 valid function ids. - """ - if function_id not in self._VALID_FNS: - raise ValueError('Function id not recognized: %s.' % str(function_id)) - self._history[function_id][key] = value - diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor_test.py deleted file mode 100644 index 588a3f90c..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/preprocessor_test.py +++ /dev/null @@ -1,2814 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.preprocessor.""" - -import numpy as np -import six - -import tensorflow as tf - -from object_detection.core import preprocessor -from object_detection.core import preprocessor_cache -from object_detection.core import standard_fields as fields - -if six.PY2: - import mock # pylint: disable=g-import-not-at-top -else: - from unittest import mock # pylint: disable=g-import-not-at-top - - -class PreprocessorTest(tf.test.TestCase): - - def createColorfulTestImage(self): - ch255 = tf.fill([1, 100, 200, 1], tf.constant(255, dtype=tf.uint8)) - ch128 = tf.fill([1, 100, 200, 1], tf.constant(128, dtype=tf.uint8)) - ch0 = tf.fill([1, 100, 200, 1], tf.constant(0, dtype=tf.uint8)) - imr = tf.concat([ch255, ch0, ch0], 3) - img = tf.concat([ch255, ch255, ch0], 3) - imb = tf.concat([ch255, ch0, ch255], 3) - imw = tf.concat([ch128, ch128, ch128], 3) - imu = tf.concat([imr, img], 2) - imd = tf.concat([imb, imw], 2) - im = tf.concat([imu, imd], 1) - return im - - def createTestImages(self): - images_r = tf.constant([[[128, 128, 128, 128], [0, 0, 128, 128], - [0, 128, 128, 128], [192, 192, 128, 128]]], - dtype=tf.uint8) - images_r = tf.expand_dims(images_r, 3) - images_g = tf.constant([[[0, 0, 128, 128], [0, 0, 128, 128], - [0, 128, 192, 192], [192, 192, 128, 192]]], - dtype=tf.uint8) - images_g = tf.expand_dims(images_g, 3) - images_b = tf.constant([[[128, 128, 192, 0], [0, 0, 128, 192], - [0, 128, 128, 0], [192, 192, 192, 128]]], - dtype=tf.uint8) - images_b = tf.expand_dims(images_b, 3) - images = tf.concat([images_r, images_g, images_b], 3) - return images - - def createEmptyTestBoxes(self): - boxes = tf.constant([[]], dtype=tf.float32) - return boxes - - def createTestBoxes(self): - boxes = tf.constant( - [[0.0, 0.25, 0.75, 1.0], [0.25, 0.5, 0.75, 1.0]], dtype=tf.float32) - return boxes - - def createTestLabelScores(self): - return tf.constant([1.0, 0.5], dtype=tf.float32) - - def createTestLabelScoresWithMissingScore(self): - return tf.constant([0.5, np.nan], dtype=tf.float32) - - def createTestMasks(self): - mask = np.array([ - [[255.0, 0.0, 0.0], - [255.0, 0.0, 0.0], - [255.0, 0.0, 0.0]], - [[255.0, 255.0, 0.0], - [255.0, 255.0, 0.0], - [255.0, 255.0, 0.0]]]) - return tf.constant(mask, dtype=tf.float32) - - def createTestKeypoints(self): - keypoints = np.array([ - [[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]], - [[0.4, 0.4], [0.5, 0.5], [0.6, 0.6]], - ]) - return tf.constant(keypoints, dtype=tf.float32) - - def createTestKeypointsInsideCrop(self): - keypoints = np.array([ - [[0.4, 0.4], [0.5, 0.5], [0.6, 0.6]], - [[0.4, 0.4], [0.5, 0.5], [0.6, 0.6]], - ]) - return tf.constant(keypoints, dtype=tf.float32) - - def createTestKeypointsOutsideCrop(self): - keypoints = np.array([ - [[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]], - [[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]], - ]) - return tf.constant(keypoints, dtype=tf.float32) - - def createKeypointFlipPermutation(self): - return np.array([0, 2, 1], dtype=np.int32) - - def createTestLabels(self): - labels = tf.constant([1, 2], dtype=tf.int32) - return labels - - def createTestBoxesOutOfImage(self): - boxes = tf.constant( - [[-0.1, 0.25, 0.75, 1], [0.25, 0.5, 0.75, 1.1]], dtype=tf.float32) - return boxes - - def createTestMultiClassScores(self): - return tf.constant([[1.0, 0.0], [0.5, 0.5]], dtype=tf.float32) - - def expectedImagesAfterNormalization(self): - images_r = tf.constant([[[0, 0, 0, 0], [-1, -1, 0, 0], - [-1, 0, 0, 0], [0.5, 0.5, 0, 0]]], - dtype=tf.float32) - images_r = tf.expand_dims(images_r, 3) - images_g = tf.constant([[[-1, -1, 0, 0], [-1, -1, 0, 0], - [-1, 0, 0.5, 0.5], [0.5, 0.5, 0, 0.5]]], - dtype=tf.float32) - images_g = tf.expand_dims(images_g, 3) - images_b = tf.constant([[[0, 0, 0.5, -1], [-1, -1, 0, 0.5], - [-1, 0, 0, -1], [0.5, 0.5, 0.5, 0]]], - dtype=tf.float32) - images_b = tf.expand_dims(images_b, 3) - images = tf.concat([images_r, images_g, images_b], 3) - return images - - def expectedMaxImageAfterColorScale(self): - images_r = tf.constant([[[0.1, 0.1, 0.1, 0.1], [-0.9, -0.9, 0.1, 0.1], - [-0.9, 0.1, 0.1, 0.1], [0.6, 0.6, 0.1, 0.1]]], - dtype=tf.float32) - images_r = tf.expand_dims(images_r, 3) - images_g = tf.constant([[[-0.9, -0.9, 0.1, 0.1], [-0.9, -0.9, 0.1, 0.1], - [-0.9, 0.1, 0.6, 0.6], [0.6, 0.6, 0.1, 0.6]]], - dtype=tf.float32) - images_g = tf.expand_dims(images_g, 3) - images_b = tf.constant([[[0.1, 0.1, 0.6, -0.9], [-0.9, -0.9, 0.1, 0.6], - [-0.9, 0.1, 0.1, -0.9], [0.6, 0.6, 0.6, 0.1]]], - dtype=tf.float32) - images_b = tf.expand_dims(images_b, 3) - images = tf.concat([images_r, images_g, images_b], 3) - return images - - def expectedMinImageAfterColorScale(self): - images_r = tf.constant([[[-0.1, -0.1, -0.1, -0.1], [-1, -1, -0.1, -0.1], - [-1, -0.1, -0.1, -0.1], [0.4, 0.4, -0.1, -0.1]]], - dtype=tf.float32) - images_r = tf.expand_dims(images_r, 3) - images_g = tf.constant([[[-1, -1, -0.1, -0.1], [-1, -1, -0.1, -0.1], - [-1, -0.1, 0.4, 0.4], [0.4, 0.4, -0.1, 0.4]]], - dtype=tf.float32) - images_g = tf.expand_dims(images_g, 3) - images_b = tf.constant([[[-0.1, -0.1, 0.4, -1], [-1, -1, -0.1, 0.4], - [-1, -0.1, -0.1, -1], [0.4, 0.4, 0.4, -0.1]]], - dtype=tf.float32) - images_b = tf.expand_dims(images_b, 3) - images = tf.concat([images_r, images_g, images_b], 3) - return images - - def expectedImagesAfterLeftRightFlip(self): - images_r = tf.constant([[[0, 0, 0, 0], [0, 0, -1, -1], - [0, 0, 0, -1], [0, 0, 0.5, 0.5]]], - dtype=tf.float32) - images_r = tf.expand_dims(images_r, 3) - images_g = tf.constant([[[0, 0, -1, -1], [0, 0, -1, -1], - [0.5, 0.5, 0, -1], [0.5, 0, 0.5, 0.5]]], - dtype=tf.float32) - images_g = tf.expand_dims(images_g, 3) - images_b = tf.constant([[[-1, 0.5, 0, 0], [0.5, 0, -1, -1], - [-1, 0, 0, -1], [0, 0.5, 0.5, 0.5]]], - dtype=tf.float32) - images_b = tf.expand_dims(images_b, 3) - images = tf.concat([images_r, images_g, images_b], 3) - return images - - def expectedImagesAfterUpDownFlip(self): - images_r = tf.constant([[[0.5, 0.5, 0, 0], [-1, 0, 0, 0], - [-1, -1, 0, 0], [0, 0, 0, 0]]], - dtype=tf.float32) - images_r = tf.expand_dims(images_r, 3) - images_g = tf.constant([[[0.5, 0.5, 0, 0.5], [-1, 0, 0.5, 0.5], - [-1, -1, 0, 0], [-1, -1, 0, 0]]], - dtype=tf.float32) - images_g = tf.expand_dims(images_g, 3) - images_b = tf.constant([[[0.5, 0.5, 0.5, 0], [-1, 0, 0, -1], - [-1, -1, 0, 0.5], [0, 0, 0.5, -1]]], - dtype=tf.float32) - images_b = tf.expand_dims(images_b, 3) - images = tf.concat([images_r, images_g, images_b], 3) - return images - - def expectedImagesAfterRot90(self): - images_r = tf.constant([[[0, 0, 0, 0], [0, 0, 0, 0], - [0, -1, 0, 0.5], [0, -1, -1, 0.5]]], - dtype=tf.float32) - images_r = tf.expand_dims(images_r, 3) - images_g = tf.constant([[[0, 0, 0.5, 0.5], [0, 0, 0.5, 0], - [-1, -1, 0, 0.5], [-1, -1, -1, 0.5]]], - dtype=tf.float32) - images_g = tf.expand_dims(images_g, 3) - images_b = tf.constant([[[-1, 0.5, -1, 0], [0.5, 0, 0, 0.5], - [0, -1, 0, 0.5], [0, -1, -1, 0.5]]], - dtype=tf.float32) - images_b = tf.expand_dims(images_b, 3) - images = tf.concat([images_r, images_g, images_b], 3) - return images - - def expectedBoxesAfterLeftRightFlip(self): - boxes = tf.constant([[0.0, 0.0, 0.75, 0.75], [0.25, 0.0, 0.75, 0.5]], - dtype=tf.float32) - return boxes - - def expectedBoxesAfterUpDownFlip(self): - boxes = tf.constant([[0.25, 0.25, 1.0, 1.0], [0.25, 0.5, 0.75, 1.0]], - dtype=tf.float32) - return boxes - - def expectedBoxesAfterRot90(self): - boxes = tf.constant( - [[0.0, 0.0, 0.75, 0.75], [0.0, 0.25, 0.5, 0.75]], dtype=tf.float32) - return boxes - - def expectedMasksAfterLeftRightFlip(self): - mask = np.array([ - [[0.0, 0.0, 255.0], - [0.0, 0.0, 255.0], - [0.0, 0.0, 255.0]], - [[0.0, 255.0, 255.0], - [0.0, 255.0, 255.0], - [0.0, 255.0, 255.0]]]) - return tf.constant(mask, dtype=tf.float32) - - def expectedMasksAfterUpDownFlip(self): - mask = np.array([ - [[255.0, 0.0, 0.0], - [255.0, 0.0, 0.0], - [255.0, 0.0, 0.0]], - [[255.0, 255.0, 0.0], - [255.0, 255.0, 0.0], - [255.0, 255.0, 0.0]]]) - return tf.constant(mask, dtype=tf.float32) - - def expectedMasksAfterRot90(self): - mask = np.array([ - [[0.0, 0.0, 0.0], - [0.0, 0.0, 0.0], - [255.0, 255.0, 255.0]], - [[0.0, 0.0, 0.0], - [255.0, 255.0, 255.0], - [255.0, 255.0, 255.0]]]) - return tf.constant(mask, dtype=tf.float32) - - def expectedLabelScoresAfterThresholding(self): - return tf.constant([1.0], dtype=tf.float32) - - def expectedBoxesAfterThresholding(self): - return tf.constant([[0.0, 0.25, 0.75, 1.0]], dtype=tf.float32) - - def expectedLabelsAfterThresholding(self): - return tf.constant([1], dtype=tf.float32) - - def expectedMultiClassScoresAfterThresholding(self): - return tf.constant([[1.0, 0.0]], dtype=tf.float32) - - def expectedMasksAfterThresholding(self): - mask = np.array([ - [[255.0, 0.0, 0.0], - [255.0, 0.0, 0.0], - [255.0, 0.0, 0.0]]]) - return tf.constant(mask, dtype=tf.float32) - - def expectedKeypointsAfterThresholding(self): - keypoints = np.array([ - [[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]] - ]) - return tf.constant(keypoints, dtype=tf.float32) - - def expectedLabelScoresAfterThresholdingWithMissingScore(self): - return tf.constant([np.nan], dtype=tf.float32) - - def expectedBoxesAfterThresholdingWithMissingScore(self): - return tf.constant([[0.25, 0.5, 0.75, 1]], dtype=tf.float32) - - def expectedLabelsAfterThresholdingWithMissingScore(self): - return tf.constant([2], dtype=tf.float32) - - def testRgbToGrayscale(self): - images = self.createTestImages() - grayscale_images = preprocessor._rgb_to_grayscale(images) - expected_images = tf.image.rgb_to_grayscale(images) - with self.test_session() as sess: - (grayscale_images, expected_images) = sess.run( - [grayscale_images, expected_images]) - self.assertAllEqual(expected_images, grayscale_images) - - def testNormalizeImage(self): - preprocess_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 256, - 'target_minval': -1, - 'target_maxval': 1 - })] - images = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images = tensor_dict[fields.InputDataFields.image] - images_expected = self.expectedImagesAfterNormalization() - - with self.test_session() as sess: - (images_, images_expected_) = sess.run( - [images, images_expected]) - images_shape_ = images_.shape - images_expected_shape_ = images_expected_.shape - expected_shape = [1, 4, 4, 3] - self.assertAllEqual(images_expected_shape_, images_shape_) - self.assertAllEqual(images_shape_, expected_shape) - self.assertAllClose(images_, images_expected_) - - def testRetainBoxesAboveThreshold(self): - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - (retained_boxes, retained_labels, - retained_label_scores) = preprocessor.retain_boxes_above_threshold( - boxes, labels, label_scores, threshold=0.6) - with self.test_session() as sess: - (retained_boxes_, retained_labels_, retained_label_scores_, - expected_retained_boxes_, expected_retained_labels_, - expected_retained_label_scores_) = sess.run([ - retained_boxes, retained_labels, retained_label_scores, - self.expectedBoxesAfterThresholding(), - self.expectedLabelsAfterThresholding(), - self.expectedLabelScoresAfterThresholding()]) - self.assertAllClose( - retained_boxes_, expected_retained_boxes_) - self.assertAllClose( - retained_labels_, expected_retained_labels_) - self.assertAllClose( - retained_label_scores_, expected_retained_label_scores_) - - def testRetainBoxesAboveThresholdWithMultiClassScores(self): - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - multiclass_scores = self.createTestMultiClassScores() - (_, _, _, - retained_multiclass_scores) = preprocessor.retain_boxes_above_threshold( - boxes, - labels, - label_scores, - multiclass_scores=multiclass_scores, - threshold=0.6) - with self.test_session() as sess: - (retained_multiclass_scores_, - expected_retained_multiclass_scores_) = sess.run([ - retained_multiclass_scores, - self.expectedMultiClassScoresAfterThresholding() - ]) - - self.assertAllClose(retained_multiclass_scores_, - expected_retained_multiclass_scores_) - - def testRetainBoxesAboveThresholdWithMasks(self): - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - masks = self.createTestMasks() - _, _, _, retained_masks = preprocessor.retain_boxes_above_threshold( - boxes, labels, label_scores, masks, threshold=0.6) - with self.test_session() as sess: - retained_masks_, expected_retained_masks_ = sess.run([ - retained_masks, self.expectedMasksAfterThresholding()]) - - self.assertAllClose( - retained_masks_, expected_retained_masks_) - - def testRetainBoxesAboveThresholdWithKeypoints(self): - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - keypoints = self.createTestKeypoints() - (_, _, _, retained_keypoints) = preprocessor.retain_boxes_above_threshold( - boxes, labels, label_scores, keypoints=keypoints, threshold=0.6) - with self.test_session() as sess: - (retained_keypoints_, - expected_retained_keypoints_) = sess.run([ - retained_keypoints, - self.expectedKeypointsAfterThresholding()]) - - self.assertAllClose( - retained_keypoints_, expected_retained_keypoints_) - - def testRetainBoxesAboveThresholdWithMissingScore(self): - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScoresWithMissingScore() - (retained_boxes, retained_labels, - retained_label_scores) = preprocessor.retain_boxes_above_threshold( - boxes, labels, label_scores, threshold=0.6) - with self.test_session() as sess: - (retained_boxes_, retained_labels_, retained_label_scores_, - expected_retained_boxes_, expected_retained_labels_, - expected_retained_label_scores_) = sess.run([ - retained_boxes, retained_labels, retained_label_scores, - self.expectedBoxesAfterThresholdingWithMissingScore(), - self.expectedLabelsAfterThresholdingWithMissingScore(), - self.expectedLabelScoresAfterThresholdingWithMissingScore()]) - self.assertAllClose( - retained_boxes_, expected_retained_boxes_) - self.assertAllClose( - retained_labels_, expected_retained_labels_) - self.assertAllClose( - retained_label_scores_, expected_retained_label_scores_) - - def testFlipBoxesLeftRight(self): - boxes = self.createTestBoxes() - flipped_boxes = preprocessor._flip_boxes_left_right(boxes) - expected_boxes = self.expectedBoxesAfterLeftRightFlip() - with self.test_session() as sess: - flipped_boxes, expected_boxes = sess.run([flipped_boxes, expected_boxes]) - self.assertAllEqual(flipped_boxes.flatten(), expected_boxes.flatten()) - - def testFlipBoxesUpDown(self): - boxes = self.createTestBoxes() - flipped_boxes = preprocessor._flip_boxes_up_down(boxes) - expected_boxes = self.expectedBoxesAfterUpDownFlip() - with self.test_session() as sess: - flipped_boxes, expected_boxes = sess.run([flipped_boxes, expected_boxes]) - self.assertAllEqual(flipped_boxes.flatten(), expected_boxes.flatten()) - - def testRot90Boxes(self): - boxes = self.createTestBoxes() - rotated_boxes = preprocessor._rot90_boxes(boxes) - expected_boxes = self.expectedBoxesAfterRot90() - with self.test_session() as sess: - rotated_boxes, expected_boxes = sess.run([rotated_boxes, expected_boxes]) - self.assertAllEqual(rotated_boxes.flatten(), expected_boxes.flatten()) - - def testFlipMasksLeftRight(self): - test_mask = self.createTestMasks() - flipped_mask = preprocessor._flip_masks_left_right(test_mask) - expected_mask = self.expectedMasksAfterLeftRightFlip() - with self.test_session() as sess: - flipped_mask, expected_mask = sess.run([flipped_mask, expected_mask]) - self.assertAllEqual(flipped_mask.flatten(), expected_mask.flatten()) - - def testFlipMasksUpDown(self): - test_mask = self.createTestMasks() - flipped_mask = preprocessor._flip_masks_up_down(test_mask) - expected_mask = self.expectedMasksAfterUpDownFlip() - with self.test_session() as sess: - flipped_mask, expected_mask = sess.run([flipped_mask, expected_mask]) - self.assertAllEqual(flipped_mask.flatten(), expected_mask.flatten()) - - def testRot90Masks(self): - test_mask = self.createTestMasks() - rotated_mask = preprocessor._rot90_masks(test_mask) - expected_mask = self.expectedMasksAfterRot90() - with self.test_session() as sess: - rotated_mask, expected_mask = sess.run([rotated_mask, expected_mask]) - self.assertAllEqual(rotated_mask.flatten(), expected_mask.flatten()) - - def _testPreprocessorCache(self, - preprocess_options, - test_boxes=False, - test_masks=False, - test_keypoints=False, - num_runs=4): - cache = preprocessor_cache.PreprocessorCache() - images = self.createTestImages() - boxes = self.createTestBoxes() - classes = self.createTestLabels() - masks = self.createTestMasks() - keypoints = self.createTestKeypoints() - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_instance_masks=test_masks, include_keypoints=test_keypoints) - out = [] - for i in range(num_runs): - tensor_dict = { - fields.InputDataFields.image: images, - } - num_outputs = 1 - if test_boxes: - tensor_dict[fields.InputDataFields.groundtruth_boxes] = boxes - tensor_dict[fields.InputDataFields.groundtruth_classes] = classes - num_outputs += 1 - if test_masks: - tensor_dict[fields.InputDataFields.groundtruth_instance_masks] = masks - num_outputs += 1 - if test_keypoints: - tensor_dict[fields.InputDataFields.groundtruth_keypoints] = keypoints - num_outputs += 1 - out.append(preprocessor.preprocess( - tensor_dict, preprocess_options, preprocessor_arg_map, cache)) - - with self.test_session() as sess: - to_run = [] - for i in range(num_runs): - to_run.append(out[i][fields.InputDataFields.image]) - if test_boxes: - to_run.append(out[i][fields.InputDataFields.groundtruth_boxes]) - if test_masks: - to_run.append( - out[i][fields.InputDataFields.groundtruth_instance_masks]) - if test_keypoints: - to_run.append(out[i][fields.InputDataFields.groundtruth_keypoints]) - - out_array = sess.run(to_run) - for i in range(num_outputs, len(out_array)): - self.assertAllClose(out_array[i], out_array[i - num_outputs]) - - def testRandomHorizontalFlip(self): - preprocess_options = [(preprocessor.random_horizontal_flip, {})] - images = self.expectedImagesAfterNormalization() - boxes = self.createTestBoxes() - tensor_dict = {fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes} - images_expected1 = self.expectedImagesAfterLeftRightFlip() - boxes_expected1 = self.expectedBoxesAfterLeftRightFlip() - images_expected2 = images - boxes_expected2 = boxes - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images = tensor_dict[fields.InputDataFields.image] - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - - boxes_diff1 = tf.squared_difference(boxes, boxes_expected1) - boxes_diff2 = tf.squared_difference(boxes, boxes_expected2) - boxes_diff = tf.multiply(boxes_diff1, boxes_diff2) - boxes_diff_expected = tf.zeros_like(boxes_diff) - - images_diff1 = tf.squared_difference(images, images_expected1) - images_diff2 = tf.squared_difference(images, images_expected2) - images_diff = tf.multiply(images_diff1, images_diff2) - images_diff_expected = tf.zeros_like(images_diff) - - with self.test_session() as sess: - (images_diff_, images_diff_expected_, boxes_diff_, - boxes_diff_expected_) = sess.run([images_diff, images_diff_expected, - boxes_diff, boxes_diff_expected]) - self.assertAllClose(boxes_diff_, boxes_diff_expected_) - self.assertAllClose(images_diff_, images_diff_expected_) - - def testRandomHorizontalFlipWithEmptyBoxes(self): - preprocess_options = [(preprocessor.random_horizontal_flip, {})] - images = self.expectedImagesAfterNormalization() - boxes = self.createEmptyTestBoxes() - tensor_dict = {fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes} - images_expected1 = self.expectedImagesAfterLeftRightFlip() - boxes_expected = self.createEmptyTestBoxes() - images_expected2 = images - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images = tensor_dict[fields.InputDataFields.image] - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - - images_diff1 = tf.squared_difference(images, images_expected1) - images_diff2 = tf.squared_difference(images, images_expected2) - images_diff = tf.multiply(images_diff1, images_diff2) - images_diff_expected = tf.zeros_like(images_diff) - - with self.test_session() as sess: - (images_diff_, images_diff_expected_, boxes_, - boxes_expected_) = sess.run([images_diff, images_diff_expected, boxes, - boxes_expected]) - self.assertAllClose(boxes_, boxes_expected_) - self.assertAllClose(images_diff_, images_diff_expected_) - - def testRandomHorizontalFlipWithCache(self): - keypoint_flip_permutation = self.createKeypointFlipPermutation() - preprocess_options = [ - (preprocessor.random_horizontal_flip, - {'keypoint_flip_permutation': keypoint_flip_permutation})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=True, - test_keypoints=True) - - def testRunRandomHorizontalFlipWithMaskAndKeypoints(self): - preprocess_options = [(preprocessor.random_horizontal_flip, {})] - image_height = 3 - image_width = 3 - images = tf.random_uniform([1, image_height, image_width, 3]) - boxes = self.createTestBoxes() - masks = self.createTestMasks() - keypoints = self.createTestKeypoints() - keypoint_flip_permutation = self.createKeypointFlipPermutation() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_instance_masks: masks, - fields.InputDataFields.groundtruth_keypoints: keypoints - } - preprocess_options = [ - (preprocessor.random_horizontal_flip, - {'keypoint_flip_permutation': keypoint_flip_permutation})] - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_instance_masks=True, include_keypoints=True) - tensor_dict = preprocessor.preprocess( - tensor_dict, preprocess_options, func_arg_map=preprocessor_arg_map) - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - masks = tensor_dict[fields.InputDataFields.groundtruth_instance_masks] - keypoints = tensor_dict[fields.InputDataFields.groundtruth_keypoints] - with self.test_session() as sess: - boxes, masks, keypoints = sess.run([boxes, masks, keypoints]) - self.assertTrue(boxes is not None) - self.assertTrue(masks is not None) - self.assertTrue(keypoints is not None) - - def testRandomVerticalFlip(self): - preprocess_options = [(preprocessor.random_vertical_flip, {})] - images = self.expectedImagesAfterNormalization() - boxes = self.createTestBoxes() - tensor_dict = {fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes} - images_expected1 = self.expectedImagesAfterUpDownFlip() - boxes_expected1 = self.expectedBoxesAfterUpDownFlip() - images_expected2 = images - boxes_expected2 = boxes - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images = tensor_dict[fields.InputDataFields.image] - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - - boxes_diff1 = tf.squared_difference(boxes, boxes_expected1) - boxes_diff2 = tf.squared_difference(boxes, boxes_expected2) - boxes_diff = tf.multiply(boxes_diff1, boxes_diff2) - boxes_diff_expected = tf.zeros_like(boxes_diff) - - images_diff1 = tf.squared_difference(images, images_expected1) - images_diff2 = tf.squared_difference(images, images_expected2) - images_diff = tf.multiply(images_diff1, images_diff2) - images_diff_expected = tf.zeros_like(images_diff) - - with self.test_session() as sess: - (images_diff_, images_diff_expected_, boxes_diff_, - boxes_diff_expected_) = sess.run([images_diff, images_diff_expected, - boxes_diff, boxes_diff_expected]) - self.assertAllClose(boxes_diff_, boxes_diff_expected_) - self.assertAllClose(images_diff_, images_diff_expected_) - - def testRandomVerticalFlipWithEmptyBoxes(self): - preprocess_options = [(preprocessor.random_vertical_flip, {})] - images = self.expectedImagesAfterNormalization() - boxes = self.createEmptyTestBoxes() - tensor_dict = {fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes} - images_expected1 = self.expectedImagesAfterUpDownFlip() - boxes_expected = self.createEmptyTestBoxes() - images_expected2 = images - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images = tensor_dict[fields.InputDataFields.image] - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - - images_diff1 = tf.squared_difference(images, images_expected1) - images_diff2 = tf.squared_difference(images, images_expected2) - images_diff = tf.multiply(images_diff1, images_diff2) - images_diff_expected = tf.zeros_like(images_diff) - - with self.test_session() as sess: - (images_diff_, images_diff_expected_, boxes_, - boxes_expected_) = sess.run([images_diff, images_diff_expected, boxes, - boxes_expected]) - self.assertAllClose(boxes_, boxes_expected_) - self.assertAllClose(images_diff_, images_diff_expected_) - - def testRandomVerticalFlipWithCache(self): - keypoint_flip_permutation = self.createKeypointFlipPermutation() - preprocess_options = [ - (preprocessor.random_vertical_flip, - {'keypoint_flip_permutation': keypoint_flip_permutation})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=True, - test_keypoints=True) - - def testRunRandomVerticalFlipWithMaskAndKeypoints(self): - preprocess_options = [(preprocessor.random_vertical_flip, {})] - image_height = 3 - image_width = 3 - images = tf.random_uniform([1, image_height, image_width, 3]) - boxes = self.createTestBoxes() - masks = self.createTestMasks() - keypoints = self.createTestKeypoints() - keypoint_flip_permutation = self.createKeypointFlipPermutation() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_instance_masks: masks, - fields.InputDataFields.groundtruth_keypoints: keypoints - } - preprocess_options = [ - (preprocessor.random_vertical_flip, - {'keypoint_flip_permutation': keypoint_flip_permutation})] - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_instance_masks=True, include_keypoints=True) - tensor_dict = preprocessor.preprocess( - tensor_dict, preprocess_options, func_arg_map=preprocessor_arg_map) - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - masks = tensor_dict[fields.InputDataFields.groundtruth_instance_masks] - keypoints = tensor_dict[fields.InputDataFields.groundtruth_keypoints] - with self.test_session() as sess: - boxes, masks, keypoints = sess.run([boxes, masks, keypoints]) - self.assertTrue(boxes is not None) - self.assertTrue(masks is not None) - self.assertTrue(keypoints is not None) - - def testRandomRotation90(self): - preprocess_options = [(preprocessor.random_rotation90, {})] - images = self.expectedImagesAfterNormalization() - boxes = self.createTestBoxes() - tensor_dict = {fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes} - images_expected1 = self.expectedImagesAfterRot90() - boxes_expected1 = self.expectedBoxesAfterRot90() - images_expected2 = images - boxes_expected2 = boxes - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images = tensor_dict[fields.InputDataFields.image] - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - - boxes_diff1 = tf.squared_difference(boxes, boxes_expected1) - boxes_diff2 = tf.squared_difference(boxes, boxes_expected2) - boxes_diff = tf.multiply(boxes_diff1, boxes_diff2) - boxes_diff_expected = tf.zeros_like(boxes_diff) - - images_diff1 = tf.squared_difference(images, images_expected1) - images_diff2 = tf.squared_difference(images, images_expected2) - images_diff = tf.multiply(images_diff1, images_diff2) - images_diff_expected = tf.zeros_like(images_diff) - - with self.test_session() as sess: - (images_diff_, images_diff_expected_, boxes_diff_, - boxes_diff_expected_) = sess.run([images_diff, images_diff_expected, - boxes_diff, boxes_diff_expected]) - self.assertAllClose(boxes_diff_, boxes_diff_expected_) - self.assertAllClose(images_diff_, images_diff_expected_) - - def testRandomRotation90WithEmptyBoxes(self): - preprocess_options = [(preprocessor.random_rotation90, {})] - images = self.expectedImagesAfterNormalization() - boxes = self.createEmptyTestBoxes() - tensor_dict = {fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes} - images_expected1 = self.expectedImagesAfterRot90() - boxes_expected = self.createEmptyTestBoxes() - images_expected2 = images - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images = tensor_dict[fields.InputDataFields.image] - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - - images_diff1 = tf.squared_difference(images, images_expected1) - images_diff2 = tf.squared_difference(images, images_expected2) - images_diff = tf.multiply(images_diff1, images_diff2) - images_diff_expected = tf.zeros_like(images_diff) - - with self.test_session() as sess: - (images_diff_, images_diff_expected_, boxes_, - boxes_expected_) = sess.run([images_diff, images_diff_expected, boxes, - boxes_expected]) - self.assertAllClose(boxes_, boxes_expected_) - self.assertAllClose(images_diff_, images_diff_expected_) - - def testRandomRotation90WithCache(self): - preprocess_options = [(preprocessor.random_rotation90, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=True, - test_keypoints=True) - - def testRunRandomRotation90WithMaskAndKeypoints(self): - preprocess_options = [(preprocessor.random_rotation90, {})] - image_height = 3 - image_width = 3 - images = tf.random_uniform([1, image_height, image_width, 3]) - boxes = self.createTestBoxes() - masks = self.createTestMasks() - keypoints = self.createTestKeypoints() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_instance_masks: masks, - fields.InputDataFields.groundtruth_keypoints: keypoints - } - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_instance_masks=True, include_keypoints=True) - tensor_dict = preprocessor.preprocess( - tensor_dict, preprocess_options, func_arg_map=preprocessor_arg_map) - boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - masks = tensor_dict[fields.InputDataFields.groundtruth_instance_masks] - keypoints = tensor_dict[fields.InputDataFields.groundtruth_keypoints] - with self.test_session() as sess: - boxes, masks, keypoints = sess.run([boxes, masks, keypoints]) - self.assertTrue(boxes is not None) - self.assertTrue(masks is not None) - self.assertTrue(keypoints is not None) - - def testRandomPixelValueScale(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_pixel_value_scale, {})) - images = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images_min = tf.to_float(images) * 0.9 / 255.0 - images_max = tf.to_float(images) * 1.1 / 255.0 - images = tensor_dict[fields.InputDataFields.image] - values_greater = tf.greater_equal(images, images_min) - values_less = tf.less_equal(images, images_max) - values_true = tf.fill([1, 4, 4, 3], True) - with self.test_session() as sess: - (values_greater_, values_less_, values_true_) = sess.run( - [values_greater, values_less, values_true]) - self.assertAllClose(values_greater_, values_true_) - self.assertAllClose(values_less_, values_true_) - - def testRandomPixelValueScaleWithCache(self): - preprocess_options = [] - preprocess_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocess_options.append((preprocessor.random_pixel_value_scale, {})) - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=False, - test_keypoints=False) - - def testRandomImageScale(self): - preprocess_options = [(preprocessor.random_image_scale, {})] - images_original = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images_original} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images_scaled = tensor_dict[fields.InputDataFields.image] - images_original_shape = tf.shape(images_original) - images_scaled_shape = tf.shape(images_scaled) - with self.test_session() as sess: - (images_original_shape_, images_scaled_shape_) = sess.run( - [images_original_shape, images_scaled_shape]) - self.assertTrue( - images_original_shape_[1] * 0.5 <= images_scaled_shape_[1]) - self.assertTrue( - images_original_shape_[1] * 2.0 >= images_scaled_shape_[1]) - self.assertTrue( - images_original_shape_[2] * 0.5 <= images_scaled_shape_[2]) - self.assertTrue( - images_original_shape_[2] * 2.0 >= images_scaled_shape_[2]) - - def testRandomImageScaleWithCache(self): - preprocess_options = [(preprocessor.random_image_scale, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=False, - test_masks=False, - test_keypoints=False) - - def testRandomRGBtoGray(self): - preprocess_options = [(preprocessor.random_rgb_to_gray, {})] - images_original = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images_original} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocess_options) - images_gray = tensor_dict[fields.InputDataFields.image] - images_gray_r, images_gray_g, images_gray_b = tf.split( - value=images_gray, num_or_size_splits=3, axis=3) - images_r, images_g, images_b = tf.split( - value=images_original, num_or_size_splits=3, axis=3) - images_r_diff1 = tf.squared_difference(tf.to_float(images_r), - tf.to_float(images_gray_r)) - images_r_diff2 = tf.squared_difference(tf.to_float(images_gray_r), - tf.to_float(images_gray_g)) - images_r_diff = tf.multiply(images_r_diff1, images_r_diff2) - images_g_diff1 = tf.squared_difference(tf.to_float(images_g), - tf.to_float(images_gray_g)) - images_g_diff2 = tf.squared_difference(tf.to_float(images_gray_g), - tf.to_float(images_gray_b)) - images_g_diff = tf.multiply(images_g_diff1, images_g_diff2) - images_b_diff1 = tf.squared_difference(tf.to_float(images_b), - tf.to_float(images_gray_b)) - images_b_diff2 = tf.squared_difference(tf.to_float(images_gray_b), - tf.to_float(images_gray_r)) - images_b_diff = tf.multiply(images_b_diff1, images_b_diff2) - image_zero1 = tf.constant(0, dtype=tf.float32, shape=[1, 4, 4, 1]) - with self.test_session() as sess: - (images_r_diff_, images_g_diff_, images_b_diff_, image_zero1_) = sess.run( - [images_r_diff, images_g_diff, images_b_diff, image_zero1]) - self.assertAllClose(images_r_diff_, image_zero1_) - self.assertAllClose(images_g_diff_, image_zero1_) - self.assertAllClose(images_b_diff_, image_zero1_) - - def testRandomRGBtoGrayWithCache(self): - preprocess_options = [( - preprocessor.random_rgb_to_gray, {'probability': 0.5})] - self._testPreprocessorCache(preprocess_options, - test_boxes=False, - test_masks=False, - test_keypoints=False) - - def testRandomAdjustBrightness(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_adjust_brightness, {})) - images_original = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images_original} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images_bright = tensor_dict[fields.InputDataFields.image] - image_original_shape = tf.shape(images_original) - image_bright_shape = tf.shape(images_bright) - with self.test_session() as sess: - (image_original_shape_, image_bright_shape_) = sess.run( - [image_original_shape, image_bright_shape]) - self.assertAllEqual(image_original_shape_, image_bright_shape_) - - def testRandomAdjustBrightnessWithCache(self): - preprocess_options = [] - preprocess_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocess_options.append((preprocessor.random_adjust_brightness, {})) - self._testPreprocessorCache(preprocess_options, - test_boxes=False, - test_masks=False, - test_keypoints=False) - - def testRandomAdjustContrast(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_adjust_contrast, {})) - images_original = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images_original} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images_contrast = tensor_dict[fields.InputDataFields.image] - image_original_shape = tf.shape(images_original) - image_contrast_shape = tf.shape(images_contrast) - with self.test_session() as sess: - (image_original_shape_, image_contrast_shape_) = sess.run( - [image_original_shape, image_contrast_shape]) - self.assertAllEqual(image_original_shape_, image_contrast_shape_) - - def testRandomAdjustContrastWithCache(self): - preprocess_options = [] - preprocess_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocess_options.append((preprocessor.random_adjust_contrast, {})) - self._testPreprocessorCache(preprocess_options, - test_boxes=False, - test_masks=False, - test_keypoints=False) - - def testRandomAdjustHue(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_adjust_hue, {})) - images_original = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images_original} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images_hue = tensor_dict[fields.InputDataFields.image] - image_original_shape = tf.shape(images_original) - image_hue_shape = tf.shape(images_hue) - with self.test_session() as sess: - (image_original_shape_, image_hue_shape_) = sess.run( - [image_original_shape, image_hue_shape]) - self.assertAllEqual(image_original_shape_, image_hue_shape_) - - def testRandomAdjustHueWithCache(self): - preprocess_options = [] - preprocess_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocess_options.append((preprocessor.random_adjust_hue, {})) - self._testPreprocessorCache(preprocess_options, - test_boxes=False, - test_masks=False, - test_keypoints=False) - - def testRandomDistortColor(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_distort_color, {})) - images_original = self.createTestImages() - images_original_shape = tf.shape(images_original) - tensor_dict = {fields.InputDataFields.image: images_original} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images_distorted_color = tensor_dict[fields.InputDataFields.image] - images_distorted_color_shape = tf.shape(images_distorted_color) - with self.test_session() as sess: - (images_original_shape_, images_distorted_color_shape_) = sess.run( - [images_original_shape, images_distorted_color_shape]) - self.assertAllEqual(images_original_shape_, images_distorted_color_shape_) - - def testRandomDistortColorWithCache(self): - preprocess_options = [] - preprocess_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocess_options.append((preprocessor.random_distort_color, {})) - self._testPreprocessorCache(preprocess_options, - test_boxes=False, - test_masks=False, - test_keypoints=False) - - def testRandomJitterBoxes(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.random_jitter_boxes, {})) - boxes = self.createTestBoxes() - boxes_shape = tf.shape(boxes) - tensor_dict = {fields.InputDataFields.groundtruth_boxes: boxes} - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - distorted_boxes = tensor_dict[fields.InputDataFields.groundtruth_boxes] - distorted_boxes_shape = tf.shape(distorted_boxes) - - with self.test_session() as sess: - (boxes_shape_, distorted_boxes_shape_) = sess.run( - [boxes_shape, distorted_boxes_shape]) - self.assertAllEqual(boxes_shape_, distorted_boxes_shape_) - - def testRandomCropImage(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_crop_image, {})) - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - distorted_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - boxes_rank = tf.rank(boxes) - distorted_boxes_rank = tf.rank(distorted_boxes) - images_rank = tf.rank(images) - distorted_images_rank = tf.rank(distorted_images) - self.assertEqual(3, distorted_images.get_shape()[3]) - - with self.test_session() as sess: - (boxes_rank_, distorted_boxes_rank_, images_rank_, - distorted_images_rank_) = sess.run([ - boxes_rank, distorted_boxes_rank, images_rank, distorted_images_rank - ]) - self.assertAllEqual(boxes_rank_, distorted_boxes_rank_) - self.assertAllEqual(images_rank_, distorted_images_rank_) - - def testRandomCropImageWithCache(self): - preprocess_options = [(preprocessor.random_rgb_to_gray, - {'probability': 0.5}), - (preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1, - }), - (preprocessor.random_crop_image, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=False, - test_keypoints=False) - - def testRandomCropImageGrayscale(self): - preprocessing_options = [(preprocessor.rgb_to_gray, {}), - (preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1, - }), - (preprocessor.random_crop_image, {})] - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options) - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - boxes_rank = tf.rank(boxes) - distorted_boxes_rank = tf.rank(distorted_boxes) - images_rank = tf.rank(images) - distorted_images_rank = tf.rank(distorted_images) - self.assertEqual(1, distorted_images.get_shape()[3]) - - with self.test_session() as sess: - session_results = sess.run([ - boxes_rank, distorted_boxes_rank, images_rank, distorted_images_rank - ]) - (boxes_rank_, distorted_boxes_rank_, images_rank_, - distorted_images_rank_) = session_results - self.assertAllEqual(boxes_rank_, distorted_boxes_rank_) - self.assertAllEqual(images_rank_, distorted_images_rank_) - - def testRandomCropImageWithBoxOutOfImage(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_crop_image, {})) - images = self.createTestImages() - boxes = self.createTestBoxesOutOfImage() - labels = self.createTestLabels() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - distorted_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - boxes_rank = tf.rank(boxes) - distorted_boxes_rank = tf.rank(distorted_boxes) - images_rank = tf.rank(images) - distorted_images_rank = tf.rank(distorted_images) - - with self.test_session() as sess: - (boxes_rank_, distorted_boxes_rank_, images_rank_, - distorted_images_rank_) = sess.run( - [boxes_rank, distorted_boxes_rank, images_rank, - distorted_images_rank]) - self.assertAllEqual(boxes_rank_, distorted_boxes_rank_) - self.assertAllEqual(images_rank_, distorted_images_rank_) - - def testRandomCropImageWithRandomCoefOne(self): - preprocessing_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })] - - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_label_scores: label_scores - } - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images = tensor_dict[fields.InputDataFields.image] - - preprocessing_options = [(preprocessor.random_crop_image, { - 'random_coef': 1.0 - })] - distorted_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - distorted_label_scores = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_label_scores] - boxes_shape = tf.shape(boxes) - distorted_boxes_shape = tf.shape(distorted_boxes) - images_shape = tf.shape(images) - distorted_images_shape = tf.shape(distorted_images) - - with self.test_session() as sess: - (boxes_shape_, distorted_boxes_shape_, images_shape_, - distorted_images_shape_, images_, distorted_images_, - boxes_, distorted_boxes_, labels_, distorted_labels_, - label_scores_, distorted_label_scores_) = sess.run( - [boxes_shape, distorted_boxes_shape, images_shape, - distorted_images_shape, images, distorted_images, - boxes, distorted_boxes, labels, distorted_labels, - label_scores, distorted_label_scores]) - self.assertAllEqual(boxes_shape_, distorted_boxes_shape_) - self.assertAllEqual(images_shape_, distorted_images_shape_) - self.assertAllClose(images_, distorted_images_) - self.assertAllClose(boxes_, distorted_boxes_) - self.assertAllEqual(labels_, distorted_labels_) - self.assertAllEqual(label_scores_, distorted_label_scores_) - - def testRandomCropWithMockSampleDistortedBoundingBox(self): - preprocessing_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })] - - images = self.createColorfulTestImage() - boxes = tf.constant([[0.1, 0.1, 0.8, 0.3], - [0.2, 0.4, 0.75, 0.75], - [0.3, 0.1, 0.4, 0.7]], dtype=tf.float32) - labels = tf.constant([1, 7, 11], dtype=tf.int32) - - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images = tensor_dict[fields.InputDataFields.image] - - preprocessing_options = [(preprocessor.random_crop_image, {})] - with mock.patch.object( - tf.image, - 'sample_distorted_bounding_box') as mock_sample_distorted_bounding_box: - mock_sample_distorted_bounding_box.return_value = (tf.constant( - [6, 143, 0], dtype=tf.int32), tf.constant( - [190, 237, -1], dtype=tf.int32), tf.constant( - [[[0.03, 0.3575, 0.98, 0.95]]], dtype=tf.float32)) - - distorted_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - expected_boxes = tf.constant([[0.178947, 0.07173, 0.75789469, 0.66244733], - [0.28421, 0.0, 0.38947365, 0.57805908]], - dtype=tf.float32) - expected_labels = tf.constant([7, 11], dtype=tf.int32) - - with self.test_session() as sess: - (distorted_boxes_, distorted_labels_, - expected_boxes_, expected_labels_) = sess.run( - [distorted_boxes, distorted_labels, - expected_boxes, expected_labels]) - self.assertAllClose(distorted_boxes_, expected_boxes_) - self.assertAllEqual(distorted_labels_, expected_labels_) - - def testRandomCropImageWithMultiClassScores(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_crop_image, {})) - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - multiclass_scores = self.createTestMultiClassScores() - - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.multiclass_scores: multiclass_scores - } - distorted_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_multiclass_scores = distorted_tensor_dict[ - fields.InputDataFields.multiclass_scores] - boxes_rank = tf.rank(boxes) - distorted_boxes_rank = tf.rank(distorted_boxes) - images_rank = tf.rank(images) - distorted_images_rank = tf.rank(distorted_images) - multiclass_scores_rank = tf.rank(multiclass_scores) - distorted_multiclass_scores_rank = tf.rank(distorted_multiclass_scores) - - with self.test_session() as sess: - (boxes_rank_, distorted_boxes_, distorted_boxes_rank_, images_rank_, - distorted_images_rank_, multiclass_scores_rank_, - distorted_multiclass_scores_rank_, - distorted_multiclass_scores_) = sess.run([ - boxes_rank, distorted_boxes, distorted_boxes_rank, images_rank, - distorted_images_rank, multiclass_scores_rank, - distorted_multiclass_scores_rank, distorted_multiclass_scores - ]) - self.assertAllEqual(boxes_rank_, distorted_boxes_rank_) - self.assertAllEqual(images_rank_, distorted_images_rank_) - self.assertAllEqual(multiclass_scores_rank_, - distorted_multiclass_scores_rank_) - self.assertAllEqual(distorted_boxes_.shape[0], - distorted_multiclass_scores_.shape[0]) - - def testStrictRandomCropImageWithLabelScores(self): - image = self.createColorfulTestImage()[0] - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - with mock.patch.object( - tf.image, - 'sample_distorted_bounding_box' - ) as mock_sample_distorted_bounding_box: - mock_sample_distorted_bounding_box.return_value = ( - tf.constant([6, 143, 0], dtype=tf.int32), - tf.constant([190, 237, -1], dtype=tf.int32), - tf.constant([[[0.03, 0.3575, 0.98, 0.95]]], dtype=tf.float32)) - new_image, new_boxes, new_labels, new_label_scores = ( - preprocessor._strict_random_crop_image( - image, boxes, labels, label_scores)) - with self.test_session() as sess: - new_image, new_boxes, new_labels, new_label_scores = ( - sess.run( - [new_image, new_boxes, new_labels, new_label_scores]) - ) - - expected_boxes = np.array( - [[0.0, 0.0, 0.75789469, 1.0], - [0.23157893, 0.24050637, 0.75789469, 1.0]], dtype=np.float32) - self.assertAllEqual(new_image.shape, [190, 237, 3]) - self.assertAllEqual(new_label_scores, [1.0, 0.5]) - self.assertAllClose( - new_boxes.flatten(), expected_boxes.flatten()) - - def testStrictRandomCropImageWithMasks(self): - image = self.createColorfulTestImage()[0] - boxes = self.createTestBoxes() - labels = self.createTestLabels() - masks = tf.random_uniform([2, 200, 400], dtype=tf.float32) - with mock.patch.object( - tf.image, - 'sample_distorted_bounding_box' - ) as mock_sample_distorted_bounding_box: - mock_sample_distorted_bounding_box.return_value = ( - tf.constant([6, 143, 0], dtype=tf.int32), - tf.constant([190, 237, -1], dtype=tf.int32), - tf.constant([[[0.03, 0.3575, 0.98, 0.95]]], dtype=tf.float32)) - new_image, new_boxes, new_labels, new_masks = ( - preprocessor._strict_random_crop_image( - image, boxes, labels, masks=masks)) - with self.test_session() as sess: - new_image, new_boxes, new_labels, new_masks = sess.run( - [new_image, new_boxes, new_labels, new_masks]) - expected_boxes = np.array( - [[0.0, 0.0, 0.75789469, 1.0], - [0.23157893, 0.24050637, 0.75789469, 1.0]], dtype=np.float32) - self.assertAllEqual(new_image.shape, [190, 237, 3]) - self.assertAllEqual(new_masks.shape, [2, 190, 237]) - self.assertAllClose( - new_boxes.flatten(), expected_boxes.flatten()) - - def testStrictRandomCropImageWithKeypoints(self): - image = self.createColorfulTestImage()[0] - boxes = self.createTestBoxes() - labels = self.createTestLabels() - keypoints = self.createTestKeypoints() - with mock.patch.object( - tf.image, - 'sample_distorted_bounding_box' - ) as mock_sample_distorted_bounding_box: - mock_sample_distorted_bounding_box.return_value = ( - tf.constant([6, 143, 0], dtype=tf.int32), - tf.constant([190, 237, -1], dtype=tf.int32), - tf.constant([[[0.03, 0.3575, 0.98, 0.95]]], dtype=tf.float32)) - new_image, new_boxes, new_labels, new_keypoints = ( - preprocessor._strict_random_crop_image( - image, boxes, labels, keypoints=keypoints)) - with self.test_session() as sess: - new_image, new_boxes, new_labels, new_keypoints = sess.run( - [new_image, new_boxes, new_labels, new_keypoints]) - - expected_boxes = np.array([ - [0.0, 0.0, 0.75789469, 1.0], - [0.23157893, 0.24050637, 0.75789469, 1.0],], dtype=np.float32) - expected_keypoints = np.array([ - [[np.nan, np.nan], - [np.nan, np.nan], - [np.nan, np.nan]], - [[0.38947368, 0.07173], - [0.49473682, 0.24050637], - [0.60000002, 0.40928277]] - ], dtype=np.float32) - self.assertAllEqual(new_image.shape, [190, 237, 3]) - self.assertAllClose( - new_boxes.flatten(), expected_boxes.flatten()) - self.assertAllClose( - new_keypoints.flatten(), expected_keypoints.flatten()) - - def testRunRandomCropImageWithMasks(self): - image = self.createColorfulTestImage() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - masks = tf.random_uniform([2, 200, 400], dtype=tf.float32) - - tensor_dict = { - fields.InputDataFields.image: image, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_instance_masks: masks, - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_instance_masks=True) - - preprocessing_options = [(preprocessor.random_crop_image, {})] - - with mock.patch.object( - tf.image, - 'sample_distorted_bounding_box' - ) as mock_sample_distorted_bounding_box: - mock_sample_distorted_bounding_box.return_value = ( - tf.constant([6, 143, 0], dtype=tf.int32), - tf.constant([190, 237, -1], dtype=tf.int32), - tf.constant([[[0.03, 0.3575, 0.98, 0.95]]], dtype=tf.float32)) - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_image = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - distorted_masks = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_instance_masks] - with self.test_session() as sess: - (distorted_image_, distorted_boxes_, distorted_labels_, - distorted_masks_) = sess.run( - [distorted_image, distorted_boxes, distorted_labels, - distorted_masks]) - - expected_boxes = np.array([ - [0.0, 0.0, 0.75789469, 1.0], - [0.23157893, 0.24050637, 0.75789469, 1.0], - ], dtype=np.float32) - self.assertAllEqual(distorted_image_.shape, [1, 190, 237, 3]) - self.assertAllEqual(distorted_masks_.shape, [2, 190, 237]) - self.assertAllEqual(distorted_labels_, [1, 2]) - self.assertAllClose( - distorted_boxes_.flatten(), expected_boxes.flatten()) - - def testRunRandomCropImageWithKeypointsInsideCrop(self): - image = self.createColorfulTestImage() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - keypoints = self.createTestKeypointsInsideCrop() - - tensor_dict = { - fields.InputDataFields.image: image, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_keypoints: keypoints - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_keypoints=True) - - preprocessing_options = [(preprocessor.random_crop_image, {})] - - with mock.patch.object( - tf.image, - 'sample_distorted_bounding_box' - ) as mock_sample_distorted_bounding_box: - mock_sample_distorted_bounding_box.return_value = ( - tf.constant([6, 143, 0], dtype=tf.int32), - tf.constant([190, 237, -1], dtype=tf.int32), - tf.constant([[[0.03, 0.3575, 0.98, 0.95]]], dtype=tf.float32)) - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_image = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - distorted_keypoints = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_keypoints] - with self.test_session() as sess: - (distorted_image_, distorted_boxes_, distorted_labels_, - distorted_keypoints_) = sess.run( - [distorted_image, distorted_boxes, distorted_labels, - distorted_keypoints]) - - expected_boxes = np.array([ - [0.0, 0.0, 0.75789469, 1.0], - [0.23157893, 0.24050637, 0.75789469, 1.0], - ], dtype=np.float32) - expected_keypoints = np.array([ - [[0.38947368, 0.07173], - [0.49473682, 0.24050637], - [0.60000002, 0.40928277]], - [[0.38947368, 0.07173], - [0.49473682, 0.24050637], - [0.60000002, 0.40928277]] - ]) - self.assertAllEqual(distorted_image_.shape, [1, 190, 237, 3]) - self.assertAllEqual(distorted_labels_, [1, 2]) - self.assertAllClose( - distorted_boxes_.flatten(), expected_boxes.flatten()) - self.assertAllClose( - distorted_keypoints_.flatten(), expected_keypoints.flatten()) - - def testRunRandomCropImageWithKeypointsOutsideCrop(self): - image = self.createColorfulTestImage() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - keypoints = self.createTestKeypointsOutsideCrop() - - tensor_dict = { - fields.InputDataFields.image: image, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_keypoints: keypoints - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_keypoints=True) - - preprocessing_options = [(preprocessor.random_crop_image, {})] - - with mock.patch.object( - tf.image, - 'sample_distorted_bounding_box' - ) as mock_sample_distorted_bounding_box: - mock_sample_distorted_bounding_box.return_value = ( - tf.constant([6, 143, 0], dtype=tf.int32), - tf.constant([190, 237, -1], dtype=tf.int32), - tf.constant([[[0.03, 0.3575, 0.98, 0.95]]], dtype=tf.float32)) - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_image = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - distorted_keypoints = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_keypoints] - with self.test_session() as sess: - (distorted_image_, distorted_boxes_, distorted_labels_, - distorted_keypoints_) = sess.run( - [distorted_image, distorted_boxes, distorted_labels, - distorted_keypoints]) - - expected_boxes = np.array([ - [0.0, 0.0, 0.75789469, 1.0], - [0.23157893, 0.24050637, 0.75789469, 1.0], - ], dtype=np.float32) - expected_keypoints = np.array([ - [[np.nan, np.nan], - [np.nan, np.nan], - [np.nan, np.nan]], - [[np.nan, np.nan], - [np.nan, np.nan], - [np.nan, np.nan]], - ]) - self.assertAllEqual(distorted_image_.shape, [1, 190, 237, 3]) - self.assertAllEqual(distorted_labels_, [1, 2]) - self.assertAllClose( - distorted_boxes_.flatten(), expected_boxes.flatten()) - self.assertAllClose( - distorted_keypoints_.flatten(), expected_keypoints.flatten()) - - def testRunRetainBoxesAboveThreshold(self): - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - - tensor_dict = { - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_label_scores: label_scores - } - - preprocessing_options = [ - (preprocessor.retain_boxes_above_threshold, {'threshold': 0.6}) - ] - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_label_scores=True) - retained_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - retained_boxes = retained_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - retained_labels = retained_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - retained_label_scores = retained_tensor_dict[ - fields.InputDataFields.groundtruth_label_scores] - - with self.test_session() as sess: - (retained_boxes_, retained_labels_, - retained_label_scores_, expected_retained_boxes_, - expected_retained_labels_, expected_retained_label_scores_) = sess.run( - [retained_boxes, retained_labels, retained_label_scores, - self.expectedBoxesAfterThresholding(), - self.expectedLabelsAfterThresholding(), - self.expectedLabelScoresAfterThresholding()]) - - self.assertAllClose(retained_boxes_, expected_retained_boxes_) - self.assertAllClose(retained_labels_, expected_retained_labels_) - self.assertAllClose( - retained_label_scores_, expected_retained_label_scores_) - - def testRunRetainBoxesAboveThresholdWithMasks(self): - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - masks = self.createTestMasks() - - tensor_dict = { - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_label_scores: label_scores, - fields.InputDataFields.groundtruth_instance_masks: masks - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_label_scores=True, - include_instance_masks=True) - - preprocessing_options = [ - (preprocessor.retain_boxes_above_threshold, {'threshold': 0.6}) - ] - - retained_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - retained_masks = retained_tensor_dict[ - fields.InputDataFields.groundtruth_instance_masks] - - with self.test_session() as sess: - (retained_masks_, expected_masks_) = sess.run( - [retained_masks, - self.expectedMasksAfterThresholding()]) - self.assertAllClose(retained_masks_, expected_masks_) - - def testRunRetainBoxesAboveThresholdWithKeypoints(self): - boxes = self.createTestBoxes() - labels = self.createTestLabels() - label_scores = self.createTestLabelScores() - keypoints = self.createTestKeypoints() - - tensor_dict = { - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_label_scores: label_scores, - fields.InputDataFields.groundtruth_keypoints: keypoints - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_label_scores=True, - include_keypoints=True) - - preprocessing_options = [ - (preprocessor.retain_boxes_above_threshold, {'threshold': 0.6}) - ] - - retained_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - retained_keypoints = retained_tensor_dict[ - fields.InputDataFields.groundtruth_keypoints] - - with self.test_session() as sess: - (retained_keypoints_, expected_keypoints_) = sess.run( - [retained_keypoints, - self.expectedKeypointsAfterThresholding()]) - self.assertAllClose(retained_keypoints_, expected_keypoints_) - - def testRandomCropToAspectRatioWithCache(self): - preprocess_options = [(preprocessor.random_crop_to_aspect_ratio, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=False, - test_keypoints=False) - - def testRunRandomCropToAspectRatioWithMasks(self): - image = self.createColorfulTestImage() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - masks = tf.random_uniform([2, 200, 400], dtype=tf.float32) - - tensor_dict = { - fields.InputDataFields.image: image, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_instance_masks: masks - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_instance_masks=True) - - preprocessing_options = [(preprocessor.random_crop_to_aspect_ratio, {})] - - with mock.patch.object(preprocessor, - '_random_integer') as mock_random_integer: - mock_random_integer.return_value = tf.constant(0, dtype=tf.int32) - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_image = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - distorted_masks = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_instance_masks] - with self.test_session() as sess: - (distorted_image_, distorted_boxes_, distorted_labels_, - distorted_masks_) = sess.run([ - distorted_image, distorted_boxes, distorted_labels, distorted_masks - ]) - - expected_boxes = np.array([0.0, 0.5, 0.75, 1.0], dtype=np.float32) - self.assertAllEqual(distorted_image_.shape, [1, 200, 200, 3]) - self.assertAllEqual(distorted_labels_, [1]) - self.assertAllClose(distorted_boxes_.flatten(), - expected_boxes.flatten()) - self.assertAllEqual(distorted_masks_.shape, [1, 200, 200]) - - def testRunRandomCropToAspectRatioWithKeypoints(self): - image = self.createColorfulTestImage() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - keypoints = self.createTestKeypoints() - - tensor_dict = { - fields.InputDataFields.image: image, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_keypoints: keypoints - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_keypoints=True) - - preprocessing_options = [(preprocessor.random_crop_to_aspect_ratio, {})] - - with mock.patch.object(preprocessor, - '_random_integer') as mock_random_integer: - mock_random_integer.return_value = tf.constant(0, dtype=tf.int32) - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_image = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - distorted_keypoints = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_keypoints] - with self.test_session() as sess: - (distorted_image_, distorted_boxes_, distorted_labels_, - distorted_keypoints_) = sess.run([ - distorted_image, distorted_boxes, distorted_labels, - distorted_keypoints - ]) - - expected_boxes = np.array([0.0, 0.5, 0.75, 1.0], dtype=np.float32) - expected_keypoints = np.array( - [[0.1, 0.2], [0.2, 0.4], [0.3, 0.6]], dtype=np.float32) - self.assertAllEqual(distorted_image_.shape, [1, 200, 200, 3]) - self.assertAllEqual(distorted_labels_, [1]) - self.assertAllClose(distorted_boxes_.flatten(), - expected_boxes.flatten()) - self.assertAllClose(distorted_keypoints_.flatten(), - expected_keypoints.flatten()) - - def testRandomPadToAspectRatioWithCache(self): - preprocess_options = [(preprocessor.random_pad_to_aspect_ratio, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=True, - test_keypoints=True) - - def testRunRandomPadToAspectRatioWithMinMaxPaddedSizeRatios(self): - image = self.createColorfulTestImage() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - - tensor_dict = { - fields.InputDataFields.image: image, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map() - preprocessing_options = [(preprocessor.random_pad_to_aspect_ratio, - {'min_padded_size_ratio': (4.0, 4.0), - 'max_padded_size_ratio': (4.0, 4.0)})] - - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_image = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - with self.test_session() as sess: - distorted_image_, distorted_boxes_, distorted_labels_ = sess.run([ - distorted_image, distorted_boxes, distorted_labels]) - - expected_boxes = np.array( - [[0.0, 0.125, 0.1875, 0.5], [0.0625, 0.25, 0.1875, 0.5]], - dtype=np.float32) - self.assertAllEqual(distorted_image_.shape, [1, 800, 800, 3]) - self.assertAllEqual(distorted_labels_, [1, 2]) - self.assertAllClose(distorted_boxes_.flatten(), - expected_boxes.flatten()) - - def testRunRandomPadToAspectRatioWithMasks(self): - image = self.createColorfulTestImage() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - masks = tf.random_uniform([2, 200, 400], dtype=tf.float32) - - tensor_dict = { - fields.InputDataFields.image: image, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_instance_masks: masks - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_instance_masks=True) - - preprocessing_options = [(preprocessor.random_pad_to_aspect_ratio, {})] - - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_image = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - distorted_masks = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_instance_masks] - with self.test_session() as sess: - (distorted_image_, distorted_boxes_, distorted_labels_, - distorted_masks_) = sess.run([ - distorted_image, distorted_boxes, distorted_labels, distorted_masks - ]) - - expected_boxes = np.array( - [[0.0, 0.25, 0.375, 1.0], [0.125, 0.5, 0.375, 1.0]], dtype=np.float32) - self.assertAllEqual(distorted_image_.shape, [1, 400, 400, 3]) - self.assertAllEqual(distorted_labels_, [1, 2]) - self.assertAllClose(distorted_boxes_.flatten(), - expected_boxes.flatten()) - self.assertAllEqual(distorted_masks_.shape, [2, 400, 400]) - - def testRunRandomPadToAspectRatioWithKeypoints(self): - image = self.createColorfulTestImage() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - keypoints = self.createTestKeypoints() - - tensor_dict = { - fields.InputDataFields.image: image, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.groundtruth_keypoints: keypoints - } - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_keypoints=True) - - preprocessing_options = [(preprocessor.random_pad_to_aspect_ratio, {})] - - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_image = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_labels = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_classes] - distorted_keypoints = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_keypoints] - with self.test_session() as sess: - (distorted_image_, distorted_boxes_, distorted_labels_, - distorted_keypoints_) = sess.run([ - distorted_image, distorted_boxes, distorted_labels, - distorted_keypoints - ]) - - expected_boxes = np.array( - [[0.0, 0.25, 0.375, 1.0], [0.125, 0.5, 0.375, 1.0]], dtype=np.float32) - expected_keypoints = np.array([ - [[0.05, 0.1], [0.1, 0.2], [0.15, 0.3]], - [[0.2, 0.4], [0.25, 0.5], [0.3, 0.6]], - ], dtype=np.float32) - self.assertAllEqual(distorted_image_.shape, [1, 400, 400, 3]) - self.assertAllEqual(distorted_labels_, [1, 2]) - self.assertAllClose(distorted_boxes_.flatten(), - expected_boxes.flatten()) - self.assertAllClose(distorted_keypoints_.flatten(), - expected_keypoints.flatten()) - - def testRandomPadImageWithCache(self): - preprocess_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1,}), (preprocessor.random_pad_image, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=True, - test_keypoints=True) - - def testRandomPadImage(self): - preprocessing_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })] - - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images = tensor_dict[fields.InputDataFields.image] - - preprocessing_options = [(preprocessor.random_pad_image, {})] - padded_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - - padded_images = padded_tensor_dict[fields.InputDataFields.image] - padded_boxes = padded_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - boxes_shape = tf.shape(boxes) - padded_boxes_shape = tf.shape(padded_boxes) - images_shape = tf.shape(images) - padded_images_shape = tf.shape(padded_images) - - with self.test_session() as sess: - (boxes_shape_, padded_boxes_shape_, images_shape_, - padded_images_shape_, boxes_, padded_boxes_) = sess.run( - [boxes_shape, padded_boxes_shape, images_shape, - padded_images_shape, boxes, padded_boxes]) - self.assertAllEqual(boxes_shape_, padded_boxes_shape_) - self.assertTrue((images_shape_[1] >= padded_images_shape_[1] * 0.5).all) - self.assertTrue((images_shape_[2] >= padded_images_shape_[2] * 0.5).all) - self.assertTrue((images_shape_[1] <= padded_images_shape_[1]).all) - self.assertTrue((images_shape_[2] <= padded_images_shape_[2]).all) - self.assertTrue(np.all((boxes_[:, 2] - boxes_[:, 0]) >= ( - padded_boxes_[:, 2] - padded_boxes_[:, 0]))) - self.assertTrue(np.all((boxes_[:, 3] - boxes_[:, 1]) >= ( - padded_boxes_[:, 3] - padded_boxes_[:, 1]))) - - def testRandomCropPadImageWithCache(self): - preprocess_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1,}), (preprocessor.random_crop_pad_image, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=True, - test_keypoints=True) - - def testRandomCropPadImageWithRandomCoefOne(self): - preprocessing_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })] - - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - tensor_dict = preprocessor.preprocess(tensor_dict, preprocessing_options) - images = tensor_dict[fields.InputDataFields.image] - - preprocessing_options = [(preprocessor.random_crop_pad_image, { - 'random_coef': 1.0 - })] - padded_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - - padded_images = padded_tensor_dict[fields.InputDataFields.image] - padded_boxes = padded_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - boxes_shape = tf.shape(boxes) - padded_boxes_shape = tf.shape(padded_boxes) - images_shape = tf.shape(images) - padded_images_shape = tf.shape(padded_images) - - with self.test_session() as sess: - (boxes_shape_, padded_boxes_shape_, images_shape_, - padded_images_shape_, boxes_, padded_boxes_) = sess.run( - [boxes_shape, padded_boxes_shape, images_shape, - padded_images_shape, boxes, padded_boxes]) - self.assertAllEqual(boxes_shape_, padded_boxes_shape_) - self.assertTrue((images_shape_[1] >= padded_images_shape_[1] * 0.5).all) - self.assertTrue((images_shape_[2] >= padded_images_shape_[2] * 0.5).all) - self.assertTrue((images_shape_[1] <= padded_images_shape_[1]).all) - self.assertTrue((images_shape_[2] <= padded_images_shape_[2]).all) - self.assertTrue(np.all((boxes_[:, 2] - boxes_[:, 0]) >= ( - padded_boxes_[:, 2] - padded_boxes_[:, 0]))) - self.assertTrue(np.all((boxes_[:, 3] - boxes_[:, 1]) >= ( - padded_boxes_[:, 3] - padded_boxes_[:, 1]))) - - def testRandomCropToAspectRatio(self): - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - tensor_dict = preprocessor.preprocess(tensor_dict, []) - images = tensor_dict[fields.InputDataFields.image] - - preprocessing_options = [(preprocessor.random_crop_to_aspect_ratio, { - 'aspect_ratio': 2.0 - })] - cropped_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - - cropped_images = cropped_tensor_dict[fields.InputDataFields.image] - cropped_boxes = cropped_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - boxes_shape = tf.shape(boxes) - cropped_boxes_shape = tf.shape(cropped_boxes) - images_shape = tf.shape(images) - cropped_images_shape = tf.shape(cropped_images) - - with self.test_session() as sess: - (boxes_shape_, cropped_boxes_shape_, images_shape_, - cropped_images_shape_) = sess.run([ - boxes_shape, cropped_boxes_shape, images_shape, cropped_images_shape - ]) - self.assertAllEqual(boxes_shape_, cropped_boxes_shape_) - self.assertEqual(images_shape_[1], cropped_images_shape_[1] * 2) - self.assertEqual(images_shape_[2], cropped_images_shape_[2]) - - def testRandomPadToAspectRatio(self): - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - tensor_dict = preprocessor.preprocess(tensor_dict, []) - images = tensor_dict[fields.InputDataFields.image] - - preprocessing_options = [(preprocessor.random_pad_to_aspect_ratio, { - 'aspect_ratio': 2.0 - })] - padded_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - - padded_images = padded_tensor_dict[fields.InputDataFields.image] - padded_boxes = padded_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - boxes_shape = tf.shape(boxes) - padded_boxes_shape = tf.shape(padded_boxes) - images_shape = tf.shape(images) - padded_images_shape = tf.shape(padded_images) - - with self.test_session() as sess: - (boxes_shape_, padded_boxes_shape_, images_shape_, - padded_images_shape_) = sess.run([ - boxes_shape, padded_boxes_shape, images_shape, padded_images_shape - ]) - self.assertAllEqual(boxes_shape_, padded_boxes_shape_) - self.assertEqual(images_shape_[1], padded_images_shape_[1]) - self.assertEqual(2 * images_shape_[2], padded_images_shape_[2]) - - def testRandomBlackPatchesWithCache(self): - preprocess_options = [] - preprocess_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocess_options.append((preprocessor.random_black_patches, { - 'size_to_image_ratio': 0.5 - })) - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=True, - test_keypoints=True) - - def testRandomBlackPatches(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_black_patches, { - 'size_to_image_ratio': 0.5 - })) - images = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images} - blacked_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - blacked_images = blacked_tensor_dict[fields.InputDataFields.image] - images_shape = tf.shape(images) - blacked_images_shape = tf.shape(blacked_images) - - with self.test_session() as sess: - (images_shape_, blacked_images_shape_) = sess.run( - [images_shape, blacked_images_shape]) - self.assertAllEqual(images_shape_, blacked_images_shape_) - - def testRandomResizeMethodWithCache(self): - preprocess_options = [] - preprocess_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocess_options.append((preprocessor.random_resize_method, { - 'target_size': (75, 150) - })) - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=True, - test_keypoints=True) - - def testRandomResizeMethod(self): - preprocessing_options = [] - preprocessing_options.append((preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - })) - preprocessing_options.append((preprocessor.random_resize_method, { - 'target_size': (75, 150) - })) - images = self.createTestImages() - tensor_dict = {fields.InputDataFields.image: images} - resized_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - resized_images = resized_tensor_dict[fields.InputDataFields.image] - resized_images_shape = tf.shape(resized_images) - expected_images_shape = tf.constant([1, 75, 150, 3], dtype=tf.int32) - - with self.test_session() as sess: - (expected_images_shape_, resized_images_shape_) = sess.run( - [expected_images_shape, resized_images_shape]) - self.assertAllEqual(expected_images_shape_, - resized_images_shape_) - - def testResizeImageWithMasks(self): - """Tests image resizing, checking output sizes.""" - in_image_shape_list = [[60, 40, 3], [15, 30, 3]] - in_masks_shape_list = [[15, 60, 40], [10, 15, 30]] - height = 50 - width = 100 - expected_image_shape_list = [[50, 100, 3], [50, 100, 3]] - expected_masks_shape_list = [[15, 50, 100], [10, 50, 100]] - - for (in_image_shape, expected_image_shape, in_masks_shape, - expected_mask_shape) in zip(in_image_shape_list, - expected_image_shape_list, - in_masks_shape_list, - expected_masks_shape_list): - in_image = tf.random_uniform(in_image_shape) - in_masks = tf.random_uniform(in_masks_shape) - out_image, out_masks, _ = preprocessor.resize_image( - in_image, in_masks, new_height=height, new_width=width) - out_image_shape = tf.shape(out_image) - out_masks_shape = tf.shape(out_masks) - - with self.test_session() as sess: - out_image_shape, out_masks_shape = sess.run( - [out_image_shape, out_masks_shape]) - self.assertAllEqual(out_image_shape, expected_image_shape) - self.assertAllEqual(out_masks_shape, expected_mask_shape) - - def testResizeImageWithMasksTensorInputHeightAndWidth(self): - """Tests image resizing, checking output sizes.""" - in_image_shape_list = [[60, 40, 3], [15, 30, 3]] - in_masks_shape_list = [[15, 60, 40], [10, 15, 30]] - height = tf.constant(50, dtype=tf.int32) - width = tf.constant(100, dtype=tf.int32) - expected_image_shape_list = [[50, 100, 3], [50, 100, 3]] - expected_masks_shape_list = [[15, 50, 100], [10, 50, 100]] - - for (in_image_shape, expected_image_shape, in_masks_shape, - expected_mask_shape) in zip(in_image_shape_list, - expected_image_shape_list, - in_masks_shape_list, - expected_masks_shape_list): - in_image = tf.random_uniform(in_image_shape) - in_masks = tf.random_uniform(in_masks_shape) - out_image, out_masks, _ = preprocessor.resize_image( - in_image, in_masks, new_height=height, new_width=width) - out_image_shape = tf.shape(out_image) - out_masks_shape = tf.shape(out_masks) - - with self.test_session() as sess: - out_image_shape, out_masks_shape = sess.run( - [out_image_shape, out_masks_shape]) - self.assertAllEqual(out_image_shape, expected_image_shape) - self.assertAllEqual(out_masks_shape, expected_mask_shape) - - def testResizeImageWithNoInstanceMask(self): - """Tests image resizing, checking output sizes.""" - in_image_shape_list = [[60, 40, 3], [15, 30, 3]] - in_masks_shape_list = [[0, 60, 40], [0, 15, 30]] - height = 50 - width = 100 - expected_image_shape_list = [[50, 100, 3], [50, 100, 3]] - expected_masks_shape_list = [[0, 50, 100], [0, 50, 100]] - - for (in_image_shape, expected_image_shape, in_masks_shape, - expected_mask_shape) in zip(in_image_shape_list, - expected_image_shape_list, - in_masks_shape_list, - expected_masks_shape_list): - in_image = tf.random_uniform(in_image_shape) - in_masks = tf.random_uniform(in_masks_shape) - out_image, out_masks, _ = preprocessor.resize_image( - in_image, in_masks, new_height=height, new_width=width) - out_image_shape = tf.shape(out_image) - out_masks_shape = tf.shape(out_masks) - - with self.test_session() as sess: - out_image_shape, out_masks_shape = sess.run( - [out_image_shape, out_masks_shape]) - self.assertAllEqual(out_image_shape, expected_image_shape) - self.assertAllEqual(out_masks_shape, expected_mask_shape) - - def testResizeToRangePreservesStaticSpatialShape(self): - """Tests image resizing, checking output sizes.""" - in_shape_list = [[60, 40, 3], [15, 30, 3], [15, 50, 3]] - min_dim = 50 - max_dim = 100 - expected_shape_list = [[75, 50, 3], [50, 100, 3], [30, 100, 3]] - - for in_shape, expected_shape in zip(in_shape_list, expected_shape_list): - in_image = tf.random_uniform(in_shape) - out_image, _ = preprocessor.resize_to_range( - in_image, min_dimension=min_dim, max_dimension=max_dim) - self.assertAllEqual(out_image.get_shape().as_list(), expected_shape) - - def testResizeToRangeWithDynamicSpatialShape(self): - """Tests image resizing, checking output sizes.""" - in_shape_list = [[60, 40, 3], [15, 30, 3], [15, 50, 3]] - min_dim = 50 - max_dim = 100 - expected_shape_list = [[75, 50, 3], [50, 100, 3], [30, 100, 3]] - - for in_shape, expected_shape in zip(in_shape_list, expected_shape_list): - in_image = tf.placeholder(tf.float32, shape=(None, None, 3)) - out_image, _ = preprocessor.resize_to_range( - in_image, min_dimension=min_dim, max_dimension=max_dim) - out_image_shape = tf.shape(out_image) - with self.test_session() as sess: - out_image_shape = sess.run(out_image_shape, - feed_dict={in_image: - np.random.randn(*in_shape)}) - self.assertAllEqual(out_image_shape, expected_shape) - - def testResizeToRangeWithPadToMaxDimensionReturnsCorrectShapes(self): - in_shape_list = [[60, 40, 3], [15, 30, 3], [15, 50, 3]] - min_dim = 50 - max_dim = 100 - expected_shape_list = [[100, 100, 3], [100, 100, 3], [100, 100, 3]] - - for in_shape, expected_shape in zip(in_shape_list, expected_shape_list): - in_image = tf.placeholder(tf.float32, shape=(None, None, 3)) - out_image, _ = preprocessor.resize_to_range( - in_image, - min_dimension=min_dim, - max_dimension=max_dim, - pad_to_max_dimension=True) - self.assertAllEqual(out_image.shape.as_list(), expected_shape) - out_image_shape = tf.shape(out_image) - with self.test_session() as sess: - out_image_shape = sess.run( - out_image_shape, feed_dict={in_image: np.random.randn(*in_shape)}) - self.assertAllEqual(out_image_shape, expected_shape) - - def testResizeToRangeWithPadToMaxDimensionReturnsCorrectTensor(self): - in_image_np = np.array([[[0, 1, 2]]], np.float32) - ex_image_np = np.array( - [[[0, 1, 2], [123.68, 116.779, 103.939]], - [[123.68, 116.779, 103.939], [123.68, 116.779, 103.939]]], np.float32) - min_dim = 1 - max_dim = 2 - - in_image = tf.placeholder(tf.float32, shape=(None, None, 3)) - out_image, _ = preprocessor.resize_to_range( - in_image, - min_dimension=min_dim, - max_dimension=max_dim, - pad_to_max_dimension=True, - per_channel_pad_value=(123.68, 116.779, 103.939)) - - with self.test_session() as sess: - out_image_np = sess.run(out_image, feed_dict={in_image: in_image_np}) - self.assertAllClose(ex_image_np, out_image_np) - - def testResizeToRangeWithMasksPreservesStaticSpatialShape(self): - """Tests image resizing, checking output sizes.""" - in_image_shape_list = [[60, 40, 3], [15, 30, 3]] - in_masks_shape_list = [[15, 60, 40], [10, 15, 30]] - min_dim = 50 - max_dim = 100 - expected_image_shape_list = [[75, 50, 3], [50, 100, 3]] - expected_masks_shape_list = [[15, 75, 50], [10, 50, 100]] - - for (in_image_shape, expected_image_shape, in_masks_shape, - expected_mask_shape) in zip(in_image_shape_list, - expected_image_shape_list, - in_masks_shape_list, - expected_masks_shape_list): - in_image = tf.random_uniform(in_image_shape) - in_masks = tf.random_uniform(in_masks_shape) - out_image, out_masks, _ = preprocessor.resize_to_range( - in_image, in_masks, min_dimension=min_dim, max_dimension=max_dim) - self.assertAllEqual(out_masks.get_shape().as_list(), expected_mask_shape) - self.assertAllEqual(out_image.get_shape().as_list(), expected_image_shape) - - def testResizeToRangeWithMasksAndDynamicSpatialShape(self): - """Tests image resizing, checking output sizes.""" - in_image_shape_list = [[60, 40, 3], [15, 30, 3]] - in_masks_shape_list = [[15, 60, 40], [10, 15, 30]] - min_dim = 50 - max_dim = 100 - expected_image_shape_list = [[75, 50, 3], [50, 100, 3]] - expected_masks_shape_list = [[15, 75, 50], [10, 50, 100]] - - for (in_image_shape, expected_image_shape, in_masks_shape, - expected_mask_shape) in zip(in_image_shape_list, - expected_image_shape_list, - in_masks_shape_list, - expected_masks_shape_list): - in_image = tf.placeholder(tf.float32, shape=(None, None, 3)) - in_masks = tf.placeholder(tf.float32, shape=(None, None, None)) - in_masks = tf.random_uniform(in_masks_shape) - out_image, out_masks, _ = preprocessor.resize_to_range( - in_image, in_masks, min_dimension=min_dim, max_dimension=max_dim) - out_image_shape = tf.shape(out_image) - out_masks_shape = tf.shape(out_masks) - - with self.test_session() as sess: - out_image_shape, out_masks_shape = sess.run( - [out_image_shape, out_masks_shape], - feed_dict={ - in_image: np.random.randn(*in_image_shape), - in_masks: np.random.randn(*in_masks_shape) - }) - self.assertAllEqual(out_image_shape, expected_image_shape) - self.assertAllEqual(out_masks_shape, expected_mask_shape) - - def testResizeToRangeWithInstanceMasksTensorOfSizeZero(self): - """Tests image resizing, checking output sizes.""" - in_image_shape_list = [[60, 40, 3], [15, 30, 3]] - in_masks_shape_list = [[0, 60, 40], [0, 15, 30]] - min_dim = 50 - max_dim = 100 - expected_image_shape_list = [[75, 50, 3], [50, 100, 3]] - expected_masks_shape_list = [[0, 75, 50], [0, 50, 100]] - - for (in_image_shape, expected_image_shape, in_masks_shape, - expected_mask_shape) in zip(in_image_shape_list, - expected_image_shape_list, - in_masks_shape_list, - expected_masks_shape_list): - in_image = tf.random_uniform(in_image_shape) - in_masks = tf.random_uniform(in_masks_shape) - out_image, out_masks, _ = preprocessor.resize_to_range( - in_image, in_masks, min_dimension=min_dim, max_dimension=max_dim) - out_image_shape = tf.shape(out_image) - out_masks_shape = tf.shape(out_masks) - - with self.test_session() as sess: - out_image_shape, out_masks_shape = sess.run( - [out_image_shape, out_masks_shape]) - self.assertAllEqual(out_image_shape, expected_image_shape) - self.assertAllEqual(out_masks_shape, expected_mask_shape) - - def testResizeToRange4DImageTensor(self): - image = tf.random_uniform([1, 200, 300, 3]) - with self.assertRaises(ValueError): - preprocessor.resize_to_range(image, 500, 600) - - def testResizeToRangeSameMinMax(self): - """Tests image resizing, checking output sizes.""" - in_shape_list = [[312, 312, 3], [299, 299, 3]] - min_dim = 320 - max_dim = 320 - expected_shape_list = [[320, 320, 3], [320, 320, 3]] - - for in_shape, expected_shape in zip(in_shape_list, expected_shape_list): - in_image = tf.random_uniform(in_shape) - out_image, _ = preprocessor.resize_to_range( - in_image, min_dimension=min_dim, max_dimension=max_dim) - out_image_shape = tf.shape(out_image) - - with self.test_session() as sess: - out_image_shape = sess.run(out_image_shape) - self.assertAllEqual(out_image_shape, expected_shape) - - def testResizeToMinDimensionTensorShapes(self): - in_image_shape_list = [[60, 55, 3], [15, 30, 3]] - in_masks_shape_list = [[15, 60, 55], [10, 15, 30]] - min_dim = 50 - expected_image_shape_list = [[60, 55, 3], [50, 100, 3]] - expected_masks_shape_list = [[15, 60, 55], [10, 50, 100]] - - for (in_image_shape, expected_image_shape, in_masks_shape, - expected_mask_shape) in zip(in_image_shape_list, - expected_image_shape_list, - in_masks_shape_list, - expected_masks_shape_list): - in_image = tf.placeholder(tf.float32, shape=(None, None, 3)) - in_masks = tf.placeholder(tf.float32, shape=(None, None, None)) - in_masks = tf.random_uniform(in_masks_shape) - out_image, out_masks, _ = preprocessor.resize_to_min_dimension( - in_image, in_masks, min_dimension=min_dim) - out_image_shape = tf.shape(out_image) - out_masks_shape = tf.shape(out_masks) - - with self.test_session() as sess: - out_image_shape, out_masks_shape = sess.run( - [out_image_shape, out_masks_shape], - feed_dict={ - in_image: np.random.randn(*in_image_shape), - in_masks: np.random.randn(*in_masks_shape) - }) - self.assertAllEqual(out_image_shape, expected_image_shape) - self.assertAllEqual(out_masks_shape, expected_mask_shape) - - def testResizeToMinDimensionWithInstanceMasksTensorOfSizeZero(self): - """Tests image resizing, checking output sizes.""" - in_image_shape_list = [[60, 40, 3], [15, 30, 3]] - in_masks_shape_list = [[0, 60, 40], [0, 15, 30]] - min_dim = 50 - expected_image_shape_list = [[75, 50, 3], [50, 100, 3]] - expected_masks_shape_list = [[0, 75, 50], [0, 50, 100]] - - for (in_image_shape, expected_image_shape, in_masks_shape, - expected_mask_shape) in zip(in_image_shape_list, - expected_image_shape_list, - in_masks_shape_list, - expected_masks_shape_list): - in_image = tf.random_uniform(in_image_shape) - in_masks = tf.random_uniform(in_masks_shape) - out_image, out_masks, _ = preprocessor.resize_to_min_dimension( - in_image, in_masks, min_dimension=min_dim) - out_image_shape = tf.shape(out_image) - out_masks_shape = tf.shape(out_masks) - - with self.test_session() as sess: - out_image_shape, out_masks_shape = sess.run( - [out_image_shape, out_masks_shape]) - self.assertAllEqual(out_image_shape, expected_image_shape) - self.assertAllEqual(out_masks_shape, expected_mask_shape) - - def testResizeToMinDimensionRaisesErrorOn4DImage(self): - image = tf.random_uniform([1, 200, 300, 3]) - with self.assertRaises(ValueError): - preprocessor.resize_to_min_dimension(image, 500) - - def testScaleBoxesToPixelCoordinates(self): - """Tests box scaling, checking scaled values.""" - in_shape = [60, 40, 3] - in_boxes = [[0.1, 0.2, 0.4, 0.6], - [0.5, 0.3, 0.9, 0.7]] - - expected_boxes = [[6., 8., 24., 24.], - [30., 12., 54., 28.]] - - in_image = tf.random_uniform(in_shape) - in_boxes = tf.constant(in_boxes) - _, out_boxes = preprocessor.scale_boxes_to_pixel_coordinates( - in_image, boxes=in_boxes) - with self.test_session() as sess: - out_boxes = sess.run(out_boxes) - self.assertAllClose(out_boxes, expected_boxes) - - def testScaleBoxesToPixelCoordinatesWithKeypoints(self): - """Tests box and keypoint scaling, checking scaled values.""" - in_shape = [60, 40, 3] - in_boxes = self.createTestBoxes() - in_keypoints = self.createTestKeypoints() - - expected_boxes = [[0., 10., 45., 40.], - [15., 20., 45., 40.]] - expected_keypoints = [ - [[6., 4.], [12., 8.], [18., 12.]], - [[24., 16.], [30., 20.], [36., 24.]], - ] - - in_image = tf.random_uniform(in_shape) - _, out_boxes, out_keypoints = preprocessor.scale_boxes_to_pixel_coordinates( - in_image, boxes=in_boxes, keypoints=in_keypoints) - with self.test_session() as sess: - out_boxes_, out_keypoints_ = sess.run([out_boxes, out_keypoints]) - self.assertAllClose(out_boxes_, expected_boxes) - self.assertAllClose(out_keypoints_, expected_keypoints) - - def testSubtractChannelMean(self): - """Tests whether channel means have been subtracted.""" - with self.test_session(): - image = tf.zeros((240, 320, 3)) - means = [1, 2, 3] - actual = preprocessor.subtract_channel_mean(image, means=means) - actual = actual.eval() - - self.assertTrue((actual[:, :, 0] == -1).all()) - self.assertTrue((actual[:, :, 1] == -2).all()) - self.assertTrue((actual[:, :, 2] == -3).all()) - - def testOneHotEncoding(self): - """Tests one hot encoding of multiclass labels.""" - with self.test_session(): - labels = tf.constant([1, 4, 2], dtype=tf.int32) - one_hot = preprocessor.one_hot_encoding(labels, num_classes=5) - one_hot = one_hot.eval() - - self.assertAllEqual([0, 1, 1, 0, 1], one_hot) - - def testSSDRandomCropWithCache(self): - preprocess_options = [ - (preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - }), - (preprocessor.ssd_random_crop, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=False, - test_keypoints=False) - - def testSSDRandomCrop(self): - preprocessing_options = [ - (preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - }), - (preprocessor.ssd_random_crop, {})] - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - distorted_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - - images_rank = tf.rank(images) - distorted_images_rank = tf.rank(distorted_images) - boxes_rank = tf.rank(boxes) - distorted_boxes_rank = tf.rank(distorted_boxes) - - with self.test_session() as sess: - (boxes_rank_, distorted_boxes_rank_, images_rank_, - distorted_images_rank_) = sess.run( - [boxes_rank, distorted_boxes_rank, images_rank, - distorted_images_rank]) - self.assertAllEqual(boxes_rank_, distorted_boxes_rank_) - self.assertAllEqual(images_rank_, distorted_images_rank_) - - def testSSDRandomCropWithMultiClassScores(self): - preprocessing_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - }), (preprocessor.ssd_random_crop, {})] - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - multiclass_scores = self.createTestMultiClassScores() - - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - fields.InputDataFields.multiclass_scores: multiclass_scores, - } - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_multiclass_scores=True) - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - distorted_multiclass_scores = distorted_tensor_dict[ - fields.InputDataFields.multiclass_scores] - - images_rank = tf.rank(images) - distorted_images_rank = tf.rank(distorted_images) - boxes_rank = tf.rank(boxes) - distorted_boxes_rank = tf.rank(distorted_boxes) - multiclass_scores_rank = tf.rank(multiclass_scores) - distorted_multiclass_scores_rank = tf.rank(distorted_multiclass_scores) - - with self.test_session() as sess: - (boxes_rank_, distorted_boxes_, distorted_boxes_rank_, images_rank_, - distorted_images_rank_, multiclass_scores_rank_, - distorted_multiclass_scores_, - distorted_multiclass_scores_rank_) = sess.run([ - boxes_rank, distorted_boxes, distorted_boxes_rank, images_rank, - distorted_images_rank, multiclass_scores_rank, - distorted_multiclass_scores, distorted_multiclass_scores_rank - ]) - self.assertAllEqual(boxes_rank_, distorted_boxes_rank_) - self.assertAllEqual(images_rank_, distorted_images_rank_) - self.assertAllEqual(multiclass_scores_rank_, - distorted_multiclass_scores_rank_) - self.assertAllEqual(distorted_boxes_.shape[0], - distorted_multiclass_scores_.shape[0]) - - def testSSDRandomCropPad(self): - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - preprocessing_options = [ - (preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - }), - (preprocessor.ssd_random_crop_pad, {})] - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - distorted_tensor_dict = preprocessor.preprocess(tensor_dict, - preprocessing_options) - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - - images_rank = tf.rank(images) - distorted_images_rank = tf.rank(distorted_images) - boxes_rank = tf.rank(boxes) - distorted_boxes_rank = tf.rank(distorted_boxes) - - with self.test_session() as sess: - (boxes_rank_, distorted_boxes_rank_, images_rank_, - distorted_images_rank_) = sess.run([ - boxes_rank, distorted_boxes_rank, images_rank, distorted_images_rank - ]) - self.assertAllEqual(boxes_rank_, distorted_boxes_rank_) - self.assertAllEqual(images_rank_, distorted_images_rank_) - - def testSSDRandomCropFixedAspectRatioWithCache(self): - preprocess_options = [ - (preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - }), - (preprocessor.ssd_random_crop_fixed_aspect_ratio, {})] - self._testPreprocessorCache(preprocess_options, - test_boxes=True, - test_masks=False, - test_keypoints=False) - - def _testSSDRandomCropFixedAspectRatio(self, - include_label_scores, - include_multiclass_scores, - include_instance_masks, - include_keypoints): - images = self.createTestImages() - boxes = self.createTestBoxes() - labels = self.createTestLabels() - preprocessing_options = [(preprocessor.normalize_image, { - 'original_minval': 0, - 'original_maxval': 255, - 'target_minval': 0, - 'target_maxval': 1 - }), (preprocessor.ssd_random_crop_fixed_aspect_ratio, {})] - tensor_dict = { - fields.InputDataFields.image: images, - fields.InputDataFields.groundtruth_boxes: boxes, - fields.InputDataFields.groundtruth_classes: labels, - } - if include_label_scores: - label_scores = self.createTestLabelScores() - tensor_dict[fields.InputDataFields.groundtruth_label_scores] = ( - label_scores) - if include_multiclass_scores: - multiclass_scores = self.createTestMultiClassScores() - tensor_dict[fields.InputDataFields.multiclass_scores] = ( - multiclass_scores) - if include_instance_masks: - masks = self.createTestMasks() - tensor_dict[fields.InputDataFields.groundtruth_instance_masks] = masks - if include_keypoints: - keypoints = self.createTestKeypoints() - tensor_dict[fields.InputDataFields.groundtruth_keypoints] = keypoints - - preprocessor_arg_map = preprocessor.get_default_func_arg_map( - include_label_scores=include_label_scores, - include_multiclass_scores=include_multiclass_scores, - include_instance_masks=include_instance_masks, - include_keypoints=include_keypoints) - distorted_tensor_dict = preprocessor.preprocess( - tensor_dict, preprocessing_options, func_arg_map=preprocessor_arg_map) - distorted_images = distorted_tensor_dict[fields.InputDataFields.image] - distorted_boxes = distorted_tensor_dict[ - fields.InputDataFields.groundtruth_boxes] - images_rank = tf.rank(images) - distorted_images_rank = tf.rank(distorted_images) - boxes_rank = tf.rank(boxes) - distorted_boxes_rank = tf.rank(distorted_boxes) - - with self.test_session() as sess: - (boxes_rank_, distorted_boxes_rank_, images_rank_, - distorted_images_rank_) = sess.run( - [boxes_rank, distorted_boxes_rank, images_rank, - distorted_images_rank]) - self.assertAllEqual(boxes_rank_, distorted_boxes_rank_) - self.assertAllEqual(images_rank_, distorted_images_rank_) - - def testSSDRandomCropFixedAspectRatio(self): - self._testSSDRandomCropFixedAspectRatio(include_label_scores=False, - include_multiclass_scores=False, - include_instance_masks=False, - include_keypoints=False) - - def testSSDRandomCropFixedAspectRatioWithMultiClassScores(self): - self._testSSDRandomCropFixedAspectRatio(include_label_scores=False, - include_multiclass_scores=True, - include_instance_masks=False, - include_keypoints=False) - - def testSSDRandomCropFixedAspectRatioWithMasksAndKeypoints(self): - self._testSSDRandomCropFixedAspectRatio(include_label_scores=False, - include_multiclass_scores=False, - include_instance_masks=True, - include_keypoints=True) - - def testSSDRandomCropFixedAspectRatioWithLabelScoresMasksAndKeypoints(self): - self._testSSDRandomCropFixedAspectRatio(include_label_scores=True, - include_multiclass_scores=False, - include_instance_masks=True, - include_keypoints=True) - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/region_similarity_calculator.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/region_similarity_calculator.py deleted file mode 100644 index f344006a3..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/region_similarity_calculator.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Region Similarity Calculators for BoxLists. - -Region Similarity Calculators compare a pairwise measure of similarity -between the boxes in two BoxLists. -""" -from abc import ABCMeta -from abc import abstractmethod - -import tensorflow as tf - -from object_detection.core import box_list_ops - - -class RegionSimilarityCalculator(object): - """Abstract base class for region similarity calculator.""" - __metaclass__ = ABCMeta - - def compare(self, boxlist1, boxlist2, scope=None): - """Computes matrix of pairwise similarity between BoxLists. - - This op (to be overriden) computes a measure of pairwise similarity between - the boxes in the given BoxLists. Higher values indicate more similarity. - - Note that this method simply measures similarity and does not explicitly - perform a matching. - - Args: - boxlist1: BoxList holding N boxes. - boxlist2: BoxList holding M boxes. - scope: Op scope name. Defaults to 'Compare' if None. - - Returns: - a (float32) tensor of shape [N, M] with pairwise similarity score. - """ - with tf.name_scope(scope, 'Compare', [boxlist1, boxlist2]) as scope: - return self._compare(boxlist1, boxlist2) - - @abstractmethod - def _compare(self, boxlist1, boxlist2): - pass - - -class IouSimilarity(RegionSimilarityCalculator): - """Class to compute similarity based on Intersection over Union (IOU) metric. - - This class computes pairwise similarity between two BoxLists based on IOU. - """ - - def _compare(self, boxlist1, boxlist2): - """Compute pairwise IOU similarity between the two BoxLists. - - Args: - boxlist1: BoxList holding N boxes. - boxlist2: BoxList holding M boxes. - - Returns: - A tensor with shape [N, M] representing pairwise iou scores. - """ - return box_list_ops.iou(boxlist1, boxlist2) - - -class NegSqDistSimilarity(RegionSimilarityCalculator): - """Class to compute similarity based on the squared distance metric. - - This class computes pairwise similarity between two BoxLists based on the - negative squared distance metric. - """ - - def _compare(self, boxlist1, boxlist2): - """Compute matrix of (negated) sq distances. - - Args: - boxlist1: BoxList holding N boxes. - boxlist2: BoxList holding M boxes. - - Returns: - A tensor with shape [N, M] representing negated pairwise squared distance. - """ - return -1 * box_list_ops.sq_dist(boxlist1, boxlist2) - - -class IoaSimilarity(RegionSimilarityCalculator): - """Class to compute similarity based on Intersection over Area (IOA) metric. - - This class computes pairwise similarity between two BoxLists based on their - pairwise intersections divided by the areas of second BoxLists. - """ - - def _compare(self, boxlist1, boxlist2): - """Compute pairwise IOA similarity between the two BoxLists. - - Args: - boxlist1: BoxList holding N boxes. - boxlist2: BoxList holding M boxes. - - Returns: - A tensor with shape [N, M] representing pairwise IOA scores. - """ - return box_list_ops.ioa(boxlist1, boxlist2) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/region_similarity_calculator_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/region_similarity_calculator_test.py deleted file mode 100644 index 162151a3b..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/region_similarity_calculator_test.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for region_similarity_calculator.""" -import tensorflow as tf - -from object_detection.core import box_list -from object_detection.core import region_similarity_calculator - - -class RegionSimilarityCalculatorTest(tf.test.TestCase): - - def test_get_correct_pairwise_similarity_based_on_iou(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - exp_output = [[2.0 / 16.0, 0, 6.0 / 400.0], [1.0 / 16.0, 0.0, 5.0 / 400.0]] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - iou_similarity_calculator = region_similarity_calculator.IouSimilarity() - iou_similarity = iou_similarity_calculator.compare(boxes1, boxes2) - with self.test_session() as sess: - iou_output = sess.run(iou_similarity) - self.assertAllClose(iou_output, exp_output) - - def test_get_correct_pairwise_similarity_based_on_squared_distances(self): - corners1 = tf.constant([[0.0, 0.0, 0.0, 0.0], - [1.0, 1.0, 0.0, 2.0]]) - corners2 = tf.constant([[3.0, 4.0, 1.0, 0.0], - [-4.0, 0.0, 0.0, 3.0], - [0.0, 0.0, 0.0, 0.0]]) - exp_output = [[-26, -25, 0], [-18, -27, -6]] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - dist_similarity_calc = region_similarity_calculator.NegSqDistSimilarity() - dist_similarity = dist_similarity_calc.compare(boxes1, boxes2) - with self.test_session() as sess: - dist_output = sess.run(dist_similarity) - self.assertAllClose(dist_output, exp_output) - - def test_get_correct_pairwise_similarity_based_on_ioa(self): - corners1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) - corners2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0], - [0.0, 0.0, 20.0, 20.0]]) - exp_output_1 = [[2.0 / 12.0, 0, 6.0 / 400.0], - [1.0 / 12.0, 0.0, 5.0 / 400.0]] - exp_output_2 = [[2.0 / 6.0, 1.0 / 5.0], - [0, 0], - [6.0 / 6.0, 5.0 / 5.0]] - boxes1 = box_list.BoxList(corners1) - boxes2 = box_list.BoxList(corners2) - ioa_similarity_calculator = region_similarity_calculator.IoaSimilarity() - ioa_similarity_1 = ioa_similarity_calculator.compare(boxes1, boxes2) - ioa_similarity_2 = ioa_similarity_calculator.compare(boxes2, boxes1) - with self.test_session() as sess: - iou_output_1, iou_output_2 = sess.run( - [ioa_similarity_1, ioa_similarity_2]) - self.assertAllClose(iou_output_1, exp_output_1) - self.assertAllClose(iou_output_2, exp_output_2) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/standard_fields.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/standard_fields.py deleted file mode 100644 index 11282da6d..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/standard_fields.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Contains classes specifying naming conventions used for object detection. - - -Specifies: - InputDataFields: standard fields used by reader/preprocessor/batcher. - DetectionResultFields: standard fields returned by object detector. - BoxListFields: standard field used by BoxList - TfExampleFields: standard fields for tf-example data format (go/tf-example). -""" - - -class InputDataFields(object): - """Names for the input tensors. - - Holds the standard data field names to use for identifying input tensors. This - should be used by the decoder to identify keys for the returned tensor_dict - containing input tensors. And it should be used by the model to identify the - tensors it needs. - - Attributes: - image: image. - image_additional_channels: additional channels. - original_image: image in the original input size. - key: unique key corresponding to image. - source_id: source of the original image. - filename: original filename of the dataset (without common path). - groundtruth_image_classes: image-level class labels. - groundtruth_boxes: coordinates of the ground truth boxes in the image. - groundtruth_classes: box-level class labels. - groundtruth_label_types: box-level label types (e.g. explicit negative). - groundtruth_is_crowd: [DEPRECATED, use groundtruth_group_of instead] - is the groundtruth a single object or a crowd. - groundtruth_area: area of a groundtruth segment. - groundtruth_difficult: is a `difficult` object - groundtruth_group_of: is a `group_of` objects, e.g. multiple objects of the - same class, forming a connected group, where instances are heavily - occluding each other. - proposal_boxes: coordinates of object proposal boxes. - proposal_objectness: objectness score of each proposal. - groundtruth_instance_masks: ground truth instance masks. - groundtruth_instance_boundaries: ground truth instance boundaries. - groundtruth_instance_classes: instance mask-level class labels. - groundtruth_keypoints: ground truth keypoints. - groundtruth_keypoint_visibilities: ground truth keypoint visibilities. - groundtruth_label_scores: groundtruth label scores. - groundtruth_weights: groundtruth weight factor for bounding boxes. - num_groundtruth_boxes: number of groundtruth boxes. - true_image_shapes: true shapes of images in the resized images, as resized - images can be padded with zeros. - verified_labels: list of human-verified image-level labels (note, that a - label can be verified both as positive and negative). - multiclass_scores: the label score per class for each box. - """ - image = 'image' - image_additional_channels = 'image_additional_channels' - original_image = 'original_image' - key = 'key' - source_id = 'source_id' - filename = 'filename' - groundtruth_image_classes = 'groundtruth_image_classes' - groundtruth_boxes = 'groundtruth_boxes' - groundtruth_classes = 'groundtruth_classes' - groundtruth_label_types = 'groundtruth_label_types' - groundtruth_is_crowd = 'groundtruth_is_crowd' - groundtruth_area = 'groundtruth_area' - groundtruth_difficult = 'groundtruth_difficult' - groundtruth_group_of = 'groundtruth_group_of' - proposal_boxes = 'proposal_boxes' - proposal_objectness = 'proposal_objectness' - groundtruth_instance_masks = 'groundtruth_instance_masks' - groundtruth_instance_boundaries = 'groundtruth_instance_boundaries' - groundtruth_instance_classes = 'groundtruth_instance_classes' - groundtruth_keypoints = 'groundtruth_keypoints' - groundtruth_keypoint_visibilities = 'groundtruth_keypoint_visibilities' - groundtruth_label_scores = 'groundtruth_label_scores' - groundtruth_weights = 'groundtruth_weights' - num_groundtruth_boxes = 'num_groundtruth_boxes' - true_image_shape = 'true_image_shape' - verified_labels = 'verified_labels' - multiclass_scores = 'multiclass_scores' - - -class DetectionResultFields(object): - """Naming conventions for storing the output of the detector. - - Attributes: - source_id: source of the original image. - key: unique key corresponding to image. - detection_boxes: coordinates of the detection boxes in the image. - detection_scores: detection scores for the detection boxes in the image. - detection_classes: detection-level class labels. - detection_masks: contains a segmentation mask for each detection box. - detection_boundaries: contains an object boundary for each detection box. - detection_keypoints: contains detection keypoints for each detection box. - num_detections: number of detections in the batch. - """ - - source_id = 'source_id' - key = 'key' - detection_boxes = 'detection_boxes' - detection_scores = 'detection_scores' - detection_classes = 'detection_classes' - detection_masks = 'detection_masks' - detection_boundaries = 'detection_boundaries' - detection_keypoints = 'detection_keypoints' - num_detections = 'num_detections' - - -class BoxListFields(object): - """Naming conventions for BoxLists. - - Attributes: - boxes: bounding box coordinates. - classes: classes per bounding box. - scores: scores per bounding box. - weights: sample weights per bounding box. - objectness: objectness score per bounding box. - masks: masks per bounding box. - boundaries: boundaries per bounding box. - keypoints: keypoints per bounding box. - keypoint_heatmaps: keypoint heatmaps per bounding box. - is_crowd: is_crowd annotation per bounding box. - """ - boxes = 'boxes' - classes = 'classes' - scores = 'scores' - weights = 'weights' - objectness = 'objectness' - masks = 'masks' - boundaries = 'boundaries' - keypoints = 'keypoints' - keypoint_heatmaps = 'keypoint_heatmaps' - is_crowd = 'is_crowd' - - -class TfExampleFields(object): - """TF-example proto feature names for object detection. - - Holds the standard feature names to load from an Example proto for object - detection. - - Attributes: - image_encoded: JPEG encoded string - image_format: image format, e.g. "JPEG" - filename: filename - channels: number of channels of image - colorspace: colorspace, e.g. "RGB" - height: height of image in pixels, e.g. 462 - width: width of image in pixels, e.g. 581 - source_id: original source of the image - image_class_text: image-level label in text format - image_class_label: image-level label in numerical format - object_class_text: labels in text format, e.g. ["person", "cat"] - object_class_label: labels in numbers, e.g. [16, 8] - object_bbox_xmin: xmin coordinates of groundtruth box, e.g. 10, 30 - object_bbox_xmax: xmax coordinates of groundtruth box, e.g. 50, 40 - object_bbox_ymin: ymin coordinates of groundtruth box, e.g. 40, 50 - object_bbox_ymax: ymax coordinates of groundtruth box, e.g. 80, 70 - object_view: viewpoint of object, e.g. ["frontal", "left"] - object_truncated: is object truncated, e.g. [true, false] - object_occluded: is object occluded, e.g. [true, false] - object_difficult: is object difficult, e.g. [true, false] - object_group_of: is object a single object or a group of objects - object_depiction: is object a depiction - object_is_crowd: [DEPRECATED, use object_group_of instead] - is the object a single object or a crowd - object_segment_area: the area of the segment. - object_weight: a weight factor for the object's bounding box. - instance_masks: instance segmentation masks. - instance_boundaries: instance boundaries. - instance_classes: Classes for each instance segmentation mask. - detection_class_label: class label in numbers. - detection_bbox_ymin: ymin coordinates of a detection box. - detection_bbox_xmin: xmin coordinates of a detection box. - detection_bbox_ymax: ymax coordinates of a detection box. - detection_bbox_xmax: xmax coordinates of a detection box. - detection_score: detection score for the class label and box. - """ - image_encoded = 'image/encoded' - image_format = 'image/format' # format is reserved keyword - filename = 'image/filename' - channels = 'image/channels' - colorspace = 'image/colorspace' - height = 'image/height' - width = 'image/width' - source_id = 'image/source_id' - image_class_text = 'image/class/text' - image_class_label = 'image/class/label' - object_class_text = 'image/object/class/text' - object_class_label = 'image/object/class/label' - object_bbox_ymin = 'image/object/bbox/ymin' - object_bbox_xmin = 'image/object/bbox/xmin' - object_bbox_ymax = 'image/object/bbox/ymax' - object_bbox_xmax = 'image/object/bbox/xmax' - object_view = 'image/object/view' - object_truncated = 'image/object/truncated' - object_occluded = 'image/object/occluded' - object_difficult = 'image/object/difficult' - object_group_of = 'image/object/group_of' - object_depiction = 'image/object/depiction' - object_is_crowd = 'image/object/is_crowd' - object_segment_area = 'image/object/segment/area' - object_weight = 'image/object/weight' - instance_masks = 'image/segmentation/object' - instance_boundaries = 'image/boundaries/object' - instance_classes = 'image/segmentation/object/class' - detection_class_label = 'image/detection/label' - detection_bbox_ymin = 'image/detection/bbox/ymin' - detection_bbox_xmin = 'image/detection/bbox/xmin' - detection_bbox_ymax = 'image/detection/bbox/ymax' - detection_bbox_xmax = 'image/detection/bbox/xmax' - detection_score = 'image/detection/score' diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/target_assigner.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/target_assigner.py deleted file mode 100644 index 14e66def1..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/target_assigner.py +++ /dev/null @@ -1,458 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Base target assigner module. - -The job of a TargetAssigner is, for a given set of anchors (bounding boxes) and -groundtruth detections (bounding boxes), to assign classification and regression -targets to each anchor as well as weights to each anchor (specifying, e.g., -which anchors should not contribute to training loss). - -It assigns classification/regression targets by performing the following steps: -1) Computing pairwise similarity between anchors and groundtruth boxes using a - provided RegionSimilarity Calculator -2) Computing a matching based on the similarity matrix using a provided Matcher -3) Assigning regression targets based on the matching and a provided BoxCoder -4) Assigning classification targets based on the matching and groundtruth labels - -Note that TargetAssigners only operate on detections from a single -image at a time, so any logic for applying a TargetAssigner to multiple -images must be handled externally. -""" -import tensorflow as tf - -from object_detection.box_coders import faster_rcnn_box_coder -from object_detection.box_coders import mean_stddev_box_coder -from object_detection.core import box_coder as bcoder -from object_detection.core import box_list -from object_detection.core import matcher as mat -from object_detection.core import region_similarity_calculator as sim_calc -from object_detection.core import standard_fields as fields -from object_detection.matchers import argmax_matcher -from object_detection.matchers import bipartite_matcher -from object_detection.utils import shape_utils - - -class TargetAssigner(object): - """Target assigner to compute classification and regression targets.""" - - def __init__(self, similarity_calc, matcher, box_coder, - negative_class_weight=1.0, unmatched_cls_target=None): - """Construct Object Detection Target Assigner. - - Args: - similarity_calc: a RegionSimilarityCalculator - matcher: an object_detection.core.Matcher used to match groundtruth to - anchors. - box_coder: an object_detection.core.BoxCoder used to encode matching - groundtruth boxes with respect to anchors. - negative_class_weight: classification weight to be associated to negative - anchors (default: 1.0). The weight must be in [0., 1.]. - unmatched_cls_target: a float32 tensor with shape [d_1, d_2, ..., d_k] - which is consistent with the classification target for each - anchor (and can be empty for scalar targets). This shape must thus be - compatible with the groundtruth labels that are passed to the "assign" - function (which have shape [num_gt_boxes, d_1, d_2, ..., d_k]). - If set to None, unmatched_cls_target is set to be [0] for each anchor. - - Raises: - ValueError: if similarity_calc is not a RegionSimilarityCalculator or - if matcher is not a Matcher or if box_coder is not a BoxCoder - """ - if not isinstance(similarity_calc, sim_calc.RegionSimilarityCalculator): - raise ValueError('similarity_calc must be a RegionSimilarityCalculator') - if not isinstance(matcher, mat.Matcher): - raise ValueError('matcher must be a Matcher') - if not isinstance(box_coder, bcoder.BoxCoder): - raise ValueError('box_coder must be a BoxCoder') - self._similarity_calc = similarity_calc - self._matcher = matcher - self._box_coder = box_coder - self._negative_class_weight = negative_class_weight - if unmatched_cls_target is None: - self._unmatched_cls_target = tf.constant([0], tf.float32) - else: - self._unmatched_cls_target = unmatched_cls_target - - @property - def box_coder(self): - return self._box_coder - - def assign(self, anchors, groundtruth_boxes, groundtruth_labels=None, - groundtruth_weights=None, **params): - """Assign classification and regression targets to each anchor. - - For a given set of anchors and groundtruth detections, match anchors - to groundtruth_boxes and assign classification and regression targets to - each anchor as well as weights based on the resulting match (specifying, - e.g., which anchors should not contribute to training loss). - - Anchors that are not matched to anything are given a classification target - of self._unmatched_cls_target which can be specified via the constructor. - - Args: - anchors: a BoxList representing N anchors - groundtruth_boxes: a BoxList representing M groundtruth boxes - groundtruth_labels: a tensor of shape [M, d_1, ... d_k] - with labels for each of the ground_truth boxes. The subshape - [d_1, ... d_k] can be empty (corresponding to scalar inputs). When set - to None, groundtruth_labels assumes a binary problem where all - ground_truth boxes get a positive label (of 1). - groundtruth_weights: a float tensor of shape [M] indicating the weight to - assign to all anchors match to a particular groundtruth box. The weights - must be in [0., 1.]. If None, all weights are set to 1. - **params: Additional keyword arguments for specific implementations of - the Matcher. - - Returns: - cls_targets: a float32 tensor with shape [num_anchors, d_1, d_2 ... d_k], - where the subshape [d_1, ..., d_k] is compatible with groundtruth_labels - which has shape [num_gt_boxes, d_1, d_2, ... d_k]. - cls_weights: a float32 tensor with shape [num_anchors] - reg_targets: a float32 tensor with shape [num_anchors, box_code_dimension] - reg_weights: a float32 tensor with shape [num_anchors] - match: a matcher.Match object encoding the match between anchors and - groundtruth boxes, with rows corresponding to groundtruth boxes - and columns corresponding to anchors. - - Raises: - ValueError: if anchors or groundtruth_boxes are not of type - box_list.BoxList - """ - if not isinstance(anchors, box_list.BoxList): - raise ValueError('anchors must be an BoxList') - if not isinstance(groundtruth_boxes, box_list.BoxList): - raise ValueError('groundtruth_boxes must be an BoxList') - - if groundtruth_labels is None: - groundtruth_labels = tf.ones(tf.expand_dims(groundtruth_boxes.num_boxes(), - 0)) - groundtruth_labels = tf.expand_dims(groundtruth_labels, -1) - unmatched_shape_assert = shape_utils.assert_shape_equal( - shape_utils.combined_static_and_dynamic_shape(groundtruth_labels)[1:], - shape_utils.combined_static_and_dynamic_shape( - self._unmatched_cls_target)) - labels_and_box_shapes_assert = shape_utils.assert_shape_equal( - shape_utils.combined_static_and_dynamic_shape( - groundtruth_labels)[:1], - shape_utils.combined_static_and_dynamic_shape( - groundtruth_boxes.get())[:1]) - - if groundtruth_weights is None: - num_gt_boxes = groundtruth_boxes.num_boxes_static() - if not num_gt_boxes: - num_gt_boxes = groundtruth_boxes.num_boxes() - groundtruth_weights = tf.ones([num_gt_boxes], dtype=tf.float32) - with tf.control_dependencies( - [unmatched_shape_assert, labels_and_box_shapes_assert]): - match_quality_matrix = self._similarity_calc.compare(groundtruth_boxes, - anchors) - match = self._matcher.match(match_quality_matrix, **params) - reg_targets = self._create_regression_targets(anchors, - groundtruth_boxes, - match) - cls_targets = self._create_classification_targets(groundtruth_labels, - match) - reg_weights = self._create_regression_weights(match, groundtruth_weights) - cls_weights = self._create_classification_weights(match, - groundtruth_weights) - - num_anchors = anchors.num_boxes_static() - if num_anchors is not None: - reg_targets = self._reset_target_shape(reg_targets, num_anchors) - cls_targets = self._reset_target_shape(cls_targets, num_anchors) - reg_weights = self._reset_target_shape(reg_weights, num_anchors) - cls_weights = self._reset_target_shape(cls_weights, num_anchors) - - return cls_targets, cls_weights, reg_targets, reg_weights, match - - def _reset_target_shape(self, target, num_anchors): - """Sets the static shape of the target. - - Args: - target: the target tensor. Its first dimension will be overwritten. - num_anchors: the number of anchors, which is used to override the target's - first dimension. - - Returns: - A tensor with the shape info filled in. - """ - target_shape = target.get_shape().as_list() - target_shape[0] = num_anchors - target.set_shape(target_shape) - return target - - def _create_regression_targets(self, anchors, groundtruth_boxes, match): - """Returns a regression target for each anchor. - - Args: - anchors: a BoxList representing N anchors - groundtruth_boxes: a BoxList representing M groundtruth_boxes - match: a matcher.Match object - - Returns: - reg_targets: a float32 tensor with shape [N, box_code_dimension] - """ - matched_gt_boxes = match.gather_based_on_match( - groundtruth_boxes.get(), - unmatched_value=tf.zeros(4), - ignored_value=tf.zeros(4)) - matched_gt_boxlist = box_list.BoxList(matched_gt_boxes) - if groundtruth_boxes.has_field(fields.BoxListFields.keypoints): - groundtruth_keypoints = groundtruth_boxes.get_field( - fields.BoxListFields.keypoints) - matched_keypoints = match.gather_based_on_match( - groundtruth_keypoints, - unmatched_value=tf.zeros(groundtruth_keypoints.get_shape()[1:]), - ignored_value=tf.zeros(groundtruth_keypoints.get_shape()[1:])) - matched_gt_boxlist.add_field(fields.BoxListFields.keypoints, - matched_keypoints) - matched_reg_targets = self._box_coder.encode(matched_gt_boxlist, anchors) - match_results_shape = shape_utils.combined_static_and_dynamic_shape( - match.match_results) - - # Zero out the unmatched and ignored regression targets. - unmatched_ignored_reg_targets = tf.tile( - self._default_regression_target(), [match_results_shape[0], 1]) - matched_anchors_mask = match.matched_column_indicator() - reg_targets = tf.where(matched_anchors_mask, - matched_reg_targets, - unmatched_ignored_reg_targets) - return reg_targets - - def _default_regression_target(self): - """Returns the default target for anchors to regress to. - - Default regression targets are set to zero (though in - this implementation what these targets are set to should - not matter as the regression weight of any box set to - regress to the default target is zero). - - Returns: - default_target: a float32 tensor with shape [1, box_code_dimension] - """ - return tf.constant([self._box_coder.code_size*[0]], tf.float32) - - def _create_classification_targets(self, groundtruth_labels, match): - """Create classification targets for each anchor. - - Assign a classification target of for each anchor to the matching - groundtruth label that is provided by match. Anchors that are not matched - to anything are given the target self._unmatched_cls_target - - Args: - groundtruth_labels: a tensor of shape [num_gt_boxes, d_1, ... d_k] - with labels for each of the ground_truth boxes. The subshape - [d_1, ... d_k] can be empty (corresponding to scalar labels). - match: a matcher.Match object that provides a matching between anchors - and groundtruth boxes. - - Returns: - a float32 tensor with shape [num_anchors, d_1, d_2 ... d_k], where the - subshape [d_1, ..., d_k] is compatible with groundtruth_labels which has - shape [num_gt_boxes, d_1, d_2, ... d_k]. - """ - return match.gather_based_on_match( - groundtruth_labels, - unmatched_value=self._unmatched_cls_target, - ignored_value=self._unmatched_cls_target) - - def _create_regression_weights(self, match, groundtruth_weights): - """Set regression weight for each anchor. - - Only positive anchors are set to contribute to the regression loss, so this - method returns a weight of 1 for every positive anchor and 0 for every - negative anchor. - - Args: - match: a matcher.Match object that provides a matching between anchors - and groundtruth boxes. - groundtruth_weights: a float tensor of shape [M] indicating the weight to - assign to all anchors match to a particular groundtruth box. - - Returns: - a float32 tensor with shape [num_anchors] representing regression weights. - """ - return match.gather_based_on_match( - groundtruth_weights, ignored_value=0., unmatched_value=0.) - - def _create_classification_weights(self, - match, - groundtruth_weights): - """Create classification weights for each anchor. - - Positive (matched) anchors are associated with a weight of - positive_class_weight and negative (unmatched) anchors are associated with - a weight of negative_class_weight. When anchors are ignored, weights are set - to zero. By default, both positive/negative weights are set to 1.0, - but they can be adjusted to handle class imbalance (which is almost always - the case in object detection). - - Args: - match: a matcher.Match object that provides a matching between anchors - and groundtruth boxes. - groundtruth_weights: a float tensor of shape [M] indicating the weight to - assign to all anchors match to a particular groundtruth box. - - Returns: - a float32 tensor with shape [num_anchors] representing classification - weights. - """ - return match.gather_based_on_match( - groundtruth_weights, - ignored_value=0., - unmatched_value=self._negative_class_weight) - - def get_box_coder(self): - """Get BoxCoder of this TargetAssigner. - - Returns: - BoxCoder object. - """ - return self._box_coder - - -# TODO(rathodv): This method pulls in all the implementation dependencies into -# core. Therefore its best to have this factory method outside of core. -def create_target_assigner(reference, stage=None, - negative_class_weight=1.0, - unmatched_cls_target=None): - """Factory function for creating standard target assigners. - - Args: - reference: string referencing the type of TargetAssigner. - stage: string denoting stage: {proposal, detection}. - negative_class_weight: classification weight to be associated to negative - anchors (default: 1.0) - unmatched_cls_target: a float32 tensor with shape [d_1, d_2, ..., d_k] - which is consistent with the classification target for each - anchor (and can be empty for scalar targets). This shape must thus be - compatible with the groundtruth labels that are passed to the Assign - function (which have shape [num_gt_boxes, d_1, d_2, ..., d_k]). - If set to None, unmatched_cls_target is set to be 0 for each anchor. - - Returns: - TargetAssigner: desired target assigner. - - Raises: - ValueError: if combination reference+stage is invalid. - """ - if reference == 'Multibox' and stage == 'proposal': - similarity_calc = sim_calc.NegSqDistSimilarity() - matcher = bipartite_matcher.GreedyBipartiteMatcher() - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() - - elif reference == 'FasterRCNN' and stage == 'proposal': - similarity_calc = sim_calc.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.7, - unmatched_threshold=0.3, - force_match_for_each_row=True) - box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder( - scale_factors=[10.0, 10.0, 5.0, 5.0]) - - elif reference == 'FasterRCNN' and stage == 'detection': - similarity_calc = sim_calc.IouSimilarity() - # Uses all proposals with IOU < 0.5 as candidate negatives. - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - negatives_lower_than_unmatched=True) - box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder( - scale_factors=[10.0, 10.0, 5.0, 5.0]) - - elif reference == 'FastRCNN': - similarity_calc = sim_calc.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.1, - force_match_for_each_row=False, - negatives_lower_than_unmatched=False) - box_coder = faster_rcnn_box_coder.FasterRcnnBoxCoder() - - else: - raise ValueError('No valid combination of reference and stage.') - - return TargetAssigner(similarity_calc, matcher, box_coder, - negative_class_weight=negative_class_weight, - unmatched_cls_target=unmatched_cls_target) - - -def batch_assign_targets(target_assigner, - anchors_batch, - gt_box_batch, - gt_class_targets_batch, - gt_weights_batch=None): - """Batched assignment of classification and regression targets. - - Args: - target_assigner: a target assigner. - anchors_batch: BoxList representing N box anchors or list of BoxList objects - with length batch_size representing anchor sets. - gt_box_batch: a list of BoxList objects with length batch_size - representing groundtruth boxes for each image in the batch - gt_class_targets_batch: a list of tensors with length batch_size, where - each tensor has shape [num_gt_boxes_i, classification_target_size] and - num_gt_boxes_i is the number of boxes in the ith boxlist of - gt_box_batch. - gt_weights_batch: A list of 1-D tf.float32 tensors of shape - [num_boxes] containing weights for groundtruth boxes. - - Returns: - batch_cls_targets: a tensor with shape [batch_size, num_anchors, - num_classes], - batch_cls_weights: a tensor with shape [batch_size, num_anchors], - batch_reg_targets: a tensor with shape [batch_size, num_anchors, - box_code_dimension] - batch_reg_weights: a tensor with shape [batch_size, num_anchors], - match_list: a list of matcher.Match objects encoding the match between - anchors and groundtruth boxes for each image of the batch, - with rows of the Match objects corresponding to groundtruth boxes - and columns corresponding to anchors. - Raises: - ValueError: if input list lengths are inconsistent, i.e., - batch_size == len(gt_box_batch) == len(gt_class_targets_batch) - and batch_size == len(anchors_batch) unless anchors_batch is a single - BoxList. - """ - if not isinstance(anchors_batch, list): - anchors_batch = len(gt_box_batch) * [anchors_batch] - if not all( - isinstance(anchors, box_list.BoxList) for anchors in anchors_batch): - raise ValueError('anchors_batch must be a BoxList or list of BoxLists.') - if not (len(anchors_batch) - == len(gt_box_batch) - == len(gt_class_targets_batch)): - raise ValueError('batch size incompatible with lengths of anchors_batch, ' - 'gt_box_batch and gt_class_targets_batch.') - cls_targets_list = [] - cls_weights_list = [] - reg_targets_list = [] - reg_weights_list = [] - match_list = [] - if gt_weights_batch is None: - gt_weights_batch = [None] * len(gt_class_targets_batch) - for anchors, gt_boxes, gt_class_targets, gt_weights in zip( - anchors_batch, gt_box_batch, gt_class_targets_batch, gt_weights_batch): - (cls_targets, cls_weights, reg_targets, - reg_weights, match) = target_assigner.assign( - anchors, gt_boxes, gt_class_targets, gt_weights) - cls_targets_list.append(cls_targets) - cls_weights_list.append(cls_weights) - reg_targets_list.append(reg_targets) - reg_weights_list.append(reg_weights) - match_list.append(match) - batch_cls_targets = tf.stack(cls_targets_list) - batch_cls_weights = tf.stack(cls_weights_list) - batch_reg_targets = tf.stack(reg_targets_list) - batch_reg_weights = tf.stack(reg_weights_list) - return (batch_cls_targets, batch_cls_weights, batch_reg_targets, - batch_reg_weights, match_list) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/target_assigner_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/core/target_assigner_test.py deleted file mode 100644 index 34a35b643..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/core/target_assigner_test.py +++ /dev/null @@ -1,827 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.core.target_assigner.""" -import numpy as np -import tensorflow as tf - -from object_detection.box_coders import keypoint_box_coder -from object_detection.box_coders import mean_stddev_box_coder -from object_detection.core import box_list -from object_detection.core import region_similarity_calculator -from object_detection.core import standard_fields as fields -from object_detection.core import target_assigner as targetassigner -from object_detection.matchers import argmax_matcher -from object_detection.matchers import bipartite_matcher -from object_detection.utils import test_case - - -class TargetAssignerTest(test_case.TestCase): - - def test_assign_agnostic(self): - def graph_fn(anchor_means, groundtruth_box_corners): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, unmatched_cls_target=None) - anchors_boxlist = box_list.BoxList(anchor_means) - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - result = target_assigner.assign(anchors_boxlist, groundtruth_boxlist) - (cls_targets, cls_weights, reg_targets, reg_weights, _) = result - return (cls_targets, cls_weights, reg_targets, reg_weights) - - anchor_means = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 0.8], - [0, 0.5, .5, 1.0]], dtype=np.float32) - groundtruth_box_corners = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.9, 0.9]], - dtype=np.float32) - exp_cls_targets = [[1], [1], [0]] - exp_cls_weights = [1, 1, 1] - exp_reg_targets = [[0, 0, 0, 0], - [0, 0, -1, 1], - [0, 0, 0, 0]] - exp_reg_weights = [1, 1, 0] - - (cls_targets_out, - cls_weights_out, reg_targets_out, reg_weights_out) = self.execute( - graph_fn, [anchor_means, groundtruth_box_corners]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - self.assertEquals(cls_targets_out.dtype, np.float32) - self.assertEquals(cls_weights_out.dtype, np.float32) - self.assertEquals(reg_targets_out.dtype, np.float32) - self.assertEquals(reg_weights_out.dtype, np.float32) - - def test_assign_class_agnostic_with_ignored_matches(self): - # Note: test is very similar to above. The third box matched with an IOU - # of 0.35, which is between the matched and unmatched threshold. This means - # That like above the expected classification targets are [1, 1, 0]. - # Unlike above, the third target is ignored and therefore expected - # classification weights are [1, 1, 0]. - def graph_fn(anchor_means, groundtruth_box_corners): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.3) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, unmatched_cls_target=None) - anchors_boxlist = box_list.BoxList(anchor_means) - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - result = target_assigner.assign(anchors_boxlist, groundtruth_boxlist) - (cls_targets, cls_weights, reg_targets, reg_weights, _) = result - return (cls_targets, cls_weights, reg_targets, reg_weights) - - anchor_means = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 0.8], - [0.0, 0.5, .9, 1.0]], dtype=np.float32) - groundtruth_box_corners = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.9, 0.9]], dtype=np.float32) - exp_cls_targets = [[1], [1], [0]] - exp_cls_weights = [1, 1, 0] - exp_reg_targets = [[0, 0, 0, 0], - [0, 0, -1, 1], - [0, 0, 0, 0]] - exp_reg_weights = [1, 1, 0] - (cls_targets_out, - cls_weights_out, reg_targets_out, reg_weights_out) = self.execute( - graph_fn, [anchor_means, groundtruth_box_corners]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - self.assertEquals(cls_targets_out.dtype, np.float32) - self.assertEquals(cls_weights_out.dtype, np.float32) - self.assertEquals(reg_targets_out.dtype, np.float32) - self.assertEquals(reg_weights_out.dtype, np.float32) - - def test_assign_agnostic_with_keypoints(self): - def graph_fn(anchor_means, groundtruth_box_corners, - groundtruth_keypoints): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = keypoint_box_coder.KeypointBoxCoder( - num_keypoints=6, scale_factors=[10.0, 10.0, 5.0, 5.0]) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, unmatched_cls_target=None) - anchors_boxlist = box_list.BoxList(anchor_means) - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - groundtruth_boxlist.add_field(fields.BoxListFields.keypoints, - groundtruth_keypoints) - result = target_assigner.assign(anchors_boxlist, groundtruth_boxlist) - (cls_targets, cls_weights, reg_targets, reg_weights, _) = result - return (cls_targets, cls_weights, reg_targets, reg_weights) - - anchor_means = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 1.0], - [0.0, 0.5, .9, 1.0]], dtype=np.float32) - groundtruth_box_corners = np.array([[0.0, 0.0, 0.5, 0.5], - [0.45, 0.45, 0.95, 0.95]], - dtype=np.float32) - groundtruth_keypoints = np.array( - [[[0.1, 0.2], [0.1, 0.3], [0.2, 0.2], [0.2, 0.2], [0.1, 0.1], [0.9, 0]], - [[0, 0.3], [0.2, 0.4], [0.5, 0.6], [0, 0.6], [0.8, 0.2], [0.2, 0.4]]], - dtype=np.float32) - exp_cls_targets = [[1], [1], [0]] - exp_cls_weights = [1, 1, 1] - exp_reg_targets = [[0, 0, 0, 0, -3, -1, -3, 1, -1, -1, -1, -1, -3, -3, 13, - -5], - [-1, -1, 0, 0, -15, -9, -11, -7, -5, -3, -15, -3, 1, -11, - -11, -7], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] - exp_reg_weights = [1, 1, 0] - (cls_targets_out, cls_weights_out, reg_targets_out, - reg_weights_out) = self.execute(graph_fn, [anchor_means, - groundtruth_box_corners, - groundtruth_keypoints]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - self.assertEquals(cls_targets_out.dtype, np.float32) - self.assertEquals(cls_weights_out.dtype, np.float32) - self.assertEquals(reg_targets_out.dtype, np.float32) - self.assertEquals(reg_weights_out.dtype, np.float32) - - def test_assign_class_agnostic_with_keypoints_and_ignored_matches(self): - # Note: test is very similar to above. The third box matched with an IOU - # of 0.35, which is between the matched and unmatched threshold. This means - # That like above the expected classification targets are [1, 1, 0]. - # Unlike above, the third target is ignored and therefore expected - # classification weights are [1, 1, 0]. - def graph_fn(anchor_means, groundtruth_box_corners, - groundtruth_keypoints): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = keypoint_box_coder.KeypointBoxCoder( - num_keypoints=6, scale_factors=[10.0, 10.0, 5.0, 5.0]) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, unmatched_cls_target=None) - anchors_boxlist = box_list.BoxList(anchor_means) - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - groundtruth_boxlist.add_field(fields.BoxListFields.keypoints, - groundtruth_keypoints) - result = target_assigner.assign(anchors_boxlist, groundtruth_boxlist) - (cls_targets, cls_weights, reg_targets, reg_weights, _) = result - return (cls_targets, cls_weights, reg_targets, reg_weights) - - anchor_means = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 1.0], - [0.0, 0.5, .9, 1.0]], dtype=np.float32) - groundtruth_box_corners = np.array([[0.0, 0.0, 0.5, 0.5], - [0.45, 0.45, 0.95, 0.95]], - dtype=np.float32) - groundtruth_keypoints = np.array( - [[[0.1, 0.2], [0.1, 0.3], [0.2, 0.2], [0.2, 0.2], [0.1, 0.1], [0.9, 0]], - [[0, 0.3], [0.2, 0.4], [0.5, 0.6], [0, 0.6], [0.8, 0.2], [0.2, 0.4]]], - dtype=np.float32) - exp_cls_targets = [[1], [1], [0]] - exp_cls_weights = [1, 1, 1] - exp_reg_targets = [[0, 0, 0, 0, -3, -1, -3, 1, -1, -1, -1, -1, -3, -3, 13, - -5], - [-1, -1, 0, 0, -15, -9, -11, -7, -5, -3, -15, -3, 1, -11, - -11, -7], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] - exp_reg_weights = [1, 1, 0] - (cls_targets_out, cls_weights_out, reg_targets_out, - reg_weights_out) = self.execute(graph_fn, [anchor_means, - groundtruth_box_corners, - groundtruth_keypoints]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - self.assertEquals(cls_targets_out.dtype, np.float32) - self.assertEquals(cls_weights_out.dtype, np.float32) - self.assertEquals(reg_targets_out.dtype, np.float32) - self.assertEquals(reg_weights_out.dtype, np.float32) - - def test_assign_multiclass(self): - - def graph_fn(anchor_means, groundtruth_box_corners, groundtruth_labels): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - unmatched_cls_target = tf.constant([1, 0, 0, 0, 0, 0, 0], tf.float32) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=unmatched_cls_target) - - anchors_boxlist = box_list.BoxList(anchor_means) - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - result = target_assigner.assign(anchors_boxlist, groundtruth_boxlist, - groundtruth_labels) - (cls_targets, cls_weights, reg_targets, reg_weights, _) = result - return (cls_targets, cls_weights, reg_targets, reg_weights) - - anchor_means = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 0.8], - [0, 0.5, .5, 1.0], - [.75, 0, 1.0, .25]], dtype=np.float32) - groundtruth_box_corners = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.9, 0.9], - [.75, 0, .95, .27]], dtype=np.float32) - groundtruth_labels = np.array([[0, 1, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 1, 0], - [0, 0, 0, 1, 0, 0, 0]], dtype=np.float32) - - exp_cls_targets = [[0, 1, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 1, 0], - [1, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 1, 0, 0, 0]] - exp_cls_weights = [1, 1, 1, 1] - exp_reg_targets = [[0, 0, 0, 0], - [0, 0, -1, 1], - [0, 0, 0, 0], - [0, 0, -.5, .2]] - exp_reg_weights = [1, 1, 0, 1] - - (cls_targets_out, - cls_weights_out, reg_targets_out, reg_weights_out) = self.execute( - graph_fn, [anchor_means, groundtruth_box_corners, groundtruth_labels]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - self.assertEquals(cls_targets_out.dtype, np.float32) - self.assertEquals(cls_weights_out.dtype, np.float32) - self.assertEquals(reg_targets_out.dtype, np.float32) - self.assertEquals(reg_weights_out.dtype, np.float32) - - def test_assign_multiclass_with_groundtruth_weights(self): - - def graph_fn(anchor_means, groundtruth_box_corners, groundtruth_labels, - groundtruth_weights): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - unmatched_cls_target = tf.constant([1, 0, 0, 0, 0, 0, 0], tf.float32) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=unmatched_cls_target) - - anchors_boxlist = box_list.BoxList(anchor_means) - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - result = target_assigner.assign(anchors_boxlist, groundtruth_boxlist, - groundtruth_labels, - groundtruth_weights) - (_, cls_weights, _, reg_weights, _) = result - return (cls_weights, reg_weights) - - anchor_means = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 0.8], - [0, 0.5, .5, 1.0], - [.75, 0, 1.0, .25]], dtype=np.float32) - groundtruth_box_corners = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.9, 0.9], - [.75, 0, .95, .27]], dtype=np.float32) - groundtruth_labels = np.array([[0, 1, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 1, 0], - [0, 0, 0, 1, 0, 0, 0]], dtype=np.float32) - groundtruth_weights = np.array([0.3, 0., 0.5], dtype=np.float32) - - exp_cls_weights = [0.3, 0., 1, 0.5] # background class gets weight of 1. - exp_reg_weights = [0.3, 0., 0., 0.5] # background class gets weight of 0. - - (cls_weights_out, reg_weights_out) = self.execute(graph_fn, [ - anchor_means, groundtruth_box_corners, groundtruth_labels, - groundtruth_weights - ]) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_weights_out, exp_reg_weights) - - def test_assign_multidimensional_class_targets(self): - - def graph_fn(anchor_means, groundtruth_box_corners, groundtruth_labels): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - - unmatched_cls_target = tf.constant([[0, 0], [0, 0]], tf.float32) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=unmatched_cls_target) - - anchors_boxlist = box_list.BoxList(anchor_means) - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - result = target_assigner.assign(anchors_boxlist, groundtruth_boxlist, - groundtruth_labels) - (cls_targets, cls_weights, reg_targets, reg_weights, _) = result - return (cls_targets, cls_weights, reg_targets, reg_weights) - - anchor_means = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 0.8], - [0, 0.5, .5, 1.0], - [.75, 0, 1.0, .25]], dtype=np.float32) - groundtruth_box_corners = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.9, 0.9], - [.75, 0, .95, .27]], dtype=np.float32) - - groundtruth_labels = np.array([[[0, 1], [1, 0]], - [[1, 0], [0, 1]], - [[0, 1], [1, .5]]], np.float32) - - exp_cls_targets = [[[0, 1], [1, 0]], - [[1, 0], [0, 1]], - [[0, 0], [0, 0]], - [[0, 1], [1, .5]]] - exp_cls_weights = [1, 1, 1, 1] - exp_reg_targets = [[0, 0, 0, 0], - [0, 0, -1, 1], - [0, 0, 0, 0], - [0, 0, -.5, .2]] - exp_reg_weights = [1, 1, 0, 1] - (cls_targets_out, - cls_weights_out, reg_targets_out, reg_weights_out) = self.execute( - graph_fn, [anchor_means, groundtruth_box_corners, groundtruth_labels]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - self.assertEquals(cls_targets_out.dtype, np.float32) - self.assertEquals(cls_weights_out.dtype, np.float32) - self.assertEquals(reg_targets_out.dtype, np.float32) - self.assertEquals(reg_weights_out.dtype, np.float32) - - def test_assign_empty_groundtruth(self): - - def graph_fn(anchor_means, groundtruth_box_corners, groundtruth_labels): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - unmatched_cls_target = tf.constant([0, 0, 0], tf.float32) - anchors_boxlist = box_list.BoxList(anchor_means) - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=unmatched_cls_target) - result = target_assigner.assign(anchors_boxlist, groundtruth_boxlist, - groundtruth_labels) - (cls_targets, cls_weights, reg_targets, reg_weights, _) = result - return (cls_targets, cls_weights, reg_targets, reg_weights) - - groundtruth_box_corners = np.zeros((0, 4), dtype=np.float32) - groundtruth_labels = np.zeros((0, 3), dtype=np.float32) - anchor_means = np.array([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 0.8], - [0, 0.5, .5, 1.0], - [.75, 0, 1.0, .25]], - dtype=np.float32) - exp_cls_targets = [[0, 0, 0], - [0, 0, 0], - [0, 0, 0], - [0, 0, 0]] - exp_cls_weights = [1, 1, 1, 1] - exp_reg_targets = [[0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0]] - exp_reg_weights = [0, 0, 0, 0] - (cls_targets_out, - cls_weights_out, reg_targets_out, reg_weights_out) = self.execute( - graph_fn, [anchor_means, groundtruth_box_corners, groundtruth_labels]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - self.assertEquals(cls_targets_out.dtype, np.float32) - self.assertEquals(cls_weights_out.dtype, np.float32) - self.assertEquals(reg_targets_out.dtype, np.float32) - self.assertEquals(reg_weights_out.dtype, np.float32) - - def test_raises_error_on_incompatible_groundtruth_boxes_and_labels(self): - similarity_calc = region_similarity_calculator.NegSqDistSimilarity() - matcher = bipartite_matcher.GreedyBipartiteMatcher() - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder() - unmatched_cls_target = tf.constant([1, 0, 0, 0, 0, 0, 0], tf.float32) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=unmatched_cls_target) - - prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 0.8], - [0, 0.5, .5, 1.0], - [.75, 0, 1.0, .25]]) - priors = box_list.BoxList(prior_means) - - box_corners = [[0.0, 0.0, 0.5, 0.5], - [0.0, 0.0, 0.5, 0.8], - [0.5, 0.5, 0.9, 0.9], - [.75, 0, .95, .27]] - boxes = box_list.BoxList(tf.constant(box_corners)) - - groundtruth_labels = tf.constant([[0, 1, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 1, 0], - [0, 0, 0, 1, 0, 0, 0]], tf.float32) - with self.assertRaisesRegexp(ValueError, 'Unequal shapes'): - target_assigner.assign(priors, boxes, groundtruth_labels, - num_valid_rows=3) - - def test_raises_error_on_invalid_groundtruth_labels(self): - similarity_calc = region_similarity_calculator.NegSqDistSimilarity() - matcher = bipartite_matcher.GreedyBipartiteMatcher() - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=1.0) - unmatched_cls_target = tf.constant([[0, 0], [0, 0], [0, 0]], tf.float32) - target_assigner = targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=unmatched_cls_target) - - prior_means = tf.constant([[0.0, 0.0, 0.5, 0.5]]) - priors = box_list.BoxList(prior_means) - - box_corners = [[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.9, 0.9], - [.75, 0, .95, .27]] - boxes = box_list.BoxList(tf.constant(box_corners)) - groundtruth_labels = tf.constant([[[0, 1], [1, 0]]], tf.float32) - - with self.assertRaises(ValueError): - target_assigner.assign(priors, boxes, groundtruth_labels, - num_valid_rows=3) - - -class BatchTargetAssignerTest(test_case.TestCase): - - def _get_agnostic_target_assigner(self): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - return targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=None) - - def _get_multi_class_target_assigner(self, num_classes): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - unmatched_cls_target = tf.constant([1] + num_classes * [0], tf.float32) - return targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=unmatched_cls_target) - - def _get_multi_dimensional_target_assigner(self, target_dimensions): - similarity_calc = region_similarity_calculator.IouSimilarity() - matcher = argmax_matcher.ArgMaxMatcher(matched_threshold=0.5, - unmatched_threshold=0.5) - box_coder = mean_stddev_box_coder.MeanStddevBoxCoder(stddev=0.1) - unmatched_cls_target = tf.constant(np.zeros(target_dimensions), - tf.float32) - return targetassigner.TargetAssigner( - similarity_calc, matcher, box_coder, - unmatched_cls_target=unmatched_cls_target) - - def test_batch_assign_targets(self): - - def graph_fn(anchor_means, groundtruth_boxlist1, groundtruth_boxlist2): - box_list1 = box_list.BoxList(groundtruth_boxlist1) - box_list2 = box_list.BoxList(groundtruth_boxlist2) - gt_box_batch = [box_list1, box_list2] - gt_class_targets = [None, None] - anchors_boxlist = box_list.BoxList(anchor_means) - agnostic_target_assigner = self._get_agnostic_target_assigner() - (cls_targets, cls_weights, reg_targets, reg_weights, - _) = targetassigner.batch_assign_targets( - agnostic_target_assigner, anchors_boxlist, gt_box_batch, - gt_class_targets) - return (cls_targets, cls_weights, reg_targets, reg_weights) - - groundtruth_boxlist1 = np.array([[0., 0., 0.2, 0.2]], dtype=np.float32) - groundtruth_boxlist2 = np.array([[0, 0.25123152, 1, 1], - [0.015789, 0.0985, 0.55789, 0.3842]], - dtype=np.float32) - anchor_means = np.array([[0, 0, .25, .25], - [0, .25, 1, 1], - [0, .1, .5, .5], - [.75, .75, 1, 1]], dtype=np.float32) - - exp_reg_targets = [[[0, 0, -0.5, -0.5], - [0, 0, 0, 0], - [0, 0, 0, 0,], - [0, 0, 0, 0,],], - [[0, 0, 0, 0,], - [0, 0.01231521, 0, 0], - [0.15789001, -0.01500003, 0.57889998, -1.15799987], - [0, 0, 0, 0]]] - exp_cls_weights = [[1, 1, 1, 1], - [1, 1, 1, 1]] - exp_cls_targets = [[[1], [0], [0], [0]], - [[0], [1], [1], [0]]] - exp_reg_weights = [[1, 0, 0, 0], - [0, 1, 1, 0]] - - (cls_targets_out, - cls_weights_out, reg_targets_out, reg_weights_out) = self.execute( - graph_fn, [anchor_means, groundtruth_boxlist1, groundtruth_boxlist2]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - - def test_batch_assign_multiclass_targets(self): - - def graph_fn(anchor_means, groundtruth_boxlist1, groundtruth_boxlist2, - class_targets1, class_targets2): - box_list1 = box_list.BoxList(groundtruth_boxlist1) - box_list2 = box_list.BoxList(groundtruth_boxlist2) - gt_box_batch = [box_list1, box_list2] - gt_class_targets = [class_targets1, class_targets2] - anchors_boxlist = box_list.BoxList(anchor_means) - multiclass_target_assigner = self._get_multi_class_target_assigner( - num_classes=3) - (cls_targets, cls_weights, reg_targets, reg_weights, - _) = targetassigner.batch_assign_targets( - multiclass_target_assigner, anchors_boxlist, gt_box_batch, - gt_class_targets) - return (cls_targets, cls_weights, reg_targets, reg_weights) - - groundtruth_boxlist1 = np.array([[0., 0., 0.2, 0.2]], dtype=np.float32) - groundtruth_boxlist2 = np.array([[0, 0.25123152, 1, 1], - [0.015789, 0.0985, 0.55789, 0.3842]], - dtype=np.float32) - class_targets1 = np.array([[0, 1, 0, 0]], dtype=np.float32) - class_targets2 = np.array([[0, 0, 0, 1], - [0, 0, 1, 0]], dtype=np.float32) - - anchor_means = np.array([[0, 0, .25, .25], - [0, .25, 1, 1], - [0, .1, .5, .5], - [.75, .75, 1, 1]], dtype=np.float32) - - exp_reg_targets = [[[0, 0, -0.5, -0.5], - [0, 0, 0, 0], - [0, 0, 0, 0,], - [0, 0, 0, 0,],], - [[0, 0, 0, 0,], - [0, 0.01231521, 0, 0], - [0.15789001, -0.01500003, 0.57889998, -1.15799987], - [0, 0, 0, 0]]] - exp_cls_weights = [[1, 1, 1, 1], - [1, 1, 1, 1]] - exp_cls_targets = [[[0, 1, 0, 0], - [1, 0, 0, 0], - [1, 0, 0, 0], - [1, 0, 0, 0]], - [[1, 0, 0, 0], - [0, 0, 0, 1], - [0, 0, 1, 0], - [1, 0, 0, 0]]] - exp_reg_weights = [[1, 0, 0, 0], - [0, 1, 1, 0]] - - (cls_targets_out, cls_weights_out, reg_targets_out, - reg_weights_out) = self.execute(graph_fn, [ - anchor_means, groundtruth_boxlist1, groundtruth_boxlist2, - class_targets1, class_targets2 - ]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - - def test_batch_assign_multiclass_targets_with_padded_groundtruth(self): - - def graph_fn(anchor_means, groundtruth_boxlist1, groundtruth_boxlist2, - class_targets1, class_targets2, groundtruth_weights1, - groundtruth_weights2): - box_list1 = box_list.BoxList(groundtruth_boxlist1) - box_list2 = box_list.BoxList(groundtruth_boxlist2) - gt_box_batch = [box_list1, box_list2] - gt_class_targets = [class_targets1, class_targets2] - gt_weights = [groundtruth_weights1, groundtruth_weights2] - anchors_boxlist = box_list.BoxList(anchor_means) - multiclass_target_assigner = self._get_multi_class_target_assigner( - num_classes=3) - (cls_targets, cls_weights, reg_targets, reg_weights, - _) = targetassigner.batch_assign_targets( - multiclass_target_assigner, anchors_boxlist, gt_box_batch, - gt_class_targets, gt_weights) - return (cls_targets, cls_weights, reg_targets, reg_weights) - - groundtruth_boxlist1 = np.array([[0., 0., 0.2, 0.2], - [0., 0., 0., 0.]], dtype=np.float32) - groundtruth_weights1 = np.array([1, 0], dtype=np.float32) - groundtruth_boxlist2 = np.array([[0, 0.25123152, 1, 1], - [0.015789, 0.0985, 0.55789, 0.3842], - [0, 0, 0, 0]], - dtype=np.float32) - groundtruth_weights2 = np.array([1, 1, 0], dtype=np.float32) - class_targets1 = np.array([[0, 1, 0, 0], [0, 0, 0, 0]], dtype=np.float32) - class_targets2 = np.array([[0, 0, 0, 1], - [0, 0, 1, 0], - [0, 0, 0, 0]], dtype=np.float32) - - anchor_means = np.array([[0, 0, .25, .25], - [0, .25, 1, 1], - [0, .1, .5, .5], - [.75, .75, 1, 1]], dtype=np.float32) - - exp_reg_targets = [[[0, 0, -0.5, -0.5], - [0, 0, 0, 0], - [0, 0, 0, 0,], - [0, 0, 0, 0,],], - [[0, 0, 0, 0,], - [0, 0.01231521, 0, 0], - [0.15789001, -0.01500003, 0.57889998, -1.15799987], - [0, 0, 0, 0]]] - exp_cls_weights = [[1, 1, 1, 1], - [1, 1, 1, 1]] - exp_cls_targets = [[[0, 1, 0, 0], - [1, 0, 0, 0], - [1, 0, 0, 0], - [1, 0, 0, 0]], - [[1, 0, 0, 0], - [0, 0, 0, 1], - [0, 0, 1, 0], - [1, 0, 0, 0]]] - exp_reg_weights = [[1, 0, 0, 0], - [0, 1, 1, 0]] - - (cls_targets_out, cls_weights_out, reg_targets_out, - reg_weights_out) = self.execute(graph_fn, [ - anchor_means, groundtruth_boxlist1, groundtruth_boxlist2, - class_targets1, class_targets2, groundtruth_weights1, - groundtruth_weights2 - ]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - - def test_batch_assign_multidimensional_targets(self): - - def graph_fn(anchor_means, groundtruth_boxlist1, groundtruth_boxlist2, - class_targets1, class_targets2): - box_list1 = box_list.BoxList(groundtruth_boxlist1) - box_list2 = box_list.BoxList(groundtruth_boxlist2) - gt_box_batch = [box_list1, box_list2] - gt_class_targets = [class_targets1, class_targets2] - anchors_boxlist = box_list.BoxList(anchor_means) - multiclass_target_assigner = self._get_multi_dimensional_target_assigner( - target_dimensions=(2, 3)) - (cls_targets, cls_weights, reg_targets, reg_weights, - _) = targetassigner.batch_assign_targets( - multiclass_target_assigner, anchors_boxlist, gt_box_batch, - gt_class_targets) - return (cls_targets, cls_weights, reg_targets, reg_weights) - - groundtruth_boxlist1 = np.array([[0., 0., 0.2, 0.2]], dtype=np.float32) - groundtruth_boxlist2 = np.array([[0, 0.25123152, 1, 1], - [0.015789, 0.0985, 0.55789, 0.3842]], - dtype=np.float32) - class_targets1 = np.array([[0, 1, 0, 0]], dtype=np.float32) - class_targets2 = np.array([[0, 0, 0, 1], - [0, 0, 1, 0]], dtype=np.float32) - class_targets1 = np.array([[[0, 1, 1], - [1, 1, 0]]], dtype=np.float32) - class_targets2 = np.array([[[0, 1, 1], - [1, 1, 0]], - [[0, 0, 1], - [0, 0, 1]]], dtype=np.float32) - - anchor_means = np.array([[0, 0, .25, .25], - [0, .25, 1, 1], - [0, .1, .5, .5], - [.75, .75, 1, 1]], dtype=np.float32) - - exp_reg_targets = [[[0, 0, -0.5, -0.5], - [0, 0, 0, 0], - [0, 0, 0, 0,], - [0, 0, 0, 0,],], - [[0, 0, 0, 0,], - [0, 0.01231521, 0, 0], - [0.15789001, -0.01500003, 0.57889998, -1.15799987], - [0, 0, 0, 0]]] - exp_cls_weights = [[1, 1, 1, 1], - [1, 1, 1, 1]] - exp_cls_targets = [[[[0., 1., 1.], - [1., 1., 0.]], - [[0., 0., 0.], - [0., 0., 0.]], - [[0., 0., 0.], - [0., 0., 0.]], - [[0., 0., 0.], - [0., 0., 0.]]], - [[[0., 0., 0.], - [0., 0., 0.]], - [[0., 1., 1.], - [1., 1., 0.]], - [[0., 0., 1.], - [0., 0., 1.]], - [[0., 0., 0.], - [0., 0., 0.]]]] - exp_reg_weights = [[1, 0, 0, 0], - [0, 1, 1, 0]] - - (cls_targets_out, cls_weights_out, reg_targets_out, - reg_weights_out) = self.execute(graph_fn, [ - anchor_means, groundtruth_boxlist1, groundtruth_boxlist2, - class_targets1, class_targets2 - ]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - - def test_batch_assign_empty_groundtruth(self): - - def graph_fn(anchor_means, groundtruth_box_corners, gt_class_targets): - groundtruth_boxlist = box_list.BoxList(groundtruth_box_corners) - gt_box_batch = [groundtruth_boxlist] - gt_class_targets_batch = [gt_class_targets] - anchors_boxlist = box_list.BoxList(anchor_means) - - multiclass_target_assigner = self._get_multi_class_target_assigner( - num_classes=3) - - (cls_targets, cls_weights, reg_targets, reg_weights, - _) = targetassigner.batch_assign_targets( - multiclass_target_assigner, anchors_boxlist, - gt_box_batch, gt_class_targets_batch) - return (cls_targets, cls_weights, reg_targets, reg_weights) - - groundtruth_box_corners = np.zeros((0, 4), dtype=np.float32) - anchor_means = np.array([[0, 0, .25, .25], - [0, .25, 1, 1]], dtype=np.float32) - exp_reg_targets = [[[0, 0, 0, 0], - [0, 0, 0, 0]]] - exp_cls_weights = [[1, 1]] - exp_cls_targets = [[[1, 0, 0, 0], - [1, 0, 0, 0]]] - exp_reg_weights = [[0, 0]] - num_classes = 3 - pad = 1 - gt_class_targets = np.zeros((0, num_classes + pad), dtype=np.float32) - - (cls_targets_out, - cls_weights_out, reg_targets_out, reg_weights_out) = self.execute( - graph_fn, [anchor_means, groundtruth_box_corners, gt_class_targets]) - self.assertAllClose(cls_targets_out, exp_cls_targets) - self.assertAllClose(cls_weights_out, exp_cls_weights) - self.assertAllClose(reg_targets_out, exp_reg_targets) - self.assertAllClose(reg_weights_out, exp_reg_weights) - - -class CreateTargetAssignerTest(tf.test.TestCase): - - def test_create_target_assigner(self): - """Tests that named constructor gives working target assigners. - - TODO(rathodv): Make this test more general. - """ - corners = [[0.0, 0.0, 1.0, 1.0]] - groundtruth = box_list.BoxList(tf.constant(corners)) - - priors = box_list.BoxList(tf.constant(corners)) - multibox_ta = (targetassigner - .create_target_assigner('Multibox', stage='proposal')) - multibox_ta.assign(priors, groundtruth) - # No tests on output, as that may vary arbitrarily as new target assigners - # are added. As long as it is constructed correctly and runs without errors, - # tests on the individual assigners cover correctness of the assignments. - - anchors = box_list.BoxList(tf.constant(corners)) - faster_rcnn_proposals_ta = (targetassigner - .create_target_assigner('FasterRCNN', - stage='proposal')) - faster_rcnn_proposals_ta.assign(anchors, groundtruth) - - fast_rcnn_ta = (targetassigner - .create_target_assigner('FastRCNN')) - fast_rcnn_ta.assign(anchors, groundtruth) - - faster_rcnn_detection_ta = (targetassigner - .create_target_assigner('FasterRCNN', - stage='detection')) - faster_rcnn_detection_ta.assign(anchors, groundtruth) - - with self.assertRaises(ValueError): - targetassigner.create_target_assigner('InvalidDetector', - stage='invalid_stage') - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/ava_label_map_v2.1.pbtxt b/research/mlperf_object_detection/Mask_RCNN/object_detection/data/ava_label_map_v2.1.pbtxt deleted file mode 100644 index 5e2c48568..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/ava_label_map_v2.1.pbtxt +++ /dev/null @@ -1,240 +0,0 @@ -item { - name: "bend/bow (at the waist)" - id: 1 -} -item { - name: "crouch/kneel" - id: 3 -} -item { - name: "dance" - id: 4 -} -item { - name: "fall down" - id: 5 -} -item { - name: "get up" - id: 6 -} -item { - name: "jump/leap" - id: 7 -} -item { - name: "lie/sleep" - id: 8 -} -item { - name: "martial art" - id: 9 -} -item { - name: "run/jog" - id: 10 -} -item { - name: "sit" - id: 11 -} -item { - name: "stand" - id: 12 -} -item { - name: "swim" - id: 13 -} -item { - name: "walk" - id: 14 -} -item { - name: "answer phone" - id: 15 -} -item { - name: "carry/hold (an object)" - id: 17 -} -item { - name: "climb (e.g., a mountain)" - id: 20 -} -item { - name: "close (e.g., a door, a box)" - id: 22 -} -item { - name: "cut" - id: 24 -} -item { - name: "dress/put on clothing" - id: 26 -} -item { - name: "drink" - id: 27 -} -item { - name: "drive (e.g., a car, a truck)" - id: 28 -} -item { - name: "eat" - id: 29 -} -item { - name: "enter" - id: 30 -} -item { - name: "hit (an object)" - id: 34 -} -item { - name: "lift/pick up" - id: 36 -} -item { - name: "listen (e.g., to music)" - id: 37 -} -item { - name: "open (e.g., a window, a car door)" - id: 38 -} -item { - name: "play musical instrument" - id: 41 -} -item { - name: "point to (an object)" - id: 43 -} -item { - name: "pull (an object)" - id: 45 -} -item { - name: "push (an object)" - id: 46 -} -item { - name: "put down" - id: 47 -} -item { - name: "read" - id: 48 -} -item { - name: "ride (e.g., a bike, a car, a horse)" - id: 49 -} -item { - name: "sail boat" - id: 51 -} -item { - name: "shoot" - id: 52 -} -item { - name: "smoke" - id: 54 -} -item { - name: "take a photo" - id: 56 -} -item { - name: "text on/look at a cellphone" - id: 57 -} -item { - name: "throw" - id: 58 -} -item { - name: "touch (an object)" - id: 59 -} -item { - name: "turn (e.g., a screwdriver)" - id: 60 -} -item { - name: "watch (e.g., TV)" - id: 61 -} -item { - name: "work on a computer" - id: 62 -} -item { - name: "write" - id: 63 -} -item { - name: "fight/hit (a person)" - id: 64 -} -item { - name: "give/serve (an object) to (a person)" - id: 65 -} -item { - name: "grab (a person)" - id: 66 -} -item { - name: "hand clap" - id: 67 -} -item { - name: "hand shake" - id: 68 -} -item { - name: "hand wave" - id: 69 -} -item { - name: "hug (a person)" - id: 70 -} -item { - name: "kiss (a person)" - id: 72 -} -item { - name: "lift (a person)" - id: 73 -} -item { - name: "listen to (a person)" - id: 74 -} -item { - name: "push (another person)" - id: 76 -} -item { - name: "sing to (e.g., self, a person, a group)" - id: 77 -} -item { - name: "take (an object) from (a person)" - id: 78 -} -item { - name: "talk to (e.g., self, a person, a group)" - id: 79 -} -item { - name: "watch (a person)" - id: 80 -} diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/kitti_label_map.pbtxt b/research/mlperf_object_detection/Mask_RCNN/object_detection/data/kitti_label_map.pbtxt deleted file mode 100644 index 0afcc6936..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/kitti_label_map.pbtxt +++ /dev/null @@ -1,9 +0,0 @@ -item { - id: 1 - name: 'car' -} - -item { - id: 2 - name: 'pedestrian' -} diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/mscoco_label_map.pbtxt b/research/mlperf_object_detection/Mask_RCNN/object_detection/data/mscoco_label_map.pbtxt deleted file mode 100644 index 1f4872bd0..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/mscoco_label_map.pbtxt +++ /dev/null @@ -1,400 +0,0 @@ -item { - name: "/m/01g317" - id: 1 - display_name: "person" -} -item { - name: "/m/0199g" - id: 2 - display_name: "bicycle" -} -item { - name: "/m/0k4j" - id: 3 - display_name: "car" -} -item { - name: "/m/04_sv" - id: 4 - display_name: "motorcycle" -} -item { - name: "/m/05czz6l" - id: 5 - display_name: "airplane" -} -item { - name: "/m/01bjv" - id: 6 - display_name: "bus" -} -item { - name: "/m/07jdr" - id: 7 - display_name: "train" -} -item { - name: "/m/07r04" - id: 8 - display_name: "truck" -} -item { - name: "/m/019jd" - id: 9 - display_name: "boat" -} -item { - name: "/m/015qff" - id: 10 - display_name: "traffic light" -} -item { - name: "/m/01pns0" - id: 11 - display_name: "fire hydrant" -} -item { - name: "/m/02pv19" - id: 13 - display_name: "stop sign" -} -item { - name: "/m/015qbp" - id: 14 - display_name: "parking meter" -} -item { - name: "/m/0cvnqh" - id: 15 - display_name: "bench" -} -item { - name: "/m/015p6" - id: 16 - display_name: "bird" -} -item { - name: "/m/01yrx" - id: 17 - display_name: "cat" -} -item { - name: "/m/0bt9lr" - id: 18 - display_name: "dog" -} -item { - name: "/m/03k3r" - id: 19 - display_name: "horse" -} -item { - name: "/m/07bgp" - id: 20 - display_name: "sheep" -} -item { - name: "/m/01xq0k1" - id: 21 - display_name: "cow" -} -item { - name: "/m/0bwd_0j" - id: 22 - display_name: "elephant" -} -item { - name: "/m/01dws" - id: 23 - display_name: "bear" -} -item { - name: "/m/0898b" - id: 24 - display_name: "zebra" -} -item { - name: "/m/03bk1" - id: 25 - display_name: "giraffe" -} -item { - name: "/m/01940j" - id: 27 - display_name: "backpack" -} -item { - name: "/m/0hnnb" - id: 28 - display_name: "umbrella" -} -item { - name: "/m/080hkjn" - id: 31 - display_name: "handbag" -} -item { - name: "/m/01rkbr" - id: 32 - display_name: "tie" -} -item { - name: "/m/01s55n" - id: 33 - display_name: "suitcase" -} -item { - name: "/m/02wmf" - id: 34 - display_name: "frisbee" -} -item { - name: "/m/071p9" - id: 35 - display_name: "skis" -} -item { - name: "/m/06__v" - id: 36 - display_name: "snowboard" -} -item { - name: "/m/018xm" - id: 37 - display_name: "sports ball" -} -item { - name: "/m/02zt3" - id: 38 - display_name: "kite" -} -item { - name: "/m/03g8mr" - id: 39 - display_name: "baseball bat" -} -item { - name: "/m/03grzl" - id: 40 - display_name: "baseball glove" -} -item { - name: "/m/06_fw" - id: 41 - display_name: "skateboard" -} -item { - name: "/m/019w40" - id: 42 - display_name: "surfboard" -} -item { - name: "/m/0dv9c" - id: 43 - display_name: "tennis racket" -} -item { - name: "/m/04dr76w" - id: 44 - display_name: "bottle" -} -item { - name: "/m/09tvcd" - id: 46 - display_name: "wine glass" -} -item { - name: "/m/08gqpm" - id: 47 - display_name: "cup" -} -item { - name: "/m/0dt3t" - id: 48 - display_name: "fork" -} -item { - name: "/m/04ctx" - id: 49 - display_name: "knife" -} -item { - name: "/m/0cmx8" - id: 50 - display_name: "spoon" -} -item { - name: "/m/04kkgm" - id: 51 - display_name: "bowl" -} -item { - name: "/m/09qck" - id: 52 - display_name: "banana" -} -item { - name: "/m/014j1m" - id: 53 - display_name: "apple" -} -item { - name: "/m/0l515" - id: 54 - display_name: "sandwich" -} -item { - name: "/m/0cyhj_" - id: 55 - display_name: "orange" -} -item { - name: "/m/0hkxq" - id: 56 - display_name: "broccoli" -} -item { - name: "/m/0fj52s" - id: 57 - display_name: "carrot" -} -item { - name: "/m/01b9xk" - id: 58 - display_name: "hot dog" -} -item { - name: "/m/0663v" - id: 59 - display_name: "pizza" -} -item { - name: "/m/0jy4k" - id: 60 - display_name: "donut" -} -item { - name: "/m/0fszt" - id: 61 - display_name: "cake" -} -item { - name: "/m/01mzpv" - id: 62 - display_name: "chair" -} -item { - name: "/m/02crq1" - id: 63 - display_name: "couch" -} -item { - name: "/m/03fp41" - id: 64 - display_name: "potted plant" -} -item { - name: "/m/03ssj5" - id: 65 - display_name: "bed" -} -item { - name: "/m/04bcr3" - id: 67 - display_name: "dining table" -} -item { - name: "/m/09g1w" - id: 70 - display_name: "toilet" -} -item { - name: "/m/07c52" - id: 72 - display_name: "tv" -} -item { - name: "/m/01c648" - id: 73 - display_name: "laptop" -} -item { - name: "/m/020lf" - id: 74 - display_name: "mouse" -} -item { - name: "/m/0qjjc" - id: 75 - display_name: "remote" -} -item { - name: "/m/01m2v" - id: 76 - display_name: "keyboard" -} -item { - name: "/m/050k8" - id: 77 - display_name: "cell phone" -} -item { - name: "/m/0fx9l" - id: 78 - display_name: "microwave" -} -item { - name: "/m/029bxz" - id: 79 - display_name: "oven" -} -item { - name: "/m/01k6s3" - id: 80 - display_name: "toaster" -} -item { - name: "/m/0130jx" - id: 81 - display_name: "sink" -} -item { - name: "/m/040b_t" - id: 82 - display_name: "refrigerator" -} -item { - name: "/m/0bt_c3" - id: 84 - display_name: "book" -} -item { - name: "/m/01x3z" - id: 85 - display_name: "clock" -} -item { - name: "/m/02s195" - id: 86 - display_name: "vase" -} -item { - name: "/m/01lsmm" - id: 87 - display_name: "scissors" -} -item { - name: "/m/0kmg4" - id: 88 - display_name: "teddy bear" -} -item { - name: "/m/03wvsk" - id: 89 - display_name: "hair drier" -} -item { - name: "/m/012xff" - id: 90 - display_name: "toothbrush" -} diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/oid_bbox_trainable_label_map.pbtxt b/research/mlperf_object_detection/Mask_RCNN/object_detection/data/oid_bbox_trainable_label_map.pbtxt deleted file mode 100644 index 863e4f31d..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/oid_bbox_trainable_label_map.pbtxt +++ /dev/null @@ -1,2725 +0,0 @@ -item { - name: "/m/01g317" - id: 1 - display_name: "Person" -} -item { - name: "/m/09j2d" - id: 2 - display_name: "Clothing" -} -item { - name: "/m/04yx4" - id: 3 - display_name: "Man" -} -item { - name: "/m/0dzct" - id: 4 - display_name: "Face" -} -item { - name: "/m/07j7r" - id: 5 - display_name: "Tree" -} -item { - name: "/m/05s2s" - id: 6 - display_name: "Plant" -} -item { - name: "/m/03bt1vf" - id: 7 - display_name: "Woman" -} -item { - name: "/m/07yv9" - id: 8 - display_name: "Vehicle" -} -item { - name: "/m/0cgh4" - id: 9 - display_name: "Building" -} -item { - name: "/m/01prls" - id: 10 - display_name: "Land vehicle" -} -item { - name: "/m/09j5n" - id: 11 - display_name: "Footwear" -} -item { - name: "/m/05r655" - id: 12 - display_name: "Girl" -} -item { - name: "/m/0jbk" - id: 13 - display_name: "Animal" -} -item { - name: "/m/0k4j" - id: 14 - display_name: "Car" -} -item { - name: "/m/02wbm" - id: 15 - display_name: "Food" -} -item { - name: "/m/083wq" - id: 16 - display_name: "Wheel" -} -item { - name: "/m/0c9ph5" - id: 17 - display_name: "Flower" -} -item { - name: "/m/0c_jw" - id: 18 - display_name: "Furniture" -} -item { - name: "/m/0d4v4" - id: 19 - display_name: "Window" -} -item { - name: "/m/03jm5" - id: 20 - display_name: "House" -} -item { - name: "/m/01bl7v" - id: 21 - display_name: "Boy" -} -item { - name: "/m/0463sg" - id: 22 - display_name: "Fashion accessory" -} -item { - name: "/m/04bcr3" - id: 23 - display_name: "Table" -} -item { - name: "/m/0jyfg" - id: 24 - display_name: "Glasses" -} -item { - name: "/m/01xyhv" - id: 25 - display_name: "Suit" -} -item { - name: "/m/08dz3q" - id: 26 - display_name: "Auto part" -} -item { - name: "/m/015p6" - id: 27 - display_name: "Bird" -} -item { - name: "/m/05y5lj" - id: 28 - display_name: "Sports equipment" -} -item { - name: "/m/01d40f" - id: 29 - display_name: "Dress" -} -item { - name: "/m/0bt9lr" - id: 30 - display_name: "Dog" -} -item { - name: "/m/01lrl" - id: 31 - display_name: "Carnivore" -} -item { - name: "/m/02p0tk3" - id: 32 - display_name: "Human body" -} -item { - name: "/m/0fly7" - id: 33 - display_name: "Jeans" -} -item { - name: "/m/04szw" - id: 34 - display_name: "Musical instrument" -} -item { - name: "/m/0271t" - id: 35 - display_name: "Drink" -} -item { - name: "/m/019jd" - id: 36 - display_name: "Boat" -} -item { - name: "/m/03q69" - id: 37 - display_name: "Hair" -} -item { - name: "/m/0h9mv" - id: 38 - display_name: "Tire" -} -item { - name: "/m/04hgtk" - id: 39 - display_name: "Head" -} -item { - name: "/m/01yrx" - id: 40 - display_name: "Cat" -} -item { - name: "/m/01rzcn" - id: 41 - display_name: "Watercraft" -} -item { - name: "/m/01mzpv" - id: 42 - display_name: "Chair" -} -item { - name: "/m/0199g" - id: 43 - display_name: "Bike" -} -item { - name: "/m/01fdzj" - id: 44 - display_name: "Tower" -} -item { - name: "/m/04rky" - id: 45 - display_name: "Mammal" -} -item { - name: "/m/079cl" - id: 46 - display_name: "Skyscraper" -} -item { - name: "/m/0dzf4" - id: 47 - display_name: "Arm" -} -item { - name: "/m/0138tl" - id: 48 - display_name: "Toy" -} -item { - name: "/m/06msq" - id: 49 - display_name: "Sculpture" -} -item { - name: "/m/03xxp" - id: 50 - display_name: "Invertebrate" -} -item { - name: "/m/0hg7b" - id: 51 - display_name: "Microphone" -} -item { - name: "/m/01n5jq" - id: 52 - display_name: "Poster" -} -item { - name: "/m/03vt0" - id: 53 - display_name: "Insect" -} -item { - name: "/m/0342h" - id: 54 - display_name: "Guitar" -} -item { - name: "/m/0k0pj" - id: 55 - display_name: "Nose" -} -item { - name: "/m/02dl1y" - id: 56 - display_name: "Hat" -} -item { - name: "/m/04brg2" - id: 57 - display_name: "Tableware" -} -item { - name: "/m/02dgv" - id: 58 - display_name: "Door" -} -item { - name: "/m/01bqk0" - id: 59 - display_name: "Bicycle wheel" -} -item { - name: "/m/017ftj" - id: 60 - display_name: "Sunglasses" -} -item { - name: "/m/052lwg6" - id: 61 - display_name: "Baked goods" -} -item { - name: "/m/014sv8" - id: 62 - display_name: "Eye" -} -item { - name: "/m/0270h" - id: 63 - display_name: "Dessert" -} -item { - name: "/m/0283dt1" - id: 64 - display_name: "Mouth" -} -item { - name: "/m/0k5j" - id: 65 - display_name: "Aircraft" -} -item { - name: "/m/0cmf2" - id: 66 - display_name: "Airplane" -} -item { - name: "/m/07jdr" - id: 67 - display_name: "Train" -} -item { - name: "/m/032b3c" - id: 68 - display_name: "Jacket" -} -item { - name: "/m/033rq4" - id: 69 - display_name: "Street light" -} -item { - name: "/m/0k65p" - id: 70 - display_name: "Hand" -} -item { - name: "/m/01ww8y" - id: 71 - display_name: "Snack" -} -item { - name: "/m/0zvk5" - id: 72 - display_name: "Helmet" -} -item { - name: "/m/07mhn" - id: 73 - display_name: "Trousers" -} -item { - name: "/m/04dr76w" - id: 74 - display_name: "Bottle" -} -item { - name: "/m/03fp41" - id: 75 - display_name: "Houseplant" -} -item { - name: "/m/03k3r" - id: 76 - display_name: "Horse" -} -item { - name: "/m/01y9k5" - id: 77 - display_name: "Desk" -} -item { - name: "/m/0cdl1" - id: 78 - display_name: "Palm tree" -} -item { - name: "/m/0f4s2w" - id: 79 - display_name: "Vegetable" -} -item { - name: "/m/02xwb" - id: 80 - display_name: "Fruit" -} -item { - name: "/m/035r7c" - id: 81 - display_name: "Leg" -} -item { - name: "/m/0bt_c3" - id: 82 - display_name: "Book" -} -item { - name: "/m/01_bhs" - id: 83 - display_name: "Fast food" -} -item { - name: "/m/01599" - id: 84 - display_name: "Beer" -} -item { - name: "/m/03120" - id: 85 - display_name: "Flag" -} -item { - name: "/m/026t6" - id: 86 - display_name: "Drum" -} -item { - name: "/m/01bjv" - id: 87 - display_name: "Bus" -} -item { - name: "/m/07r04" - id: 88 - display_name: "Truck" -} -item { - name: "/m/018xm" - id: 89 - display_name: "Ball" -} -item { - name: "/m/01rkbr" - id: 90 - display_name: "Tie" -} -item { - name: "/m/0fm3zh" - id: 91 - display_name: "Flowerpot" -} -item { - name: "/m/02_n6y" - id: 92 - display_name: "Goggles" -} -item { - name: "/m/04_sv" - id: 93 - display_name: "Motorcycle" -} -item { - name: "/m/06z37_" - id: 94 - display_name: "Picture frame" -} -item { - name: "/m/01bfm9" - id: 95 - display_name: "Shorts" -} -item { - name: "/m/0h8mhzd" - id: 96 - display_name: "Sports uniform" -} -item { - name: "/m/0d_2m" - id: 97 - display_name: "Moths and butterflies" -} -item { - name: "/m/0gjbg72" - id: 98 - display_name: "Shelf" -} -item { - name: "/m/01n4qj" - id: 99 - display_name: "Shirt" -} -item { - name: "/m/0ch_cf" - id: 100 - display_name: "Fish" -} -item { - name: "/m/06m11" - id: 101 - display_name: "Rose" -} -item { - name: "/m/01jfm_" - id: 102 - display_name: "Licence plate" -} -item { - name: "/m/02crq1" - id: 103 - display_name: "Couch" -} -item { - name: "/m/083kb" - id: 104 - display_name: "Weapon" -} -item { - name: "/m/01c648" - id: 105 - display_name: "Laptop" -} -item { - name: "/m/09tvcd" - id: 106 - display_name: "Wine glass" -} -item { - name: "/m/0h2r6" - id: 107 - display_name: "Van" -} -item { - name: "/m/081qc" - id: 108 - display_name: "Wine" -} -item { - name: "/m/09ddx" - id: 109 - display_name: "Duck" -} -item { - name: "/m/03p3bw" - id: 110 - display_name: "Bicycle helmet" -} -item { - name: "/m/0cyf8" - id: 111 - display_name: "Butterfly" -} -item { - name: "/m/0b_rs" - id: 112 - display_name: "Swimming pool" -} -item { - name: "/m/039xj_" - id: 113 - display_name: "Ear" -} -item { - name: "/m/021sj1" - id: 114 - display_name: "Office" -} -item { - name: "/m/0dv5r" - id: 115 - display_name: "Camera" -} -item { - name: "/m/01lynh" - id: 116 - display_name: "Stairs" -} -item { - name: "/m/06bt6" - id: 117 - display_name: "Reptile" -} -item { - name: "/m/01226z" - id: 118 - display_name: "Football" -} -item { - name: "/m/0fszt" - id: 119 - display_name: "Cake" -} -item { - name: "/m/050k8" - id: 120 - display_name: "Mobile phone" -} -item { - name: "/m/02wbtzl" - id: 121 - display_name: "Sun hat" -} -item { - name: "/m/02p5f1q" - id: 122 - display_name: "Coffee cup" -} -item { - name: "/m/025nd" - id: 123 - display_name: "Christmas tree" -} -item { - name: "/m/02522" - id: 124 - display_name: "Computer monitor" -} -item { - name: "/m/09ct_" - id: 125 - display_name: "Helicopter" -} -item { - name: "/m/0cvnqh" - id: 126 - display_name: "Bench" -} -item { - name: "/m/0d5gx" - id: 127 - display_name: "Castle" -} -item { - name: "/m/01xygc" - id: 128 - display_name: "Coat" -} -item { - name: "/m/04m6gz" - id: 129 - display_name: "Porch" -} -item { - name: "/m/01gkx_" - id: 130 - display_name: "Swimwear" -} -item { - name: "/m/01s105" - id: 131 - display_name: "Cabinetry" -} -item { - name: "/m/01j61q" - id: 132 - display_name: "Tent" -} -item { - name: "/m/0hnnb" - id: 133 - display_name: "Umbrella" -} -item { - name: "/m/01j51" - id: 134 - display_name: "Balloon" -} -item { - name: "/m/01knjb" - id: 135 - display_name: "Billboard" -} -item { - name: "/m/03__z0" - id: 136 - display_name: "Bookcase" -} -item { - name: "/m/01m2v" - id: 137 - display_name: "Computer keyboard" -} -item { - name: "/m/0167gd" - id: 138 - display_name: "Doll" -} -item { - name: "/m/0284d" - id: 139 - display_name: "Dairy" -} -item { - name: "/m/03ssj5" - id: 140 - display_name: "Bed" -} -item { - name: "/m/02fq_6" - id: 141 - display_name: "Fedora" -} -item { - name: "/m/06nwz" - id: 142 - display_name: "Seafood" -} -item { - name: "/m/0220r2" - id: 143 - display_name: "Fountain" -} -item { - name: "/m/01mqdt" - id: 144 - display_name: "Traffic sign" -} -item { - name: "/m/0268lbt" - id: 145 - display_name: "Hiking equipment" -} -item { - name: "/m/07c52" - id: 146 - display_name: "Television" -} -item { - name: "/m/0grw1" - id: 147 - display_name: "Salad" -} -item { - name: "/m/01h3n" - id: 148 - display_name: "Bee" -} -item { - name: "/m/078n6m" - id: 149 - display_name: "Coffee table" -} -item { - name: "/m/01xq0k1" - id: 150 - display_name: "Cattle" -} -item { - name: "/m/0gd2v" - id: 151 - display_name: "Marine mammal" -} -item { - name: "/m/0dbvp" - id: 152 - display_name: "Goose" -} -item { - name: "/m/03rszm" - id: 153 - display_name: "Curtain" -} -item { - name: "/m/0h8n5zk" - id: 154 - display_name: "Kitchen & dining room table" -} -item { - name: "/m/019dx1" - id: 155 - display_name: "Home appliance" -} -item { - name: "/m/03hl4l9" - id: 156 - display_name: "Marine invertebrates" -} -item { - name: "/m/0b3fp9" - id: 157 - display_name: "Countertop" -} -item { - name: "/m/02rdsp" - id: 158 - display_name: "Office supplies" -} -item { - name: "/m/0hf58v5" - id: 159 - display_name: "Luggage and bags" -} -item { - name: "/m/04h7h" - id: 160 - display_name: "Lighthouse" -} -item { - name: "/m/024g6" - id: 161 - display_name: "Cocktail" -} -item { - name: "/m/0cffdh" - id: 162 - display_name: "Maple" -} -item { - name: "/m/03q5c7" - id: 163 - display_name: "Saucer" -} -item { - name: "/m/014y4n" - id: 164 - display_name: "Paddle" -} -item { - name: "/m/01yx86" - id: 165 - display_name: "Bronze sculpture" -} -item { - name: "/m/020jm" - id: 166 - display_name: "Beetle" -} -item { - name: "/m/025dyy" - id: 167 - display_name: "Box" -} -item { - name: "/m/01llwg" - id: 168 - display_name: "Necklace" -} -item { - name: "/m/08pbxl" - id: 169 - display_name: "Monkey" -} -item { - name: "/m/02d9qx" - id: 170 - display_name: "Whiteboard" -} -item { - name: "/m/02pkr5" - id: 171 - display_name: "Plumbing fixture" -} -item { - name: "/m/0h99cwc" - id: 172 - display_name: "Kitchen appliance" -} -item { - name: "/m/050gv4" - id: 173 - display_name: "Plate" -} -item { - name: "/m/02vqfm" - id: 174 - display_name: "Coffee" -} -item { - name: "/m/09kx5" - id: 175 - display_name: "Deer" -} -item { - name: "/m/019w40" - id: 176 - display_name: "Surfboard" -} -item { - name: "/m/09dzg" - id: 177 - display_name: "Turtle" -} -item { - name: "/m/07k1x" - id: 178 - display_name: "Tool" -} -item { - name: "/m/080hkjn" - id: 179 - display_name: "Handbag" -} -item { - name: "/m/07qxg_" - id: 180 - display_name: "Football helmet" -} -item { - name: "/m/0ph39" - id: 181 - display_name: "Canoe" -} -item { - name: "/m/018p4k" - id: 182 - display_name: "Cart" -} -item { - name: "/m/02h19r" - id: 183 - display_name: "Scarf" -} -item { - name: "/m/015h_t" - id: 184 - display_name: "Beard" -} -item { - name: "/m/0fqfqc" - id: 185 - display_name: "Drawer" -} -item { - name: "/m/025rp__" - id: 186 - display_name: "Cowboy hat" -} -item { - name: "/m/01x3z" - id: 187 - display_name: "Clock" -} -item { - name: "/m/0crjs" - id: 188 - display_name: "Convenience store" -} -item { - name: "/m/0l515" - id: 189 - display_name: "Sandwich" -} -item { - name: "/m/015qff" - id: 190 - display_name: "Traffic light" -} -item { - name: "/m/09kmb" - id: 191 - display_name: "Spider" -} -item { - name: "/m/09728" - id: 192 - display_name: "Bread" -} -item { - name: "/m/071qp" - id: 193 - display_name: "Squirrel" -} -item { - name: "/m/02s195" - id: 194 - display_name: "Vase" -} -item { - name: "/m/06c54" - id: 195 - display_name: "Rifle" -} -item { - name: "/m/01xqw" - id: 196 - display_name: "Cello" -} -item { - name: "/m/05zsy" - id: 197 - display_name: "Pumpkin" -} -item { - name: "/m/0bwd_0j" - id: 198 - display_name: "Elephant" -} -item { - name: "/m/04m9y" - id: 199 - display_name: "Lizard" -} -item { - name: "/m/052sf" - id: 200 - display_name: "Mushroom" -} -item { - name: "/m/03grzl" - id: 201 - display_name: "Baseball glove" -} -item { - name: "/m/01z1kdw" - id: 202 - display_name: "Juice" -} -item { - name: "/m/02wv6h6" - id: 203 - display_name: "Skirt" -} -item { - name: "/m/016m2d" - id: 204 - display_name: "Skull" -} -item { - name: "/m/0dtln" - id: 205 - display_name: "Lamp" -} -item { - name: "/m/057cc" - id: 206 - display_name: "Musical keyboard" -} -item { - name: "/m/06k2mb" - id: 207 - display_name: "High heels" -} -item { - name: "/m/0f6wt" - id: 208 - display_name: "Falcon" -} -item { - name: "/m/0cxn2" - id: 209 - display_name: "Ice cream" -} -item { - name: "/m/02jvh9" - id: 210 - display_name: "Mug" -} -item { - name: "/m/0gjkl" - id: 211 - display_name: "Watch" -} -item { - name: "/m/01b638" - id: 212 - display_name: "Boot" -} -item { - name: "/m/071p9" - id: 213 - display_name: "Ski" -} -item { - name: "/m/0pg52" - id: 214 - display_name: "Taxi" -} -item { - name: "/m/0ftb8" - id: 215 - display_name: "Sunflower" -} -item { - name: "/m/0hnyx" - id: 216 - display_name: "Pastry" -} -item { - name: "/m/02jz0l" - id: 217 - display_name: "Tap" -} -item { - name: "/m/04kkgm" - id: 218 - display_name: "Bowl" -} -item { - name: "/m/0174n1" - id: 219 - display_name: "Glove" -} -item { - name: "/m/0gv1x" - id: 220 - display_name: "Parrot" -} -item { - name: "/m/09csl" - id: 221 - display_name: "Eagle" -} -item { - name: "/m/02jnhm" - id: 222 - display_name: "Tin can" -} -item { - name: "/m/099ssp" - id: 223 - display_name: "Platter" -} -item { - name: "/m/03nfch" - id: 224 - display_name: "Sandal" -} -item { - name: "/m/07y_7" - id: 225 - display_name: "Violin" -} -item { - name: "/m/05z6w" - id: 226 - display_name: "Penguin" -} -item { - name: "/m/03m3pdh" - id: 227 - display_name: "Sofa bed" -} -item { - name: "/m/09ld4" - id: 228 - display_name: "Frog" -} -item { - name: "/m/09b5t" - id: 229 - display_name: "Chicken" -} -item { - name: "/m/054xkw" - id: 230 - display_name: "Lifejacket" -} -item { - name: "/m/0130jx" - id: 231 - display_name: "Sink" -} -item { - name: "/m/07fbm7" - id: 232 - display_name: "Strawberry" -} -item { - name: "/m/01dws" - id: 233 - display_name: "Bear" -} -item { - name: "/m/01tcjp" - id: 234 - display_name: "Muffin" -} -item { - name: "/m/0dftk" - id: 235 - display_name: "Swan" -} -item { - name: "/m/0c06p" - id: 236 - display_name: "Candle" -} -item { - name: "/m/034c16" - id: 237 - display_name: "Pillow" -} -item { - name: "/m/09d5_" - id: 238 - display_name: "Owl" -} -item { - name: "/m/03hlz0c" - id: 239 - display_name: "Kitchen utensil" -} -item { - name: "/m/0ft9s" - id: 240 - display_name: "Dragonfly" -} -item { - name: "/m/011k07" - id: 241 - display_name: "Tortoise" -} -item { - name: "/m/054_l" - id: 242 - display_name: "Mirror" -} -item { - name: "/m/0jqgx" - id: 243 - display_name: "Lily" -} -item { - name: "/m/0663v" - id: 244 - display_name: "Pizza" -} -item { - name: "/m/0242l" - id: 245 - display_name: "Coin" -} -item { - name: "/m/014trl" - id: 246 - display_name: "Cosmetics" -} -item { - name: "/m/05r5c" - id: 247 - display_name: "Piano" -} -item { - name: "/m/07j87" - id: 248 - display_name: "Tomato" -} -item { - name: "/m/05kyg_" - id: 249 - display_name: "Chest of drawers" -} -item { - name: "/m/0kmg4" - id: 250 - display_name: "Teddy bear" -} -item { - name: "/m/07cmd" - id: 251 - display_name: "Tank" -} -item { - name: "/m/0dv77" - id: 252 - display_name: "Squash" -} -item { - name: "/m/096mb" - id: 253 - display_name: "Lion" -} -item { - name: "/m/01gmv2" - id: 254 - display_name: "Brassiere" -} -item { - name: "/m/07bgp" - id: 255 - display_name: "Sheep" -} -item { - name: "/m/0cmx8" - id: 256 - display_name: "Spoon" -} -item { - name: "/m/029tx" - id: 257 - display_name: "Dinosaur" -} -item { - name: "/m/073bxn" - id: 258 - display_name: "Tripod" -} -item { - name: "/m/0bh9flk" - id: 259 - display_name: "Tablet computer" -} -item { - name: "/m/06mf6" - id: 260 - display_name: "Rabbit" -} -item { - name: "/m/06_fw" - id: 261 - display_name: "Skateboard" -} -item { - name: "/m/078jl" - id: 262 - display_name: "Snake" -} -item { - name: "/m/0fbdv" - id: 263 - display_name: "Shellfish" -} -item { - name: "/m/0h23m" - id: 264 - display_name: "Sparrow" -} -item { - name: "/m/014j1m" - id: 265 - display_name: "Apple" -} -item { - name: "/m/03fwl" - id: 266 - display_name: "Goat" -} -item { - name: "/m/02y6n" - id: 267 - display_name: "French fries" -} -item { - name: "/m/06c7f7" - id: 268 - display_name: "Lipstick" -} -item { - name: "/m/026qbn5" - id: 269 - display_name: "studio couch" -} -item { - name: "/m/0cdn1" - id: 270 - display_name: "Hamburger" -} -item { - name: "/m/07clx" - id: 271 - display_name: "Tea" -} -item { - name: "/m/07cx4" - id: 272 - display_name: "Telephone" -} -item { - name: "/m/03g8mr" - id: 273 - display_name: "Baseball bat" -} -item { - name: "/m/0cnyhnx" - id: 274 - display_name: "Bull" -} -item { - name: "/m/01b7fy" - id: 275 - display_name: "Headphones" -} -item { - name: "/m/04gth" - id: 276 - display_name: "Lavender" -} -item { - name: "/m/0cyfs" - id: 277 - display_name: "Parachute" -} -item { - name: "/m/021mn" - id: 278 - display_name: "Cookie" -} -item { - name: "/m/07dm6" - id: 279 - display_name: "Tiger" -} -item { - name: "/m/0k1tl" - id: 280 - display_name: "Pen" -} -item { - name: "/m/0dv9c" - id: 281 - display_name: "Racket" -} -item { - name: "/m/0dt3t" - id: 282 - display_name: "Fork" -} -item { - name: "/m/04yqq2" - id: 283 - display_name: "Bust" -} -item { - name: "/m/01cmb2" - id: 284 - display_name: "Miniskirt" -} -item { - name: "/m/0gd36" - id: 285 - display_name: "Sea lion" -} -item { - name: "/m/033cnk" - id: 286 - display_name: "Egg" -} -item { - name: "/m/06ncr" - id: 287 - display_name: "Saxophone" -} -item { - name: "/m/03bk1" - id: 288 - display_name: "Giraffe" -} -item { - name: "/m/0bjyj5" - id: 289 - display_name: "Waste container" -} -item { - name: "/m/06__v" - id: 290 - display_name: "Snowboard" -} -item { - name: "/m/0qmmr" - id: 291 - display_name: "Wheelchair" -} -item { - name: "/m/01xgg_" - id: 292 - display_name: "Medical equipment" -} -item { - name: "/m/0czz2" - id: 293 - display_name: "Antelope" -} -item { - name: "/m/02l8p9" - id: 294 - display_name: "Harbor seal" -} -item { - name: "/m/09g1w" - id: 295 - display_name: "Toilet" -} -item { - name: "/m/0ll1f78" - id: 296 - display_name: "Shrimp" -} -item { - name: "/m/0cyhj_" - id: 297 - display_name: "Orange" -} -item { - name: "/m/0642b4" - id: 298 - display_name: "Cupboard" -} -item { - name: "/m/0h8mzrc" - id: 299 - display_name: "Wall clock" -} -item { - name: "/m/068zj" - id: 300 - display_name: "Pig" -} -item { - name: "/m/02z51p" - id: 301 - display_name: "Nightstand" -} -item { - name: "/m/0h8nr_l" - id: 302 - display_name: "Bathroom accessory" -} -item { - name: "/m/0388q" - id: 303 - display_name: "Grape" -} -item { - name: "/m/02hj4" - id: 304 - display_name: "Dolphin" -} -item { - name: "/m/01jfsr" - id: 305 - display_name: "Lantern" -} -item { - name: "/m/07gql" - id: 306 - display_name: "Trumpet" -} -item { - name: "/m/0h8my_4" - id: 307 - display_name: "Tennis racket" -} -item { - name: "/m/0n28_" - id: 308 - display_name: "Crab" -} -item { - name: "/m/0120dh" - id: 309 - display_name: "Sea turtle" -} -item { - name: "/m/020kz" - id: 310 - display_name: "Cannon" -} -item { - name: "/m/0mkg" - id: 311 - display_name: "Accordion" -} -item { - name: "/m/03c7gz" - id: 312 - display_name: "Door handle" -} -item { - name: "/m/09k_b" - id: 313 - display_name: "Lemon" -} -item { - name: "/m/031n1" - id: 314 - display_name: "Foot" -} -item { - name: "/m/04rmv" - id: 315 - display_name: "Mouse" -} -item { - name: "/m/084rd" - id: 316 - display_name: "Wok" -} -item { - name: "/m/02rgn06" - id: 317 - display_name: "Volleyball" -} -item { - name: "/m/05z55" - id: 318 - display_name: "Pasta" -} -item { - name: "/m/01r546" - id: 319 - display_name: "Earrings" -} -item { - name: "/m/09qck" - id: 320 - display_name: "Banana" -} -item { - name: "/m/012w5l" - id: 321 - display_name: "Ladder" -} -item { - name: "/m/01940j" - id: 322 - display_name: "Backpack" -} -item { - name: "/m/09f_2" - id: 323 - display_name: "Crocodile" -} -item { - name: "/m/02p3w7d" - id: 324 - display_name: "Roller skates" -} -item { - name: "/m/057p5t" - id: 325 - display_name: "Scoreboard" -} -item { - name: "/m/0d8zb" - id: 326 - display_name: "Jellyfish" -} -item { - name: "/m/01nq26" - id: 327 - display_name: "Sock" -} -item { - name: "/m/01x_v" - id: 328 - display_name: "Camel" -} -item { - name: "/m/05gqfk" - id: 329 - display_name: "Plastic bag" -} -item { - name: "/m/0cydv" - id: 330 - display_name: "Caterpillar" -} -item { - name: "/m/07030" - id: 331 - display_name: "Sushi" -} -item { - name: "/m/084zz" - id: 332 - display_name: "Whale" -} -item { - name: "/m/0c29q" - id: 333 - display_name: "Leopard" -} -item { - name: "/m/02zn6n" - id: 334 - display_name: "Barrel" -} -item { - name: "/m/03tw93" - id: 335 - display_name: "Fireplace" -} -item { - name: "/m/0fqt361" - id: 336 - display_name: "Stool" -} -item { - name: "/m/0f9_l" - id: 337 - display_name: "Snail" -} -item { - name: "/m/0gm28" - id: 338 - display_name: "Candy" -} -item { - name: "/m/09rvcxw" - id: 339 - display_name: "Rocket" -} -item { - name: "/m/01nkt" - id: 340 - display_name: "Cheese" -} -item { - name: "/m/04p0qw" - id: 341 - display_name: "Billiard table" -} -item { - name: "/m/03hj559" - id: 342 - display_name: "Mixing bowl" -} -item { - name: "/m/07pj7bq" - id: 343 - display_name: "Bowling equipment" -} -item { - name: "/m/04ctx" - id: 344 - display_name: "Knife" -} -item { - name: "/m/0703r8" - id: 345 - display_name: "Loveseat" -} -item { - name: "/m/03qrc" - id: 346 - display_name: "Hamster" -} -item { - name: "/m/020lf" - id: 347 - display_name: "Mouse" -} -item { - name: "/m/0by6g" - id: 348 - display_name: "Shark" -} -item { - name: "/m/01fh4r" - id: 349 - display_name: "Teapot" -} -item { - name: "/m/07c6l" - id: 350 - display_name: "Trombone" -} -item { - name: "/m/03bj1" - id: 351 - display_name: "Panda" -} -item { - name: "/m/0898b" - id: 352 - display_name: "Zebra" -} -item { - name: "/m/02x984l" - id: 353 - display_name: "Mechanical fan" -} -item { - name: "/m/0fj52s" - id: 354 - display_name: "Carrot" -} -item { - name: "/m/0cd4d" - id: 355 - display_name: "Cheetah" -} -item { - name: "/m/02068x" - id: 356 - display_name: "Gondola" -} -item { - name: "/m/01vbnl" - id: 357 - display_name: "Bidet" -} -item { - name: "/m/0449p" - id: 358 - display_name: "Jaguar" -} -item { - name: "/m/0gj37" - id: 359 - display_name: "Ladybug" -} -item { - name: "/m/0nl46" - id: 360 - display_name: "Crown" -} -item { - name: "/m/0152hh" - id: 361 - display_name: "Snowman" -} -item { - name: "/m/03dnzn" - id: 362 - display_name: "Bathtub" -} -item { - name: "/m/05_5p_0" - id: 363 - display_name: "Table tennis racket" -} -item { - name: "/m/02jfl0" - id: 364 - display_name: "Sombrero" -} -item { - name: "/m/01dxs" - id: 365 - display_name: "Brown bear" -} -item { - name: "/m/0cjq5" - id: 366 - display_name: "Lobster" -} -item { - name: "/m/040b_t" - id: 367 - display_name: "Refrigerator" -} -item { - name: "/m/0_cp5" - id: 368 - display_name: "Oyster" -} -item { - name: "/m/0gxl3" - id: 369 - display_name: "Handgun" -} -item { - name: "/m/029bxz" - id: 370 - display_name: "Oven" -} -item { - name: "/m/02zt3" - id: 371 - display_name: "Kite" -} -item { - name: "/m/03d443" - id: 372 - display_name: "Rhinoceros" -} -item { - name: "/m/0306r" - id: 373 - display_name: "Fox" -} -item { - name: "/m/0h8l4fh" - id: 374 - display_name: "Light bulb" -} -item { - name: "/m/0633h" - id: 375 - display_name: "Polar bear" -} -item { - name: "/m/01s55n" - id: 376 - display_name: "Suitcase" -} -item { - name: "/m/0hkxq" - id: 377 - display_name: "Broccoli" -} -item { - name: "/m/0cn6p" - id: 378 - display_name: "Otter" -} -item { - name: "/m/0dbzx" - id: 379 - display_name: "Mule" -} -item { - name: "/m/01dy8n" - id: 380 - display_name: "Woodpecker" -} -item { - name: "/m/01h8tj" - id: 381 - display_name: "Starfish" -} -item { - name: "/m/03s_tn" - id: 382 - display_name: "Kettle" -} -item { - name: "/m/01xs3r" - id: 383 - display_name: "Jet ski" -} -item { - name: "/m/031b6r" - id: 384 - display_name: "Window blind" -} -item { - name: "/m/06j2d" - id: 385 - display_name: "Raven" -} -item { - name: "/m/0hqkz" - id: 386 - display_name: "Grapefruit" -} -item { - name: "/m/01_5g" - id: 387 - display_name: "Chopsticks" -} -item { - name: "/m/02zvsm" - id: 388 - display_name: "Tart" -} -item { - name: "/m/0kpqd" - id: 389 - display_name: "Watermelon" -} -item { - name: "/m/015x4r" - id: 390 - display_name: "Cucumber" -} -item { - name: "/m/061hd_" - id: 391 - display_name: "Infant bed" -} -item { - name: "/m/04ylt" - id: 392 - display_name: "Missile" -} -item { - name: "/m/02wv84t" - id: 393 - display_name: "Gas stove" -} -item { - name: "/m/04y4h8h" - id: 394 - display_name: "Bathroom cabinet" -} -item { - name: "/m/01gllr" - id: 395 - display_name: "Beehive" -} -item { - name: "/m/0pcr" - id: 396 - display_name: "Alpaca" -} -item { - name: "/m/0jy4k" - id: 397 - display_name: "Doughnut" -} -item { - name: "/m/09f20" - id: 398 - display_name: "Hippopotamus" -} -item { - name: "/m/0mcx2" - id: 399 - display_name: "Ipod" -} -item { - name: "/m/04c0y" - id: 400 - display_name: "Kangaroo" -} -item { - name: "/m/0_k2" - id: 401 - display_name: "Ant" -} -item { - name: "/m/0jg57" - id: 402 - display_name: "Bell pepper" -} -item { - name: "/m/03fj2" - id: 403 - display_name: "Goldfish" -} -item { - name: "/m/03ldnb" - id: 404 - display_name: "Ceiling fan" -} -item { - name: "/m/06nrc" - id: 405 - display_name: "Shotgun" -} -item { - name: "/m/01btn" - id: 406 - display_name: "Barge" -} -item { - name: "/m/05vtc" - id: 407 - display_name: "Potato" -} -item { - name: "/m/08hvt4" - id: 408 - display_name: "Jug" -} -item { - name: "/m/0fx9l" - id: 409 - display_name: "Microwave oven" -} -item { - name: "/m/01h44" - id: 410 - display_name: "Bat" -} -item { - name: "/m/05n4y" - id: 411 - display_name: "Ostrich" -} -item { - name: "/m/0jly1" - id: 412 - display_name: "Turkey" -} -item { - name: "/m/06y5r" - id: 413 - display_name: "Sword" -} -item { - name: "/m/05ctyq" - id: 414 - display_name: "Tennis ball" -} -item { - name: "/m/0fp6w" - id: 415 - display_name: "Pineapple" -} -item { - name: "/m/0d4w1" - id: 416 - display_name: "Closet" -} -item { - name: "/m/02pv19" - id: 417 - display_name: "Stop sign" -} -item { - name: "/m/07crc" - id: 418 - display_name: "Taco" -} -item { - name: "/m/01dwwc" - id: 419 - display_name: "Pancake" -} -item { - name: "/m/01b9xk" - id: 420 - display_name: "Hot dog" -} -item { - name: "/m/013y1f" - id: 421 - display_name: "Organ" -} -item { - name: "/m/0m53l" - id: 422 - display_name: "Rays and skates" -} -item { - name: "/m/0174k2" - id: 423 - display_name: "Washing machine" -} -item { - name: "/m/01dwsz" - id: 424 - display_name: "Waffle" -} -item { - name: "/m/04vv5k" - id: 425 - display_name: "Snowplow" -} -item { - name: "/m/04cp_" - id: 426 - display_name: "Koala" -} -item { - name: "/m/0fz0h" - id: 427 - display_name: "Honeycomb" -} -item { - name: "/m/0llzx" - id: 428 - display_name: "Sewing machine" -} -item { - name: "/m/0319l" - id: 429 - display_name: "Horn" -} -item { - name: "/m/04v6l4" - id: 430 - display_name: "Frying pan" -} -item { - name: "/m/0dkzw" - id: 431 - display_name: "Seat belt" -} -item { - name: "/m/027pcv" - id: 432 - display_name: "Zucchini" -} -item { - name: "/m/0323sq" - id: 433 - display_name: "Golf cart" -} -item { - name: "/m/054fyh" - id: 434 - display_name: "Pitcher" -} -item { - name: "/m/01pns0" - id: 435 - display_name: "Fire hydrant" -} -item { - name: "/m/012n7d" - id: 436 - display_name: "Ambulance" -} -item { - name: "/m/044r5d" - id: 437 - display_name: "Golf ball" -} -item { - name: "/m/01krhy" - id: 438 - display_name: "Tiara" -} -item { - name: "/m/0dq75" - id: 439 - display_name: "Raccoon" -} -item { - name: "/m/0176mf" - id: 440 - display_name: "Belt" -} -item { - name: "/m/0h8lkj8" - id: 441 - display_name: "Corded phone" -} -item { - name: "/m/04tn4x" - id: 442 - display_name: "Swim cap" -} -item { - name: "/m/06l9r" - id: 443 - display_name: "Red panda" -} -item { - name: "/m/0cjs7" - id: 444 - display_name: "Asparagus" -} -item { - name: "/m/01lsmm" - id: 445 - display_name: "Scissors" -} -item { - name: "/m/01lcw4" - id: 446 - display_name: "Limousine" -} -item { - name: "/m/047j0r" - id: 447 - display_name: "Filing cabinet" -} -item { - name: "/m/01fb_0" - id: 448 - display_name: "Bagel" -} -item { - name: "/m/04169hn" - id: 449 - display_name: "Wood-burning stove" -} -item { - name: "/m/076bq" - id: 450 - display_name: "Segway" -} -item { - name: "/m/0hdln" - id: 451 - display_name: "Ruler" -} -item { - name: "/m/01g3x7" - id: 452 - display_name: "Bow and arrow" -} -item { - name: "/m/0l3ms" - id: 453 - display_name: "Balance beam" -} -item { - name: "/m/058qzx" - id: 454 - display_name: "Kitchen knife" -} -item { - name: "/m/0h8n6ft" - id: 455 - display_name: "Cake stand" -} -item { - name: "/m/018j2" - id: 456 - display_name: "Banjo" -} -item { - name: "/m/0l14j_" - id: 457 - display_name: "Flute" -} -item { - name: "/m/0wdt60w" - id: 458 - display_name: "Rugby ball" -} -item { - name: "/m/02gzp" - id: 459 - display_name: "Dagger" -} -item { - name: "/m/0h8n6f9" - id: 460 - display_name: "Dog bed" -} -item { - name: "/m/0fbw6" - id: 461 - display_name: "Cabbage" -} -item { - name: "/m/07kng9" - id: 462 - display_name: "Picnic basket" -} -item { - name: "/m/0dj6p" - id: 463 - display_name: "Peach" -} -item { - name: "/m/06pcq" - id: 464 - display_name: "Submarine sandwich" -} -item { - name: "/m/061_f" - id: 465 - display_name: "Pear" -} -item { - name: "/m/04g2r" - id: 466 - display_name: "Lynx" -} -item { - name: "/m/0jwn_" - id: 467 - display_name: "Pomegranate" -} -item { - name: "/m/02f9f_" - id: 468 - display_name: "Shower" -} -item { - name: "/m/01f8m5" - id: 469 - display_name: "Blue jay" -} -item { - name: "/m/01m4t" - id: 470 - display_name: "Printer" -} -item { - name: "/m/0cl4p" - id: 471 - display_name: "Hedgehog" -} -item { - name: "/m/07xyvk" - id: 472 - display_name: "Coffeemaker" -} -item { - name: "/m/084hf" - id: 473 - display_name: "Worm" -} -item { - name: "/m/03v5tg" - id: 474 - display_name: "Drinking straw" -} -item { - name: "/m/0qjjc" - id: 475 - display_name: "Remote control" -} -item { - name: "/m/015x5n" - id: 476 - display_name: "Radish" -} -item { - name: "/m/0ccs93" - id: 477 - display_name: "Canary" -} -item { - name: "/m/0nybt" - id: 478 - display_name: "Seahorse" -} -item { - name: "/m/02vkqh8" - id: 479 - display_name: "Wardrobe" -} -item { - name: "/m/09gtd" - id: 480 - display_name: "Toilet paper" -} -item { - name: "/m/019h78" - id: 481 - display_name: "Centipede" -} -item { - name: "/m/015wgc" - id: 482 - display_name: "Croissant" -} -item { - name: "/m/01x3jk" - id: 483 - display_name: "Snowmobile" -} -item { - name: "/m/01j3zr" - id: 484 - display_name: "Burrito" -} -item { - name: "/m/0c568" - id: 485 - display_name: "Porcupine" -} -item { - name: "/m/02pdsw" - id: 486 - display_name: "Cutting board" -} -item { - name: "/m/029b3" - id: 487 - display_name: "Dice" -} -item { - name: "/m/03q5t" - id: 488 - display_name: "Harpsichord" -} -item { - name: "/m/0p833" - id: 489 - display_name: "Perfume" -} -item { - name: "/m/01d380" - id: 490 - display_name: "Drill" -} -item { - name: "/m/024d2" - id: 491 - display_name: "Calculator" -} -item { - name: "/m/0mw_6" - id: 492 - display_name: "Willow" -} -item { - name: "/m/01f91_" - id: 493 - display_name: "Pretzel" -} -item { - name: "/m/02g30s" - id: 494 - display_name: "Guacamole" -} -item { - name: "/m/01hrv5" - id: 495 - display_name: "Popcorn" -} -item { - name: "/m/03m5k" - id: 496 - display_name: "Harp" -} -item { - name: "/m/0162_1" - id: 497 - display_name: "Towel" -} -item { - name: "/m/063rgb" - id: 498 - display_name: "Mixer" -} -item { - name: "/m/06_72j" - id: 499 - display_name: "Digital clock" -} -item { - name: "/m/046dlr" - id: 500 - display_name: "Alarm clock" -} -item { - name: "/m/047v4b" - id: 501 - display_name: "Artichoke" -} -item { - name: "/m/04zpv" - id: 502 - display_name: "Milk" -} -item { - name: "/m/043nyj" - id: 503 - display_name: "Common fig" -} -item { - name: "/m/03bbps" - id: 504 - display_name: "Power plugs and sockets" -} -item { - name: "/m/02w3r3" - id: 505 - display_name: "Paper towel" -} -item { - name: "/m/02pjr4" - id: 506 - display_name: "Blender" -} -item { - name: "/m/0755b" - id: 507 - display_name: "Scorpion" -} -item { - name: "/m/02lbcq" - id: 508 - display_name: "Stretcher" -} -item { - name: "/m/0fldg" - id: 509 - display_name: "Mango" -} -item { - name: "/m/012074" - id: 510 - display_name: "Magpie" -} -item { - name: "/m/035vxb" - id: 511 - display_name: "Isopod" -} -item { - name: "/m/02w3_ws" - id: 512 - display_name: "Personal care" -} -item { - name: "/m/0f6nr" - id: 513 - display_name: "Unicycle" -} -item { - name: "/m/0420v5" - id: 514 - display_name: "Punching bag" -} -item { - name: "/m/0frqm" - id: 515 - display_name: "Envelope" -} -item { - name: "/m/03txqz" - id: 516 - display_name: "Scale" -} -item { - name: "/m/0271qf7" - id: 517 - display_name: "Wine rack" -} -item { - name: "/m/074d1" - id: 518 - display_name: "Submarine" -} -item { - name: "/m/08p92x" - id: 519 - display_name: "Cream" -} -item { - name: "/m/01j4z9" - id: 520 - display_name: "Chainsaw" -} -item { - name: "/m/0kpt_" - id: 521 - display_name: "Cantaloupe" -} -item { - name: "/m/0h8n27j" - id: 522 - display_name: "Serving tray" -} -item { - name: "/m/03y6mg" - id: 523 - display_name: "Food processor" -} -item { - name: "/m/04h8sr" - id: 524 - display_name: "Dumbbell" -} -item { - name: "/m/065h6l" - id: 525 - display_name: "Jacuzzi" -} -item { - name: "/m/02tsc9" - id: 526 - display_name: "Slow cooker" -} -item { - name: "/m/012ysf" - id: 527 - display_name: "Syringe" -} -item { - name: "/m/0ky7b" - id: 528 - display_name: "Dishwasher" -} -item { - name: "/m/02wg_p" - id: 529 - display_name: "Tree house" -} -item { - name: "/m/0584n8" - id: 530 - display_name: "Briefcase" -} -item { - name: "/m/03kt2w" - id: 531 - display_name: "Stationary bicycle" -} -item { - name: "/m/05kms" - id: 532 - display_name: "Oboe" -} -item { - name: "/m/030610" - id: 533 - display_name: "Treadmill" -} -item { - name: "/m/0lt4_" - id: 534 - display_name: "Binoculars" -} -item { - name: "/m/076lb9" - id: 535 - display_name: "Bench" -} -item { - name: "/m/02ctlc" - id: 536 - display_name: "Cricket ball" -} -item { - name: "/m/02x8cch" - id: 537 - display_name: "Salt and pepper shakers" -} -item { - name: "/m/09gys" - id: 538 - display_name: "Squid" -} -item { - name: "/m/03jbxj" - id: 539 - display_name: "Light switch" -} -item { - name: "/m/012xff" - id: 540 - display_name: "Toothbrush" -} -item { - name: "/m/0h8kx63" - id: 541 - display_name: "Spice rack" -} -item { - name: "/m/073g6" - id: 542 - display_name: "Stethoscope" -} -item { - name: "/m/02cvgx" - id: 543 - display_name: "Winter melon" -} -item { - name: "/m/027rl48" - id: 544 - display_name: "Ladle" -} -item { - name: "/m/01kb5b" - id: 545 - display_name: "Flashlight" -} diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/oid_object_detection_challenge_500_label_map.pbtxt b/research/mlperf_object_detection/Mask_RCNN/object_detection/data/oid_object_detection_challenge_500_label_map.pbtxt deleted file mode 100644 index 044f6d4c8..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/oid_object_detection_challenge_500_label_map.pbtxt +++ /dev/null @@ -1,2500 +0,0 @@ -item { - name: "/m/061hd_" - id: 1 - display_name: "Infant bed" -} -item { - name: "/m/06m11" - id: 2 - display_name: "Rose" -} -item { - name: "/m/03120" - id: 3 - display_name: "Flag" -} -item { - name: "/m/01kb5b" - id: 4 - display_name: "Flashlight" -} -item { - name: "/m/0120dh" - id: 5 - display_name: "Sea turtle" -} -item { - name: "/m/0dv5r" - id: 6 - display_name: "Camera" -} -item { - name: "/m/0jbk" - id: 7 - display_name: "Animal" -} -item { - name: "/m/0174n1" - id: 8 - display_name: "Glove" -} -item { - name: "/m/09f_2" - id: 9 - display_name: "Crocodile" -} -item { - name: "/m/01xq0k1" - id: 10 - display_name: "Cattle" -} -item { - name: "/m/03jm5" - id: 11 - display_name: "House" -} -item { - name: "/m/02g30s" - id: 12 - display_name: "Guacamole" -} -item { - name: "/m/05z6w" - id: 13 - display_name: "Penguin" -} -item { - name: "/m/01jfm_" - id: 14 - display_name: "Vehicle registration plate" -} -item { - name: "/m/076lb9" - id: 15 - display_name: "Training bench" -} -item { - name: "/m/0gj37" - id: 16 - display_name: "Ladybug" -} -item { - name: "/m/0k0pj" - id: 17 - display_name: "Human nose" -} -item { - name: "/m/0kpqd" - id: 18 - display_name: "Watermelon" -} -item { - name: "/m/0l14j_" - id: 19 - display_name: "Flute" -} -item { - name: "/m/0cyf8" - id: 20 - display_name: "Butterfly" -} -item { - name: "/m/0174k2" - id: 21 - display_name: "Washing machine" -} -item { - name: "/m/0dq75" - id: 22 - display_name: "Raccoon" -} -item { - name: "/m/076bq" - id: 23 - display_name: "Segway" -} -item { - name: "/m/07crc" - id: 24 - display_name: "Taco" -} -item { - name: "/m/0d8zb" - id: 25 - display_name: "Jellyfish" -} -item { - name: "/m/0fszt" - id: 26 - display_name: "Cake" -} -item { - name: "/m/0k1tl" - id: 27 - display_name: "Pen" -} -item { - name: "/m/020kz" - id: 28 - display_name: "Cannon" -} -item { - name: "/m/09728" - id: 29 - display_name: "Bread" -} -item { - name: "/m/07j7r" - id: 30 - display_name: "Tree" -} -item { - name: "/m/0fbdv" - id: 31 - display_name: "Shellfish" -} -item { - name: "/m/03ssj5" - id: 32 - display_name: "Bed" -} -item { - name: "/m/03qrc" - id: 33 - display_name: "Hamster" -} -item { - name: "/m/02dl1y" - id: 34 - display_name: "Hat" -} -item { - name: "/m/01k6s3" - id: 35 - display_name: "Toaster" -} -item { - name: "/m/02jfl0" - id: 36 - display_name: "Sombrero" -} -item { - name: "/m/01krhy" - id: 37 - display_name: "Tiara" -} -item { - name: "/m/04kkgm" - id: 38 - display_name: "Bowl" -} -item { - name: "/m/0ft9s" - id: 39 - display_name: "Dragonfly" -} -item { - name: "/m/0d_2m" - id: 40 - display_name: "Moths and butterflies" -} -item { - name: "/m/0czz2" - id: 41 - display_name: "Antelope" -} -item { - name: "/m/0f4s2w" - id: 42 - display_name: "Vegetable" -} -item { - name: "/m/07dd4" - id: 43 - display_name: "Torch" -} -item { - name: "/m/0cgh4" - id: 44 - display_name: "Building" -} -item { - name: "/m/03bbps" - id: 45 - display_name: "Power plugs and sockets" -} -item { - name: "/m/02pjr4" - id: 46 - display_name: "Blender" -} -item { - name: "/m/04p0qw" - id: 47 - display_name: "Billiard table" -} -item { - name: "/m/02pdsw" - id: 48 - display_name: "Cutting board" -} -item { - name: "/m/01yx86" - id: 49 - display_name: "Bronze sculpture" -} -item { - name: "/m/09dzg" - id: 50 - display_name: "Turtle" -} -item { - name: "/m/0hkxq" - id: 51 - display_name: "Broccoli" -} -item { - name: "/m/07dm6" - id: 52 - display_name: "Tiger" -} -item { - name: "/m/054_l" - id: 53 - display_name: "Mirror" -} -item { - name: "/m/01dws" - id: 54 - display_name: "Bear" -} -item { - name: "/m/027pcv" - id: 55 - display_name: "Zucchini" -} -item { - name: "/m/01d40f" - id: 56 - display_name: "Dress" -} -item { - name: "/m/02rgn06" - id: 57 - display_name: "Volleyball" -} -item { - name: "/m/0342h" - id: 58 - display_name: "Guitar" -} -item { - name: "/m/06bt6" - id: 59 - display_name: "Reptile" -} -item { - name: "/m/0323sq" - id: 60 - display_name: "Golf cart" -} -item { - name: "/m/02zvsm" - id: 61 - display_name: "Tart" -} -item { - name: "/m/02fq_6" - id: 62 - display_name: "Fedora" -} -item { - name: "/m/01lrl" - id: 63 - display_name: "Carnivore" -} -item { - name: "/m/0k4j" - id: 64 - display_name: "Car" -} -item { - name: "/m/04h7h" - id: 65 - display_name: "Lighthouse" -} -item { - name: "/m/07xyvk" - id: 66 - display_name: "Coffeemaker" -} -item { - name: "/m/03y6mg" - id: 67 - display_name: "Food processor" -} -item { - name: "/m/07r04" - id: 68 - display_name: "Truck" -} -item { - name: "/m/03__z0" - id: 69 - display_name: "Bookcase" -} -item { - name: "/m/019w40" - id: 70 - display_name: "Surfboard" -} -item { - name: "/m/09j5n" - id: 71 - display_name: "Footwear" -} -item { - name: "/m/0cvnqh" - id: 72 - display_name: "Bench" -} -item { - name: "/m/01llwg" - id: 73 - display_name: "Necklace" -} -item { - name: "/m/0c9ph5" - id: 74 - display_name: "Flower" -} -item { - name: "/m/015x5n" - id: 75 - display_name: "Radish" -} -item { - name: "/m/0gd2v" - id: 76 - display_name: "Marine mammal" -} -item { - name: "/m/04v6l4" - id: 77 - display_name: "Frying pan" -} -item { - name: "/m/02jz0l" - id: 78 - display_name: "Tap" -} -item { - name: "/m/0dj6p" - id: 79 - display_name: "Peach" -} -item { - name: "/m/04ctx" - id: 80 - display_name: "Knife" -} -item { - name: "/m/080hkjn" - id: 81 - display_name: "Handbag" -} -item { - name: "/m/01c648" - id: 82 - display_name: "Laptop" -} -item { - name: "/m/01j61q" - id: 83 - display_name: "Tent" -} -item { - name: "/m/012n7d" - id: 84 - display_name: "Ambulance" -} -item { - name: "/m/025nd" - id: 85 - display_name: "Christmas tree" -} -item { - name: "/m/09csl" - id: 86 - display_name: "Eagle" -} -item { - name: "/m/01lcw4" - id: 87 - display_name: "Limousine" -} -item { - name: "/m/0h8n5zk" - id: 88 - display_name: "Kitchen & dining room table" -} -item { - name: "/m/0633h" - id: 89 - display_name: "Polar bear" -} -item { - name: "/m/01fdzj" - id: 90 - display_name: "Tower" -} -item { - name: "/m/01226z" - id: 91 - display_name: "Football" -} -item { - name: "/m/0mw_6" - id: 92 - display_name: "Willow" -} -item { - name: "/m/04hgtk" - id: 93 - display_name: "Human head" -} -item { - name: "/m/02pv19" - id: 94 - display_name: "Stop sign" -} -item { - name: "/m/09qck" - id: 95 - display_name: "Banana" -} -item { - name: "/m/063rgb" - id: 96 - display_name: "Mixer" -} -item { - name: "/m/0lt4_" - id: 97 - display_name: "Binoculars" -} -item { - name: "/m/0270h" - id: 98 - display_name: "Dessert" -} -item { - name: "/m/01h3n" - id: 99 - display_name: "Bee" -} -item { - name: "/m/01mzpv" - id: 100 - display_name: "Chair" -} -item { - name: "/m/04169hn" - id: 101 - display_name: "Wood-burning stove" -} -item { - name: "/m/0fm3zh" - id: 102 - display_name: "Flowerpot" -} -item { - name: "/m/0d20w4" - id: 103 - display_name: "Beaker" -} -item { - name: "/m/0_cp5" - id: 104 - display_name: "Oyster" -} -item { - name: "/m/01dy8n" - id: 105 - display_name: "Woodpecker" -} -item { - name: "/m/03m5k" - id: 106 - display_name: "Harp" -} -item { - name: "/m/03dnzn" - id: 107 - display_name: "Bathtub" -} -item { - name: "/m/0h8mzrc" - id: 108 - display_name: "Wall clock" -} -item { - name: "/m/0h8mhzd" - id: 109 - display_name: "Sports uniform" -} -item { - name: "/m/03d443" - id: 110 - display_name: "Rhinoceros" -} -item { - name: "/m/01gllr" - id: 111 - display_name: "Beehive" -} -item { - name: "/m/0642b4" - id: 112 - display_name: "Cupboard" -} -item { - name: "/m/09b5t" - id: 113 - display_name: "Chicken" -} -item { - name: "/m/04yx4" - id: 114 - display_name: "Man" -} -item { - name: "/m/01f8m5" - id: 115 - display_name: "Blue jay" -} -item { - name: "/m/015x4r" - id: 116 - display_name: "Cucumber" -} -item { - name: "/m/01j51" - id: 117 - display_name: "Balloon" -} -item { - name: "/m/02zt3" - id: 118 - display_name: "Kite" -} -item { - name: "/m/03tw93" - id: 119 - display_name: "Fireplace" -} -item { - name: "/m/01jfsr" - id: 120 - display_name: "Lantern" -} -item { - name: "/m/04ylt" - id: 121 - display_name: "Missile" -} -item { - name: "/m/0bt_c3" - id: 122 - display_name: "Book" -} -item { - name: "/m/0cmx8" - id: 123 - display_name: "Spoon" -} -item { - name: "/m/0hqkz" - id: 124 - display_name: "Grapefruit" -} -item { - name: "/m/071qp" - id: 125 - display_name: "Squirrel" -} -item { - name: "/m/0cyhj_" - id: 126 - display_name: "Orange" -} -item { - name: "/m/01xygc" - id: 127 - display_name: "Coat" -} -item { - name: "/m/0420v5" - id: 128 - display_name: "Punching bag" -} -item { - name: "/m/0898b" - id: 129 - display_name: "Zebra" -} -item { - name: "/m/01knjb" - id: 130 - display_name: "Billboard" -} -item { - name: "/m/0199g" - id: 131 - display_name: "Bicycle" -} -item { - name: "/m/03c7gz" - id: 132 - display_name: "Door handle" -} -item { - name: "/m/02x984l" - id: 133 - display_name: "Mechanical fan" -} -item { - name: "/m/04zwwv" - id: 134 - display_name: "Ring binder" -} -item { - name: "/m/04bcr3" - id: 135 - display_name: "Table" -} -item { - name: "/m/0gv1x" - id: 136 - display_name: "Parrot" -} -item { - name: "/m/01nq26" - id: 137 - display_name: "Sock" -} -item { - name: "/m/02s195" - id: 138 - display_name: "Vase" -} -item { - name: "/m/083kb" - id: 139 - display_name: "Weapon" -} -item { - name: "/m/06nrc" - id: 140 - display_name: "Shotgun" -} -item { - name: "/m/0jyfg" - id: 141 - display_name: "Glasses" -} -item { - name: "/m/0nybt" - id: 142 - display_name: "Seahorse" -} -item { - name: "/m/0176mf" - id: 143 - display_name: "Belt" -} -item { - name: "/m/01rzcn" - id: 144 - display_name: "Watercraft" -} -item { - name: "/m/0d4v4" - id: 145 - display_name: "Window" -} -item { - name: "/m/03bk1" - id: 146 - display_name: "Giraffe" -} -item { - name: "/m/096mb" - id: 147 - display_name: "Lion" -} -item { - name: "/m/0h9mv" - id: 148 - display_name: "Tire" -} -item { - name: "/m/07yv9" - id: 149 - display_name: "Vehicle" -} -item { - name: "/m/0ph39" - id: 150 - display_name: "Canoe" -} -item { - name: "/m/01rkbr" - id: 151 - display_name: "Tie" -} -item { - name: "/m/0gjbg72" - id: 152 - display_name: "Shelf" -} -item { - name: "/m/06z37_" - id: 153 - display_name: "Picture frame" -} -item { - name: "/m/01m4t" - id: 154 - display_name: "Printer" -} -item { - name: "/m/035r7c" - id: 155 - display_name: "Human leg" -} -item { - name: "/m/019jd" - id: 156 - display_name: "Boat" -} -item { - name: "/m/02tsc9" - id: 157 - display_name: "Slow cooker" -} -item { - name: "/m/015wgc" - id: 158 - display_name: "Croissant" -} -item { - name: "/m/0c06p" - id: 159 - display_name: "Candle" -} -item { - name: "/m/01dwwc" - id: 160 - display_name: "Pancake" -} -item { - name: "/m/034c16" - id: 161 - display_name: "Pillow" -} -item { - name: "/m/0242l" - id: 162 - display_name: "Coin" -} -item { - name: "/m/02lbcq" - id: 163 - display_name: "Stretcher" -} -item { - name: "/m/03nfch" - id: 164 - display_name: "Sandal" -} -item { - name: "/m/03bt1vf" - id: 165 - display_name: "Woman" -} -item { - name: "/m/01lynh" - id: 166 - display_name: "Stairs" -} -item { - name: "/m/03q5t" - id: 167 - display_name: "Harpsichord" -} -item { - name: "/m/0fqt361" - id: 168 - display_name: "Stool" -} -item { - name: "/m/01bjv" - id: 169 - display_name: "Bus" -} -item { - name: "/m/01s55n" - id: 170 - display_name: "Suitcase" -} -item { - name: "/m/0283dt1" - id: 171 - display_name: "Human mouth" -} -item { - name: "/m/01z1kdw" - id: 172 - display_name: "Juice" -} -item { - name: "/m/016m2d" - id: 173 - display_name: "Skull" -} -item { - name: "/m/02dgv" - id: 174 - display_name: "Door" -} -item { - name: "/m/07y_7" - id: 175 - display_name: "Violin" -} -item { - name: "/m/01_5g" - id: 176 - display_name: "Chopsticks" -} -item { - name: "/m/06_72j" - id: 177 - display_name: "Digital clock" -} -item { - name: "/m/0ftb8" - id: 178 - display_name: "Sunflower" -} -item { - name: "/m/0c29q" - id: 179 - display_name: "Leopard" -} -item { - name: "/m/0jg57" - id: 180 - display_name: "Bell pepper" -} -item { - name: "/m/02l8p9" - id: 181 - display_name: "Harbor seal" -} -item { - name: "/m/078jl" - id: 182 - display_name: "Snake" -} -item { - name: "/m/0llzx" - id: 183 - display_name: "Sewing machine" -} -item { - name: "/m/0dbvp" - id: 184 - display_name: "Goose" -} -item { - name: "/m/09ct_" - id: 185 - display_name: "Helicopter" -} -item { - name: "/m/0dkzw" - id: 186 - display_name: "Seat belt" -} -item { - name: "/m/02p5f1q" - id: 187 - display_name: "Coffee cup" -} -item { - name: "/m/0fx9l" - id: 188 - display_name: "Microwave oven" -} -item { - name: "/m/01b9xk" - id: 189 - display_name: "Hot dog" -} -item { - name: "/m/0b3fp9" - id: 190 - display_name: "Countertop" -} -item { - name: "/m/0h8n27j" - id: 191 - display_name: "Serving tray" -} -item { - name: "/m/0h8n6f9" - id: 192 - display_name: "Dog bed" -} -item { - name: "/m/01599" - id: 193 - display_name: "Beer" -} -item { - name: "/m/017ftj" - id: 194 - display_name: "Sunglasses" -} -item { - name: "/m/044r5d" - id: 195 - display_name: "Golf ball" -} -item { - name: "/m/01dwsz" - id: 196 - display_name: "Waffle" -} -item { - name: "/m/0cdl1" - id: 197 - display_name: "Palm tree" -} -item { - name: "/m/07gql" - id: 198 - display_name: "Trumpet" -} -item { - name: "/m/0hdln" - id: 199 - display_name: "Ruler" -} -item { - name: "/m/0zvk5" - id: 200 - display_name: "Helmet" -} -item { - name: "/m/012w5l" - id: 201 - display_name: "Ladder" -} -item { - name: "/m/021sj1" - id: 202 - display_name: "Office building" -} -item { - name: "/m/0bh9flk" - id: 203 - display_name: "Tablet computer" -} -item { - name: "/m/09gtd" - id: 204 - display_name: "Toilet paper" -} -item { - name: "/m/0jwn_" - id: 205 - display_name: "Pomegranate" -} -item { - name: "/m/02wv6h6" - id: 206 - display_name: "Skirt" -} -item { - name: "/m/02wv84t" - id: 207 - display_name: "Gas stove" -} -item { - name: "/m/021mn" - id: 208 - display_name: "Cookie" -} -item { - name: "/m/018p4k" - id: 209 - display_name: "Cart" -} -item { - name: "/m/06j2d" - id: 210 - display_name: "Raven" -} -item { - name: "/m/033cnk" - id: 211 - display_name: "Egg" -} -item { - name: "/m/01j3zr" - id: 212 - display_name: "Burrito" -} -item { - name: "/m/03fwl" - id: 213 - display_name: "Goat" -} -item { - name: "/m/058qzx" - id: 214 - display_name: "Kitchen knife" -} -item { - name: "/m/06_fw" - id: 215 - display_name: "Skateboard" -} -item { - name: "/m/02x8cch" - id: 216 - display_name: "Salt and pepper shakers" -} -item { - name: "/m/04g2r" - id: 217 - display_name: "Lynx" -} -item { - name: "/m/01b638" - id: 218 - display_name: "Boot" -} -item { - name: "/m/099ssp" - id: 219 - display_name: "Platter" -} -item { - name: "/m/071p9" - id: 220 - display_name: "Ski" -} -item { - name: "/m/01gkx_" - id: 221 - display_name: "Swimwear" -} -item { - name: "/m/0b_rs" - id: 222 - display_name: "Swimming pool" -} -item { - name: "/m/03v5tg" - id: 223 - display_name: "Drinking straw" -} -item { - name: "/m/01j5ks" - id: 224 - display_name: "Wrench" -} -item { - name: "/m/026t6" - id: 225 - display_name: "Drum" -} -item { - name: "/m/0_k2" - id: 226 - display_name: "Ant" -} -item { - name: "/m/039xj_" - id: 227 - display_name: "Human ear" -} -item { - name: "/m/01b7fy" - id: 228 - display_name: "Headphones" -} -item { - name: "/m/0220r2" - id: 229 - display_name: "Fountain" -} -item { - name: "/m/015p6" - id: 230 - display_name: "Bird" -} -item { - name: "/m/0fly7" - id: 231 - display_name: "Jeans" -} -item { - name: "/m/07c52" - id: 232 - display_name: "Television" -} -item { - name: "/m/0n28_" - id: 233 - display_name: "Crab" -} -item { - name: "/m/0hg7b" - id: 234 - display_name: "Microphone" -} -item { - name: "/m/019dx1" - id: 235 - display_name: "Home appliance" -} -item { - name: "/m/04vv5k" - id: 236 - display_name: "Snowplow" -} -item { - name: "/m/020jm" - id: 237 - display_name: "Beetle" -} -item { - name: "/m/047v4b" - id: 238 - display_name: "Artichoke" -} -item { - name: "/m/01xs3r" - id: 239 - display_name: "Jet ski" -} -item { - name: "/m/03kt2w" - id: 240 - display_name: "Stationary bicycle" -} -item { - name: "/m/03q69" - id: 241 - display_name: "Human hair" -} -item { - name: "/m/01dxs" - id: 242 - display_name: "Brown bear" -} -item { - name: "/m/01h8tj" - id: 243 - display_name: "Starfish" -} -item { - name: "/m/0dt3t" - id: 244 - display_name: "Fork" -} -item { - name: "/m/0cjq5" - id: 245 - display_name: "Lobster" -} -item { - name: "/m/0h8lkj8" - id: 246 - display_name: "Corded phone" -} -item { - name: "/m/0271t" - id: 247 - display_name: "Drink" -} -item { - name: "/m/03q5c7" - id: 248 - display_name: "Saucer" -} -item { - name: "/m/0fj52s" - id: 249 - display_name: "Carrot" -} -item { - name: "/m/03vt0" - id: 250 - display_name: "Insect" -} -item { - name: "/m/01x3z" - id: 251 - display_name: "Clock" -} -item { - name: "/m/0d5gx" - id: 252 - display_name: "Castle" -} -item { - name: "/m/0h8my_4" - id: 253 - display_name: "Tennis racket" -} -item { - name: "/m/03ldnb" - id: 254 - display_name: "Ceiling fan" -} -item { - name: "/m/0cjs7" - id: 255 - display_name: "Asparagus" -} -item { - name: "/m/0449p" - id: 256 - display_name: "Jaguar" -} -item { - name: "/m/04szw" - id: 257 - display_name: "Musical instrument" -} -item { - name: "/m/07jdr" - id: 258 - display_name: "Train" -} -item { - name: "/m/01yrx" - id: 259 - display_name: "Cat" -} -item { - name: "/m/06c54" - id: 260 - display_name: "Rifle" -} -item { - name: "/m/04h8sr" - id: 261 - display_name: "Dumbbell" -} -item { - name: "/m/050k8" - id: 262 - display_name: "Mobile phone" -} -item { - name: "/m/0pg52" - id: 263 - display_name: "Taxi" -} -item { - name: "/m/02f9f_" - id: 264 - display_name: "Shower" -} -item { - name: "/m/054fyh" - id: 265 - display_name: "Pitcher" -} -item { - name: "/m/09k_b" - id: 266 - display_name: "Lemon" -} -item { - name: "/m/03xxp" - id: 267 - display_name: "Invertebrate" -} -item { - name: "/m/0jly1" - id: 268 - display_name: "Turkey" -} -item { - name: "/m/06k2mb" - id: 269 - display_name: "High heels" -} -item { - name: "/m/04yqq2" - id: 270 - display_name: "Bust" -} -item { - name: "/m/0bwd_0j" - id: 271 - display_name: "Elephant" -} -item { - name: "/m/02h19r" - id: 272 - display_name: "Scarf" -} -item { - name: "/m/02zn6n" - id: 273 - display_name: "Barrel" -} -item { - name: "/m/07c6l" - id: 274 - display_name: "Trombone" -} -item { - name: "/m/05zsy" - id: 275 - display_name: "Pumpkin" -} -item { - name: "/m/025dyy" - id: 276 - display_name: "Box" -} -item { - name: "/m/07j87" - id: 277 - display_name: "Tomato" -} -item { - name: "/m/09ld4" - id: 278 - display_name: "Frog" -} -item { - name: "/m/01vbnl" - id: 279 - display_name: "Bidet" -} -item { - name: "/m/0dzct" - id: 280 - display_name: "Human face" -} -item { - name: "/m/03fp41" - id: 281 - display_name: "Houseplant" -} -item { - name: "/m/0h2r6" - id: 282 - display_name: "Van" -} -item { - name: "/m/0by6g" - id: 283 - display_name: "Shark" -} -item { - name: "/m/0cxn2" - id: 284 - display_name: "Ice cream" -} -item { - name: "/m/04tn4x" - id: 285 - display_name: "Swim cap" -} -item { - name: "/m/0f6wt" - id: 286 - display_name: "Falcon" -} -item { - name: "/m/05n4y" - id: 287 - display_name: "Ostrich" -} -item { - name: "/m/0gxl3" - id: 288 - display_name: "Handgun" -} -item { - name: "/m/02d9qx" - id: 289 - display_name: "Whiteboard" -} -item { - name: "/m/04m9y" - id: 290 - display_name: "Lizard" -} -item { - name: "/m/05z55" - id: 291 - display_name: "Pasta" -} -item { - name: "/m/01x3jk" - id: 292 - display_name: "Snowmobile" -} -item { - name: "/m/0h8l4fh" - id: 293 - display_name: "Light bulb" -} -item { - name: "/m/031b6r" - id: 294 - display_name: "Window blind" -} -item { - name: "/m/01tcjp" - id: 295 - display_name: "Muffin" -} -item { - name: "/m/01f91_" - id: 296 - display_name: "Pretzel" -} -item { - name: "/m/02522" - id: 297 - display_name: "Computer monitor" -} -item { - name: "/m/0319l" - id: 298 - display_name: "Horn" -} -item { - name: "/m/0c_jw" - id: 299 - display_name: "Furniture" -} -item { - name: "/m/0l515" - id: 300 - display_name: "Sandwich" -} -item { - name: "/m/0306r" - id: 301 - display_name: "Fox" -} -item { - name: "/m/0crjs" - id: 302 - display_name: "Convenience store" -} -item { - name: "/m/0ch_cf" - id: 303 - display_name: "Fish" -} -item { - name: "/m/02xwb" - id: 304 - display_name: "Fruit" -} -item { - name: "/m/01r546" - id: 305 - display_name: "Earrings" -} -item { - name: "/m/03rszm" - id: 306 - display_name: "Curtain" -} -item { - name: "/m/0388q" - id: 307 - display_name: "Grape" -} -item { - name: "/m/03m3pdh" - id: 308 - display_name: "Sofa bed" -} -item { - name: "/m/03k3r" - id: 309 - display_name: "Horse" -} -item { - name: "/m/0hf58v5" - id: 310 - display_name: "Luggage and bags" -} -item { - name: "/m/01y9k5" - id: 311 - display_name: "Desk" -} -item { - name: "/m/05441v" - id: 312 - display_name: "Crutch" -} -item { - name: "/m/03p3bw" - id: 313 - display_name: "Bicycle helmet" -} -item { - name: "/m/0175cv" - id: 314 - display_name: "Tick" -} -item { - name: "/m/0cmf2" - id: 315 - display_name: "Airplane" -} -item { - name: "/m/0ccs93" - id: 316 - display_name: "Canary" -} -item { - name: "/m/02d1br" - id: 317 - display_name: "Spatula" -} -item { - name: "/m/0gjkl" - id: 318 - display_name: "Watch" -} -item { - name: "/m/0jqgx" - id: 319 - display_name: "Lily" -} -item { - name: "/m/0h99cwc" - id: 320 - display_name: "Kitchen appliance" -} -item { - name: "/m/047j0r" - id: 321 - display_name: "Filing cabinet" -} -item { - name: "/m/0k5j" - id: 322 - display_name: "Aircraft" -} -item { - name: "/m/0h8n6ft" - id: 323 - display_name: "Cake stand" -} -item { - name: "/m/0gm28" - id: 324 - display_name: "Candy" -} -item { - name: "/m/0130jx" - id: 325 - display_name: "Sink" -} -item { - name: "/m/04rmv" - id: 326 - display_name: "Mouse" -} -item { - name: "/m/081qc" - id: 327 - display_name: "Wine" -} -item { - name: "/m/0qmmr" - id: 328 - display_name: "Wheelchair" -} -item { - name: "/m/03fj2" - id: 329 - display_name: "Goldfish" -} -item { - name: "/m/040b_t" - id: 330 - display_name: "Refrigerator" -} -item { - name: "/m/02y6n" - id: 331 - display_name: "French fries" -} -item { - name: "/m/0fqfqc" - id: 332 - display_name: "Drawer" -} -item { - name: "/m/030610" - id: 333 - display_name: "Treadmill" -} -item { - name: "/m/07kng9" - id: 334 - display_name: "Picnic basket" -} -item { - name: "/m/029b3" - id: 335 - display_name: "Dice" -} -item { - name: "/m/0fbw6" - id: 336 - display_name: "Cabbage" -} -item { - name: "/m/07qxg_" - id: 337 - display_name: "Football helmet" -} -item { - name: "/m/068zj" - id: 338 - display_name: "Pig" -} -item { - name: "/m/01g317" - id: 339 - display_name: "Person" -} -item { - name: "/m/01bfm9" - id: 340 - display_name: "Shorts" -} -item { - name: "/m/02068x" - id: 341 - display_name: "Gondola" -} -item { - name: "/m/0fz0h" - id: 342 - display_name: "Honeycomb" -} -item { - name: "/m/0jy4k" - id: 343 - display_name: "Doughnut" -} -item { - name: "/m/05kyg_" - id: 344 - display_name: "Chest of drawers" -} -item { - name: "/m/01prls" - id: 345 - display_name: "Land vehicle" -} -item { - name: "/m/01h44" - id: 346 - display_name: "Bat" -} -item { - name: "/m/08pbxl" - id: 347 - display_name: "Monkey" -} -item { - name: "/m/02gzp" - id: 348 - display_name: "Dagger" -} -item { - name: "/m/04brg2" - id: 349 - display_name: "Tableware" -} -item { - name: "/m/031n1" - id: 350 - display_name: "Human foot" -} -item { - name: "/m/02jvh9" - id: 351 - display_name: "Mug" -} -item { - name: "/m/046dlr" - id: 352 - display_name: "Alarm clock" -} -item { - name: "/m/0h8ntjv" - id: 353 - display_name: "Pressure cooker" -} -item { - name: "/m/0k65p" - id: 354 - display_name: "Human hand" -} -item { - name: "/m/011k07" - id: 355 - display_name: "Tortoise" -} -item { - name: "/m/03grzl" - id: 356 - display_name: "Baseball glove" -} -item { - name: "/m/06y5r" - id: 357 - display_name: "Sword" -} -item { - name: "/m/061_f" - id: 358 - display_name: "Pear" -} -item { - name: "/m/01cmb2" - id: 359 - display_name: "Miniskirt" -} -item { - name: "/m/01mqdt" - id: 360 - display_name: "Traffic sign" -} -item { - name: "/m/05r655" - id: 361 - display_name: "Girl" -} -item { - name: "/m/02p3w7d" - id: 362 - display_name: "Roller skates" -} -item { - name: "/m/029tx" - id: 363 - display_name: "Dinosaur" -} -item { - name: "/m/04m6gz" - id: 364 - display_name: "Porch" -} -item { - name: "/m/015h_t" - id: 365 - display_name: "Human beard" -} -item { - name: "/m/06pcq" - id: 366 - display_name: "Submarine sandwich" -} -item { - name: "/m/01bms0" - id: 367 - display_name: "Screwdriver" -} -item { - name: "/m/07fbm7" - id: 368 - display_name: "Strawberry" -} -item { - name: "/m/09tvcd" - id: 369 - display_name: "Wine glass" -} -item { - name: "/m/06nwz" - id: 370 - display_name: "Seafood" -} -item { - name: "/m/0dv9c" - id: 371 - display_name: "Racket" -} -item { - name: "/m/083wq" - id: 372 - display_name: "Wheel" -} -item { - name: "/m/0gd36" - id: 373 - display_name: "Sea lion" -} -item { - name: "/m/0138tl" - id: 374 - display_name: "Toy" -} -item { - name: "/m/07clx" - id: 375 - display_name: "Tea" -} -item { - name: "/m/05ctyq" - id: 376 - display_name: "Tennis ball" -} -item { - name: "/m/0bjyj5" - id: 377 - display_name: "Waste container" -} -item { - name: "/m/0dbzx" - id: 378 - display_name: "Mule" -} -item { - name: "/m/02ctlc" - id: 379 - display_name: "Cricket ball" -} -item { - name: "/m/0fp6w" - id: 380 - display_name: "Pineapple" -} -item { - name: "/m/0djtd" - id: 381 - display_name: "Coconut" -} -item { - name: "/m/0167gd" - id: 382 - display_name: "Doll" -} -item { - name: "/m/078n6m" - id: 383 - display_name: "Coffee table" -} -item { - name: "/m/0152hh" - id: 384 - display_name: "Snowman" -} -item { - name: "/m/04gth" - id: 385 - display_name: "Lavender" -} -item { - name: "/m/0ll1f78" - id: 386 - display_name: "Shrimp" -} -item { - name: "/m/0cffdh" - id: 387 - display_name: "Maple" -} -item { - name: "/m/025rp__" - id: 388 - display_name: "Cowboy hat" -} -item { - name: "/m/02_n6y" - id: 389 - display_name: "Goggles" -} -item { - name: "/m/0wdt60w" - id: 390 - display_name: "Rugby ball" -} -item { - name: "/m/0cydv" - id: 391 - display_name: "Caterpillar" -} -item { - name: "/m/01n5jq" - id: 392 - display_name: "Poster" -} -item { - name: "/m/09rvcxw" - id: 393 - display_name: "Rocket" -} -item { - name: "/m/013y1f" - id: 394 - display_name: "Organ" -} -item { - name: "/m/06ncr" - id: 395 - display_name: "Saxophone" -} -item { - name: "/m/015qff" - id: 396 - display_name: "Traffic light" -} -item { - name: "/m/024g6" - id: 397 - display_name: "Cocktail" -} -item { - name: "/m/05gqfk" - id: 398 - display_name: "Plastic bag" -} -item { - name: "/m/0dv77" - id: 399 - display_name: "Squash" -} -item { - name: "/m/052sf" - id: 400 - display_name: "Mushroom" -} -item { - name: "/m/0cdn1" - id: 401 - display_name: "Hamburger" -} -item { - name: "/m/03jbxj" - id: 402 - display_name: "Light switch" -} -item { - name: "/m/0cyfs" - id: 403 - display_name: "Parachute" -} -item { - name: "/m/0kmg4" - id: 404 - display_name: "Teddy bear" -} -item { - name: "/m/02cvgx" - id: 405 - display_name: "Winter melon" -} -item { - name: "/m/09kx5" - id: 406 - display_name: "Deer" -} -item { - name: "/m/057cc" - id: 407 - display_name: "Musical keyboard" -} -item { - name: "/m/02pkr5" - id: 408 - display_name: "Plumbing fixture" -} -item { - name: "/m/057p5t" - id: 409 - display_name: "Scoreboard" -} -item { - name: "/m/03g8mr" - id: 410 - display_name: "Baseball bat" -} -item { - name: "/m/0frqm" - id: 411 - display_name: "Envelope" -} -item { - name: "/m/03m3vtv" - id: 412 - display_name: "Adhesive tape" -} -item { - name: "/m/0584n8" - id: 413 - display_name: "Briefcase" -} -item { - name: "/m/014y4n" - id: 414 - display_name: "Paddle" -} -item { - name: "/m/01g3x7" - id: 415 - display_name: "Bow and arrow" -} -item { - name: "/m/07cx4" - id: 416 - display_name: "Telephone" -} -item { - name: "/m/07bgp" - id: 417 - display_name: "Sheep" -} -item { - name: "/m/032b3c" - id: 418 - display_name: "Jacket" -} -item { - name: "/m/01bl7v" - id: 419 - display_name: "Boy" -} -item { - name: "/m/0663v" - id: 420 - display_name: "Pizza" -} -item { - name: "/m/0cn6p" - id: 421 - display_name: "Otter" -} -item { - name: "/m/02rdsp" - id: 422 - display_name: "Office supplies" -} -item { - name: "/m/02crq1" - id: 423 - display_name: "Couch" -} -item { - name: "/m/01xqw" - id: 424 - display_name: "Cello" -} -item { - name: "/m/0cnyhnx" - id: 425 - display_name: "Bull" -} -item { - name: "/m/01x_v" - id: 426 - display_name: "Camel" -} -item { - name: "/m/018xm" - id: 427 - display_name: "Ball" -} -item { - name: "/m/09ddx" - id: 428 - display_name: "Duck" -} -item { - name: "/m/084zz" - id: 429 - display_name: "Whale" -} -item { - name: "/m/01n4qj" - id: 430 - display_name: "Shirt" -} -item { - name: "/m/07cmd" - id: 431 - display_name: "Tank" -} -item { - name: "/m/04_sv" - id: 432 - display_name: "Motorcycle" -} -item { - name: "/m/0mkg" - id: 433 - display_name: "Accordion" -} -item { - name: "/m/09d5_" - id: 434 - display_name: "Owl" -} -item { - name: "/m/0c568" - id: 435 - display_name: "Porcupine" -} -item { - name: "/m/02wbtzl" - id: 436 - display_name: "Sun hat" -} -item { - name: "/m/05bm6" - id: 437 - display_name: "Nail" -} -item { - name: "/m/01lsmm" - id: 438 - display_name: "Scissors" -} -item { - name: "/m/0dftk" - id: 439 - display_name: "Swan" -} -item { - name: "/m/0dtln" - id: 440 - display_name: "Lamp" -} -item { - name: "/m/0nl46" - id: 441 - display_name: "Crown" -} -item { - name: "/m/05r5c" - id: 442 - display_name: "Piano" -} -item { - name: "/m/06msq" - id: 443 - display_name: "Sculpture" -} -item { - name: "/m/0cd4d" - id: 444 - display_name: "Cheetah" -} -item { - name: "/m/05kms" - id: 445 - display_name: "Oboe" -} -item { - name: "/m/02jnhm" - id: 446 - display_name: "Tin can" -} -item { - name: "/m/0fldg" - id: 447 - display_name: "Mango" -} -item { - name: "/m/073bxn" - id: 448 - display_name: "Tripod" -} -item { - name: "/m/029bxz" - id: 449 - display_name: "Oven" -} -item { - name: "/m/020lf" - id: 450 - display_name: "Computer mouse" -} -item { - name: "/m/01btn" - id: 451 - display_name: "Barge" -} -item { - name: "/m/02vqfm" - id: 452 - display_name: "Coffee" -} -item { - name: "/m/06__v" - id: 453 - display_name: "Snowboard" -} -item { - name: "/m/043nyj" - id: 454 - display_name: "Common fig" -} -item { - name: "/m/0grw1" - id: 455 - display_name: "Salad" -} -item { - name: "/m/03hl4l9" - id: 456 - display_name: "Marine invertebrates" -} -item { - name: "/m/0hnnb" - id: 457 - display_name: "Umbrella" -} -item { - name: "/m/04c0y" - id: 458 - display_name: "Kangaroo" -} -item { - name: "/m/0dzf4" - id: 459 - display_name: "Human arm" -} -item { - name: "/m/07v9_z" - id: 460 - display_name: "Measuring cup" -} -item { - name: "/m/0f9_l" - id: 461 - display_name: "Snail" -} -item { - name: "/m/0703r8" - id: 462 - display_name: "Loveseat" -} -item { - name: "/m/01xyhv" - id: 463 - display_name: "Suit" -} -item { - name: "/m/01fh4r" - id: 464 - display_name: "Teapot" -} -item { - name: "/m/04dr76w" - id: 465 - display_name: "Bottle" -} -item { - name: "/m/0pcr" - id: 466 - display_name: "Alpaca" -} -item { - name: "/m/03s_tn" - id: 467 - display_name: "Kettle" -} -item { - name: "/m/07mhn" - id: 468 - display_name: "Trousers" -} -item { - name: "/m/01hrv5" - id: 469 - display_name: "Popcorn" -} -item { - name: "/m/019h78" - id: 470 - display_name: "Centipede" -} -item { - name: "/m/09kmb" - id: 471 - display_name: "Spider" -} -item { - name: "/m/0h23m" - id: 472 - display_name: "Sparrow" -} -item { - name: "/m/050gv4" - id: 473 - display_name: "Plate" -} -item { - name: "/m/01fb_0" - id: 474 - display_name: "Bagel" -} -item { - name: "/m/02w3_ws" - id: 475 - display_name: "Personal care" -} -item { - name: "/m/014j1m" - id: 476 - display_name: "Apple" -} -item { - name: "/m/01gmv2" - id: 477 - display_name: "Brassiere" -} -item { - name: "/m/04y4h8h" - id: 478 - display_name: "Bathroom cabinet" -} -item { - name: "/m/026qbn5" - id: 479 - display_name: "Studio couch" -} -item { - name: "/m/01m2v" - id: 480 - display_name: "Computer keyboard" -} -item { - name: "/m/05_5p_0" - id: 481 - display_name: "Table tennis racket" -} -item { - name: "/m/07030" - id: 482 - display_name: "Sushi" -} -item { - name: "/m/01s105" - id: 483 - display_name: "Cabinetry" -} -item { - name: "/m/033rq4" - id: 484 - display_name: "Street light" -} -item { - name: "/m/0162_1" - id: 485 - display_name: "Towel" -} -item { - name: "/m/02z51p" - id: 486 - display_name: "Nightstand" -} -item { - name: "/m/06mf6" - id: 487 - display_name: "Rabbit" -} -item { - name: "/m/02hj4" - id: 488 - display_name: "Dolphin" -} -item { - name: "/m/0bt9lr" - id: 489 - display_name: "Dog" -} -item { - name: "/m/08hvt4" - id: 490 - display_name: "Jug" -} -item { - name: "/m/084rd" - id: 491 - display_name: "Wok" -} -item { - name: "/m/01pns0" - id: 492 - display_name: "Fire hydrant" -} -item { - name: "/m/014sv8" - id: 493 - display_name: "Human eye" -} -item { - name: "/m/079cl" - id: 494 - display_name: "Skyscraper" -} -item { - name: "/m/01940j" - id: 495 - display_name: "Backpack" -} -item { - name: "/m/05vtc" - id: 496 - display_name: "Potato" -} -item { - name: "/m/02w3r3" - id: 497 - display_name: "Paper towel" -} -item { - name: "/m/054xkw" - id: 498 - display_name: "Lifejacket" -} -item { - name: "/m/01bqk0" - id: 499 - display_name: "Bicycle wheel" -} -item { - name: "/m/09g1w" - id: 500 - display_name: "Toilet" -} diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/pascal_label_map.pbtxt b/research/mlperf_object_detection/Mask_RCNN/object_detection/data/pascal_label_map.pbtxt deleted file mode 100644 index c9e9e2aff..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/pascal_label_map.pbtxt +++ /dev/null @@ -1,99 +0,0 @@ -item { - id: 1 - name: 'aeroplane' -} - -item { - id: 2 - name: 'bicycle' -} - -item { - id: 3 - name: 'bird' -} - -item { - id: 4 - name: 'boat' -} - -item { - id: 5 - name: 'bottle' -} - -item { - id: 6 - name: 'bus' -} - -item { - id: 7 - name: 'car' -} - -item { - id: 8 - name: 'cat' -} - -item { - id: 9 - name: 'chair' -} - -item { - id: 10 - name: 'cow' -} - -item { - id: 11 - name: 'diningtable' -} - -item { - id: 12 - name: 'dog' -} - -item { - id: 13 - name: 'horse' -} - -item { - id: 14 - name: 'motorbike' -} - -item { - id: 15 - name: 'person' -} - -item { - id: 16 - name: 'pottedplant' -} - -item { - id: 17 - name: 'sheep' -} - -item { - id: 18 - name: 'sofa' -} - -item { - id: 19 - name: 'train' -} - -item { - id: 20 - name: 'tvmonitor' -} diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/pet_label_map.pbtxt b/research/mlperf_object_detection/Mask_RCNN/object_detection/data/pet_label_map.pbtxt deleted file mode 100644 index 54d7d3518..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data/pet_label_map.pbtxt +++ /dev/null @@ -1,184 +0,0 @@ -item { - id: 1 - name: 'Abyssinian' -} - -item { - id: 2 - name: 'american_bulldog' -} - -item { - id: 3 - name: 'american_pit_bull_terrier' -} - -item { - id: 4 - name: 'basset_hound' -} - -item { - id: 5 - name: 'beagle' -} - -item { - id: 6 - name: 'Bengal' -} - -item { - id: 7 - name: 'Birman' -} - -item { - id: 8 - name: 'Bombay' -} - -item { - id: 9 - name: 'boxer' -} - -item { - id: 10 - name: 'British_Shorthair' -} - -item { - id: 11 - name: 'chihuahua' -} - -item { - id: 12 - name: 'Egyptian_Mau' -} - -item { - id: 13 - name: 'english_cocker_spaniel' -} - -item { - id: 14 - name: 'english_setter' -} - -item { - id: 15 - name: 'german_shorthaired' -} - -item { - id: 16 - name: 'great_pyrenees' -} - -item { - id: 17 - name: 'havanese' -} - -item { - id: 18 - name: 'japanese_chin' -} - -item { - id: 19 - name: 'keeshond' -} - -item { - id: 20 - name: 'leonberger' -} - -item { - id: 21 - name: 'Maine_Coon' -} - -item { - id: 22 - name: 'miniature_pinscher' -} - -item { - id: 23 - name: 'newfoundland' -} - -item { - id: 24 - name: 'Persian' -} - -item { - id: 25 - name: 'pomeranian' -} - -item { - id: 26 - name: 'pug' -} - -item { - id: 27 - name: 'Ragdoll' -} - -item { - id: 28 - name: 'Russian_Blue' -} - -item { - id: 29 - name: 'saint_bernard' -} - -item { - id: 30 - name: 'samoyed' -} - -item { - id: 31 - name: 'scottish_terrier' -} - -item { - id: 32 - name: 'shiba_inu' -} - -item { - id: 33 - name: 'Siamese' -} - -item { - id: 34 - name: 'Sphynx' -} - -item { - id: 35 - name: 'staffordshire_bull_terrier' -} - -item { - id: 36 - name: 'wheaten_terrier' -} - -item { - id: 37 - name: 'yorkshire_terrier' -} diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/__init__.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/tf_example_decoder.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/tf_example_decoder.py deleted file mode 100644 index 8480a14b4..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/tf_example_decoder.py +++ /dev/null @@ -1,439 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tensorflow Example proto decoder for object detection. - -A decoder to decode string tensors containing serialized tensorflow.Example -protos for object detection. -""" -import tensorflow as tf - -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import control_flow_ops -from tensorflow.python.ops import math_ops -from object_detection.core import data_decoder -from object_detection.core import standard_fields as fields -from object_detection.protos import input_reader_pb2 -from object_detection.utils import label_map_util - -slim_example_decoder = tf.contrib.slim.tfexample_decoder - - -# TODO(lzc): keep LookupTensor and BackupHandler in sync with -# tf.contrib.slim.tfexample_decoder version. -class LookupTensor(slim_example_decoder.Tensor): - """An ItemHandler that returns a parsed Tensor, the result of a lookup.""" - - def __init__(self, - tensor_key, - table, - shape_keys=None, - shape=None, - default_value=''): - """Initializes the LookupTensor handler. - - Simply calls a vocabulary (most often, a label mapping) lookup. - - Args: - tensor_key: the name of the `TFExample` feature to read the tensor from. - table: A tf.lookup table. - shape_keys: Optional name or list of names of the TF-Example feature in - which the tensor shape is stored. If a list, then each corresponds to - one dimension of the shape. - shape: Optional output shape of the `Tensor`. If provided, the `Tensor` is - reshaped accordingly. - default_value: The value used when the `tensor_key` is not found in a - particular `TFExample`. - - Raises: - ValueError: if both `shape_keys` and `shape` are specified. - """ - self._table = table - super(LookupTensor, self).__init__(tensor_key, shape_keys, shape, - default_value) - - def tensors_to_item(self, keys_to_tensors): - unmapped_tensor = super(LookupTensor, self).tensors_to_item(keys_to_tensors) - return self._table.lookup(unmapped_tensor) - - -class BackupHandler(slim_example_decoder.ItemHandler): - """An ItemHandler that tries two ItemHandlers in order.""" - - def __init__(self, handler, backup): - """Initializes the BackupHandler handler. - - If the first Handler's tensors_to_item returns a Tensor with no elements, - the second Handler is used. - - Args: - handler: The primary ItemHandler. - backup: The backup ItemHandler. - - Raises: - ValueError: if either is not an ItemHandler. - """ - if not isinstance(handler, slim_example_decoder.ItemHandler): - raise ValueError('Primary handler is of type %s instead of ItemHandler' % - type(handler)) - if not isinstance(backup, slim_example_decoder.ItemHandler): - raise ValueError( - 'Backup handler is of type %s instead of ItemHandler' % type(backup)) - self._handler = handler - self._backup = backup - super(BackupHandler, self).__init__(handler.keys + backup.keys) - - def tensors_to_item(self, keys_to_tensors): - item = self._handler.tensors_to_item(keys_to_tensors) - return control_flow_ops.cond( - pred=math_ops.equal(math_ops.reduce_prod(array_ops.shape(item)), 0), - true_fn=lambda: self._backup.tensors_to_item(keys_to_tensors), - false_fn=lambda: item) - - -class TfExampleDecoder(data_decoder.DataDecoder): - """Tensorflow Example proto decoder.""" - - def __init__(self, - load_instance_masks=False, - instance_mask_type=input_reader_pb2.NUMERICAL_MASKS, - label_map_proto_file=None, - use_display_name=False, - dct_method='', - num_keypoints=0, - num_additional_channels=0): - """Constructor sets keys_to_features and items_to_handlers. - - Args: - load_instance_masks: whether or not to load and handle instance masks. - instance_mask_type: type of instance masks. Options are provided in - input_reader.proto. This is only used if `load_instance_masks` is True. - label_map_proto_file: a file path to a - object_detection.protos.StringIntLabelMap proto. If provided, then the - mapped IDs of 'image/object/class/text' will take precedence over the - existing 'image/object/class/label' ID. Also, if provided, it is - assumed that 'image/object/class/text' will be in the data. - use_display_name: whether or not to use the `display_name` for label - mapping (instead of `name`). Only used if label_map_proto_file is - provided. - dct_method: An optional string. Defaults to None. It only takes - effect when image format is jpeg, used to specify a hint about the - algorithm used for jpeg decompression. Currently valid values - are ['INTEGER_FAST', 'INTEGER_ACCURATE']. The hint may be ignored, for - example, the jpeg library does not have that specific option. - num_keypoints: the number of keypoints per object. - num_additional_channels: how many additional channels to use. - - Raises: - ValueError: If `instance_mask_type` option is not one of - input_reader_pb2.DEFAULT, input_reader_pb2.NUMERICAL, or - input_reader_pb2.PNG_MASKS. - """ - self.keys_to_features = { - 'image/encoded': - tf.FixedLenFeature((), tf.string, default_value=''), - 'image/format': - tf.FixedLenFeature((), tf.string, default_value='jpeg'), - 'image/filename': - tf.FixedLenFeature((), tf.string, default_value=''), - 'image/key/sha256': - tf.FixedLenFeature((), tf.string, default_value=''), - 'image/source_id': - tf.FixedLenFeature((), tf.string, default_value=''), - 'image/height': - tf.FixedLenFeature((), tf.int64, default_value=1), - 'image/width': - tf.FixedLenFeature((), tf.int64, default_value=1), - # Object boxes and classes. - 'image/object/bbox/xmin': - tf.VarLenFeature(tf.float32), - 'image/object/bbox/xmax': - tf.VarLenFeature(tf.float32), - 'image/object/bbox/ymin': - tf.VarLenFeature(tf.float32), - 'image/object/bbox/ymax': - tf.VarLenFeature(tf.float32), - 'image/object/class/label': - tf.VarLenFeature(tf.int64), - 'image/object/class/text': - tf.VarLenFeature(tf.string), - 'image/object/area': - tf.VarLenFeature(tf.float32), - 'image/object/is_crowd': - tf.VarLenFeature(tf.int64), - 'image/object/difficult': - tf.VarLenFeature(tf.int64), - 'image/object/group_of': - tf.VarLenFeature(tf.int64), - 'image/object/weight': - tf.VarLenFeature(tf.float32), - } - # We are checking `dct_method` instead of passing it directly in order to - # ensure TF version 1.6 compatibility. - if dct_method: - image = slim_example_decoder.Image( - image_key='image/encoded', - format_key='image/format', - channels=3, - dct_method=dct_method) - additional_channel_image = slim_example_decoder.Image( - image_key='image/additional_channels/encoded', - format_key='image/format', - channels=1, - repeated=True, - dct_method=dct_method) - else: - image = slim_example_decoder.Image( - image_key='image/encoded', format_key='image/format', channels=3) - additional_channel_image = slim_example_decoder.Image( - image_key='image/additional_channels/encoded', - format_key='image/format', - channels=1, - repeated=True) - self.items_to_handlers = { - fields.InputDataFields.image: - image, - fields.InputDataFields.source_id: ( - slim_example_decoder.Tensor('image/source_id')), - fields.InputDataFields.key: ( - slim_example_decoder.Tensor('image/key/sha256')), - fields.InputDataFields.filename: ( - slim_example_decoder.Tensor('image/filename')), - # Object boxes and classes. - fields.InputDataFields.groundtruth_boxes: ( - slim_example_decoder.BoundingBox(['ymin', 'xmin', 'ymax', 'xmax'], - 'image/object/bbox/')), - fields.InputDataFields.groundtruth_area: - slim_example_decoder.Tensor('image/object/area'), - fields.InputDataFields.groundtruth_is_crowd: ( - slim_example_decoder.Tensor('image/object/is_crowd')), - fields.InputDataFields.groundtruth_difficult: ( - slim_example_decoder.Tensor('image/object/difficult')), - fields.InputDataFields.groundtruth_group_of: ( - slim_example_decoder.Tensor('image/object/group_of')), - fields.InputDataFields.groundtruth_weights: ( - slim_example_decoder.Tensor('image/object/weight')), - } - if num_additional_channels > 0: - self.keys_to_features[ - 'image/additional_channels/encoded'] = tf.FixedLenFeature( - (num_additional_channels,), tf.string) - self.items_to_handlers[ - fields.InputDataFields. - image_additional_channels] = additional_channel_image - self._num_keypoints = num_keypoints - if num_keypoints > 0: - self.keys_to_features['image/object/keypoint/x'] = ( - tf.VarLenFeature(tf.float32)) - self.keys_to_features['image/object/keypoint/y'] = ( - tf.VarLenFeature(tf.float32)) - self.items_to_handlers[fields.InputDataFields.groundtruth_keypoints] = ( - slim_example_decoder.ItemHandlerCallback( - ['image/object/keypoint/y', 'image/object/keypoint/x'], - self._reshape_keypoints)) - if load_instance_masks: - if instance_mask_type in (input_reader_pb2.DEFAULT, - input_reader_pb2.NUMERICAL_MASKS): - self.keys_to_features['image/object/mask'] = ( - tf.VarLenFeature(tf.float32)) - self.items_to_handlers[ - fields.InputDataFields.groundtruth_instance_masks] = ( - slim_example_decoder.ItemHandlerCallback( - ['image/object/mask', 'image/height', 'image/width'], - self._reshape_instance_masks)) - elif instance_mask_type == input_reader_pb2.PNG_MASKS: - self.keys_to_features['image/object/mask'] = tf.VarLenFeature(tf.string) - self.items_to_handlers[ - fields.InputDataFields.groundtruth_instance_masks] = ( - slim_example_decoder.ItemHandlerCallback( - ['image/object/mask', 'image/height', 'image/width'], - self._decode_png_instance_masks)) - else: - raise ValueError('Did not recognize the `instance_mask_type` option.') - if label_map_proto_file: - label_map = label_map_util.get_label_map_dict(label_map_proto_file, - use_display_name) - # We use a default_value of -1, but we expect all labels to be contained - # in the label map. - table = tf.contrib.lookup.HashTable( - initializer=tf.contrib.lookup.KeyValueTensorInitializer( - keys=tf.constant(list(label_map.keys())), - values=tf.constant(list(label_map.values()), dtype=tf.int64)), - default_value=-1) - # If the label_map_proto is provided, try to use it in conjunction with - # the class text, and fall back to a materialized ID. - # TODO(lzc): note that here we are using BackupHandler defined in this - # file(which is branching slim_example_decoder.BackupHandler). Need to - # switch back to slim_example_decoder.BackupHandler once tf 1.5 becomes - # more popular. - label_handler = BackupHandler( - LookupTensor('image/object/class/text', table, default_value=''), - slim_example_decoder.Tensor('image/object/class/label')) - else: - label_handler = slim_example_decoder.Tensor('image/object/class/label') - self.items_to_handlers[ - fields.InputDataFields.groundtruth_classes] = label_handler - - def decode(self, tf_example_string_tensor): - """Decodes serialized tensorflow example and returns a tensor dictionary. - - Args: - tf_example_string_tensor: a string tensor holding a serialized tensorflow - example proto. - - Returns: - A dictionary of the following tensors. - fields.InputDataFields.image - 3D uint8 tensor of shape [None, None, 3] - containing image. - fields.InputDataFields.source_id - string tensor containing original - image id. - fields.InputDataFields.key - string tensor with unique sha256 hash key. - fields.InputDataFields.filename - string tensor with original dataset - filename. - fields.InputDataFields.groundtruth_boxes - 2D float32 tensor of shape - [None, 4] containing box corners. - fields.InputDataFields.groundtruth_classes - 1D int64 tensor of shape - [None] containing classes for the boxes. - fields.InputDataFields.groundtruth_weights - 1D float32 tensor of - shape [None] indicating the weights of groundtruth boxes. - fields.InputDataFields.num_groundtruth_boxes - int32 scalar indicating - the number of groundtruth_boxes. - fields.InputDataFields.groundtruth_area - 1D float32 tensor of shape - [None] containing containing object mask area in pixel squared. - fields.InputDataFields.groundtruth_is_crowd - 1D bool tensor of shape - [None] indicating if the boxes enclose a crowd. - - Optional: - fields.InputDataFields.image_additional_channels - 3D uint8 tensor of - shape [None, None, num_additional_channels]. 1st dim is height; 2nd dim - is width; 3rd dim is the number of additional channels. - fields.InputDataFields.groundtruth_difficult - 1D bool tensor of shape - [None] indicating if the boxes represent `difficult` instances. - fields.InputDataFields.groundtruth_group_of - 1D bool tensor of shape - [None] indicating if the boxes represent `group_of` instances. - fields.InputDataFields.groundtruth_keypoints - 3D float32 tensor of - shape [None, None, 2] containing keypoints, where the coordinates of - the keypoints are ordered (y, x). - fields.InputDataFields.groundtruth_instance_masks - 3D float32 tensor of - shape [None, None, None] containing instance masks. - """ - serialized_example = tf.reshape(tf_example_string_tensor, shape=[]) - decoder = slim_example_decoder.TFExampleDecoder(self.keys_to_features, - self.items_to_handlers) - keys = decoder.list_items() - tensors = decoder.decode(serialized_example, items=keys) - tensor_dict = dict(zip(keys, tensors)) - is_crowd = fields.InputDataFields.groundtruth_is_crowd - tensor_dict[is_crowd] = tf.cast(tensor_dict[is_crowd], dtype=tf.bool) - tensor_dict[fields.InputDataFields.image].set_shape([None, None, 3]) - tensor_dict[fields.InputDataFields.num_groundtruth_boxes] = tf.shape( - tensor_dict[fields.InputDataFields.groundtruth_boxes])[0] - - if fields.InputDataFields.image_additional_channels in tensor_dict: - channels = tensor_dict[fields.InputDataFields.image_additional_channels] - channels = tf.squeeze(channels, axis=3) - channels = tf.transpose(channels, perm=[1, 2, 0]) - tensor_dict[fields.InputDataFields.image_additional_channels] = channels - - def default_groundtruth_weights(): - return tf.ones( - [tf.shape(tensor_dict[fields.InputDataFields.groundtruth_boxes])[0]], - dtype=tf.float32) - - tensor_dict[fields.InputDataFields.groundtruth_weights] = tf.cond( - tf.greater( - tf.shape( - tensor_dict[fields.InputDataFields.groundtruth_weights])[0], - 0), lambda: tensor_dict[fields.InputDataFields.groundtruth_weights], - default_groundtruth_weights) - return tensor_dict - - def _reshape_keypoints(self, keys_to_tensors): - """Reshape keypoints. - - The instance segmentation masks are reshaped to [num_instances, - num_keypoints, 2]. - - Args: - keys_to_tensors: a dictionary from keys to tensors. - - Returns: - A 3-D float tensor of shape [num_instances, num_keypoints, 2] with values - in {0, 1}. - """ - y = keys_to_tensors['image/object/keypoint/y'] - if isinstance(y, tf.SparseTensor): - y = tf.sparse_tensor_to_dense(y) - y = tf.expand_dims(y, 1) - x = keys_to_tensors['image/object/keypoint/x'] - if isinstance(x, tf.SparseTensor): - x = tf.sparse_tensor_to_dense(x) - x = tf.expand_dims(x, 1) - keypoints = tf.concat([y, x], 1) - keypoints = tf.reshape(keypoints, [-1, self._num_keypoints, 2]) - return keypoints - - def _reshape_instance_masks(self, keys_to_tensors): - """Reshape instance segmentation masks. - - The instance segmentation masks are reshaped to [num_instances, height, - width]. - - Args: - keys_to_tensors: a dictionary from keys to tensors. - - Returns: - A 3-D float tensor of shape [num_instances, height, width] with values - in {0, 1}. - """ - height = keys_to_tensors['image/height'] - width = keys_to_tensors['image/width'] - to_shape = tf.cast(tf.stack([-1, height, width]), tf.int32) - masks = keys_to_tensors['image/object/mask'] - if isinstance(masks, tf.SparseTensor): - masks = tf.sparse_tensor_to_dense(masks) - masks = tf.reshape(tf.to_float(tf.greater(masks, 0.0)), to_shape) - return tf.cast(masks, tf.float32) - - def _decode_png_instance_masks(self, keys_to_tensors): - """Decode PNG instance segmentation masks and stack into dense tensor. - - The instance segmentation masks are reshaped to [num_instances, height, - width]. - - Args: - keys_to_tensors: a dictionary from keys to tensors. - - Returns: - A 3-D float tensor of shape [num_instances, height, width] with values - in {0, 1}. - """ - - def decode_png_mask(image_buffer): - image = tf.squeeze( - tf.image.decode_image(image_buffer, channels=1), axis=2) - image.set_shape([None, None]) - image = tf.to_float(tf.greater(image, 0)) - return image - - png_masks = keys_to_tensors['image/object/mask'] - height = keys_to_tensors['image/height'] - width = keys_to_tensors['image/width'] - if isinstance(png_masks, tf.SparseTensor): - png_masks = tf.sparse_tensor_to_dense(png_masks, default_value='') - return tf.cond( - tf.greater(tf.size(png_masks), 0), - lambda: tf.map_fn(decode_png_mask, png_masks, dtype=tf.float32), - lambda: tf.zeros(tf.to_int32(tf.stack([0, height, width])))) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/tf_example_decoder_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/tf_example_decoder_test.py deleted file mode 100644 index b567b8c20..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/data_decoders/tf_example_decoder_test.py +++ /dev/null @@ -1,767 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.data_decoders.tf_example_decoder.""" - -import os -import numpy as np -import tensorflow as tf - -from tensorflow.core.example import example_pb2 -from tensorflow.core.example import feature_pb2 -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import test_util -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import lookup_ops -from tensorflow.python.ops import parsing_ops -from object_detection.core import standard_fields as fields -from object_detection.data_decoders import tf_example_decoder -from object_detection.protos import input_reader_pb2 - -slim_example_decoder = tf.contrib.slim.tfexample_decoder - - -class TfExampleDecoderTest(tf.test.TestCase): - - def _EncodeImage(self, image_tensor, encoding_type='jpeg'): - with self.test_session(): - if encoding_type == 'jpeg': - image_encoded = tf.image.encode_jpeg(tf.constant(image_tensor)).eval() - elif encoding_type == 'png': - image_encoded = tf.image.encode_png(tf.constant(image_tensor)).eval() - else: - raise ValueError('Invalid encoding type.') - return image_encoded - - def _DecodeImage(self, image_encoded, encoding_type='jpeg'): - with self.test_session(): - if encoding_type == 'jpeg': - image_decoded = tf.image.decode_jpeg(tf.constant(image_encoded)).eval() - elif encoding_type == 'png': - image_decoded = tf.image.decode_png(tf.constant(image_encoded)).eval() - else: - raise ValueError('Invalid encoding type.') - return image_decoded - - def _Int64Feature(self, value): - return tf.train.Feature(int64_list=tf.train.Int64List(value=value)) - - def _FloatFeature(self, value): - return tf.train.Feature(float_list=tf.train.FloatList(value=value)) - - def _BytesFeature(self, value): - if isinstance(value, list): - return tf.train.Feature(bytes_list=tf.train.BytesList(value=value)) - return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) - - def _Int64FeatureFromList(self, ndarray): - return feature_pb2.Feature( - int64_list=feature_pb2.Int64List(value=ndarray.flatten().tolist())) - - def _BytesFeatureFromList(self, ndarray): - values = ndarray.flatten().tolist() - return feature_pb2.Feature(bytes_list=feature_pb2.BytesList(value=values)) - - def testDecodeAdditionalChannels(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - - additional_channel_tensor = np.random.randint( - 256, size=(4, 5, 1)).astype(np.uint8) - encoded_additional_channel = self._EncodeImage(additional_channel_tensor) - decoded_additional_channel = self._DecodeImage(encoded_additional_channel) - - example = tf.train.Example( - features=tf.train.Features( - feature={ - 'image/encoded': - self._BytesFeature(encoded_jpeg), - 'image/additional_channels/encoded': - self._BytesFeatureFromList( - np.array([encoded_additional_channel] * 2)), - 'image/format': - self._BytesFeature('jpeg'), - 'image/source_id': - self._BytesFeature('image_id'), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder( - num_additional_channels=2) - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - self.assertAllEqual( - np.concatenate([decoded_additional_channel] * 2, axis=2), - tensor_dict[fields.InputDataFields.image_additional_channels]) - - def testDecodeExampleWithBranchedBackupHandler(self): - example1 = example_pb2.Example( - features=feature_pb2.Features( - feature={ - 'image/object/class/text': - self._BytesFeatureFromList( - np.array(['cat', 'dog', 'guinea pig'])), - 'image/object/class/label': - self._Int64FeatureFromList(np.array([42, 10, 900])) - })) - example2 = example_pb2.Example( - features=feature_pb2.Features( - feature={ - 'image/object/class/text': - self._BytesFeatureFromList( - np.array(['cat', 'dog', 'guinea pig'])), - })) - example3 = example_pb2.Example( - features=feature_pb2.Features( - feature={ - 'image/object/class/label': - self._Int64FeatureFromList(np.array([42, 10, 901])) - })) - # 'dog' -> 0, 'guinea pig' -> 1, 'cat' -> 2 - table = lookup_ops.index_table_from_tensor( - constant_op.constant(['dog', 'guinea pig', 'cat'])) - keys_to_features = { - 'image/object/class/text': parsing_ops.VarLenFeature(dtypes.string), - 'image/object/class/label': parsing_ops.VarLenFeature(dtypes.int64), - } - backup_handler = tf_example_decoder.BackupHandler( - handler=slim_example_decoder.Tensor('image/object/class/label'), - backup=tf_example_decoder.LookupTensor('image/object/class/text', - table)) - items_to_handlers = { - 'labels': backup_handler, - } - decoder = slim_example_decoder.TFExampleDecoder(keys_to_features, - items_to_handlers) - obtained_class_ids_each_example = [] - with self.test_session() as sess: - sess.run(lookup_ops.tables_initializer()) - for example in [example1, example2, example3]: - serialized_example = array_ops.reshape( - example.SerializeToString(), shape=[]) - obtained_class_ids_each_example.append( - decoder.decode(serialized_example)[0].eval()) - - self.assertAllClose([42, 10, 900], obtained_class_ids_each_example[0]) - self.assertAllClose([2, 0, 1], obtained_class_ids_each_example[1]) - self.assertAllClose([42, 10, 901], obtained_class_ids_each_example[2]) - - def testDecodeExampleWithBranchedLookup(self): - - example = example_pb2.Example(features=feature_pb2.Features(feature={ - 'image/object/class/text': self._BytesFeatureFromList( - np.array(['cat', 'dog', 'guinea pig'])), - })) - serialized_example = example.SerializeToString() - # 'dog' -> 0, 'guinea pig' -> 1, 'cat' -> 2 - table = lookup_ops.index_table_from_tensor( - constant_op.constant(['dog', 'guinea pig', 'cat'])) - - with self.test_session() as sess: - sess.run(lookup_ops.tables_initializer()) - - serialized_example = array_ops.reshape(serialized_example, shape=[]) - - keys_to_features = { - 'image/object/class/text': parsing_ops.VarLenFeature(dtypes.string), - } - - items_to_handlers = { - 'labels': - tf_example_decoder.LookupTensor('image/object/class/text', table), - } - - decoder = slim_example_decoder.TFExampleDecoder(keys_to_features, - items_to_handlers) - obtained_class_ids = decoder.decode(serialized_example)[0].eval() - - self.assertAllClose([2, 0, 1], obtained_class_ids) - - def testDecodeJpegImage(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - decoded_jpeg = self._DecodeImage(encoded_jpeg) - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/source_id': self._BytesFeature('image_id'), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[fields.InputDataFields.image]. - get_shape().as_list()), [None, None, 3]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual(decoded_jpeg, tensor_dict[fields.InputDataFields.image]) - self.assertEqual('image_id', tensor_dict[fields.InputDataFields.source_id]) - - def testDecodeImageKeyAndFilename(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/key/sha256': self._BytesFeature('abc'), - 'image/filename': self._BytesFeature('filename') - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertEqual('abc', tensor_dict[fields.InputDataFields.key]) - self.assertEqual('filename', tensor_dict[fields.InputDataFields.filename]) - - def testDecodePngImage(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_png = self._EncodeImage(image_tensor, encoding_type='png') - decoded_png = self._DecodeImage(encoded_png, encoding_type='png') - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_png), - 'image/format': self._BytesFeature('png'), - 'image/source_id': self._BytesFeature('image_id') - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[fields.InputDataFields.image]. - get_shape().as_list()), [None, None, 3]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual(decoded_png, tensor_dict[fields.InputDataFields.image]) - self.assertEqual('image_id', tensor_dict[fields.InputDataFields.source_id]) - - def testDecodePngInstanceMasks(self): - image_tensor = np.random.randint(256, size=(10, 10, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - mask_1 = np.random.randint(0, 2, size=(10, 10, 1)).astype(np.uint8) - mask_2 = np.random.randint(0, 2, size=(10, 10, 1)).astype(np.uint8) - encoded_png_1 = self._EncodeImage(mask_1, encoding_type='png') - decoded_png_1 = np.squeeze(mask_1.astype(np.float32)) - encoded_png_2 = self._EncodeImage(mask_2, encoding_type='png') - decoded_png_2 = np.squeeze(mask_2.astype(np.float32)) - encoded_masks = [encoded_png_1, encoded_png_2] - decoded_masks = np.stack([decoded_png_1, decoded_png_2]) - example = tf.train.Example( - features=tf.train.Features( - feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/mask': self._BytesFeature(encoded_masks) - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder( - load_instance_masks=True, instance_mask_type=input_reader_pb2.PNG_MASKS) - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual( - decoded_masks, - tensor_dict[fields.InputDataFields.groundtruth_instance_masks]) - - def testDecodeEmptyPngInstanceMasks(self): - image_tensor = np.random.randint(256, size=(10, 10, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - encoded_masks = [] - example = tf.train.Example( - features=tf.train.Features( - feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/mask': self._BytesFeature(encoded_masks), - 'image/height': self._Int64Feature([10]), - 'image/width': self._Int64Feature([10]), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder( - load_instance_masks=True, instance_mask_type=input_reader_pb2.PNG_MASKS) - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - self.assertAllEqual( - tensor_dict[fields.InputDataFields.groundtruth_instance_masks].shape, - [0, 10, 10]) - - def testDecodeBoundingBox(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - bbox_ymins = [0.0, 4.0] - bbox_xmins = [1.0, 5.0] - bbox_ymaxs = [2.0, 6.0] - bbox_xmaxs = [3.0, 7.0] - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/bbox/ymin': self._FloatFeature(bbox_ymins), - 'image/object/bbox/xmin': self._FloatFeature(bbox_xmins), - 'image/object/bbox/ymax': self._FloatFeature(bbox_ymaxs), - 'image/object/bbox/xmax': self._FloatFeature(bbox_xmaxs), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[fields.InputDataFields.groundtruth_boxes]. - get_shape().as_list()), [None, 4]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - expected_boxes = np.vstack([bbox_ymins, bbox_xmins, - bbox_ymaxs, bbox_xmaxs]).transpose() - self.assertAllEqual(expected_boxes, - tensor_dict[fields.InputDataFields.groundtruth_boxes]) - self.assertAllEqual( - 2, tensor_dict[fields.InputDataFields.num_groundtruth_boxes]) - - @test_util.enable_c_shapes - def testDecodeKeypoint(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - bbox_ymins = [0.0, 4.0] - bbox_xmins = [1.0, 5.0] - bbox_ymaxs = [2.0, 6.0] - bbox_xmaxs = [3.0, 7.0] - keypoint_ys = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] - keypoint_xs = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/bbox/ymin': self._FloatFeature(bbox_ymins), - 'image/object/bbox/xmin': self._FloatFeature(bbox_xmins), - 'image/object/bbox/ymax': self._FloatFeature(bbox_ymaxs), - 'image/object/bbox/xmax': self._FloatFeature(bbox_xmaxs), - 'image/object/keypoint/y': self._FloatFeature(keypoint_ys), - 'image/object/keypoint/x': self._FloatFeature(keypoint_xs), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder(num_keypoints=3) - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[fields.InputDataFields.groundtruth_boxes]. - get_shape().as_list()), [None, 4]) - self.assertAllEqual((tensor_dict[fields.InputDataFields. - groundtruth_keypoints]. - get_shape().as_list()), [2, 3, 2]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - expected_boxes = np.vstack([bbox_ymins, bbox_xmins, - bbox_ymaxs, bbox_xmaxs]).transpose() - self.assertAllEqual(expected_boxes, - tensor_dict[fields.InputDataFields.groundtruth_boxes]) - self.assertAllEqual( - 2, tensor_dict[fields.InputDataFields.num_groundtruth_boxes]) - - expected_keypoints = ( - np.vstack([keypoint_ys, keypoint_xs]).transpose().reshape((2, 3, 2))) - self.assertAllEqual(expected_keypoints, - tensor_dict[ - fields.InputDataFields.groundtruth_keypoints]) - - def testDecodeDefaultGroundtruthWeights(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - bbox_ymins = [0.0, 4.0] - bbox_xmins = [1.0, 5.0] - bbox_ymaxs = [2.0, 6.0] - bbox_xmaxs = [3.0, 7.0] - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/bbox/ymin': self._FloatFeature(bbox_ymins), - 'image/object/bbox/xmin': self._FloatFeature(bbox_xmins), - 'image/object/bbox/ymax': self._FloatFeature(bbox_ymaxs), - 'image/object/bbox/xmax': self._FloatFeature(bbox_xmaxs), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[fields.InputDataFields.groundtruth_boxes]. - get_shape().as_list()), [None, 4]) - - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllClose(tensor_dict[fields.InputDataFields.groundtruth_weights], - np.ones(2, dtype=np.float32)) - - @test_util.enable_c_shapes - def testDecodeObjectLabel(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - bbox_classes = [0, 1] - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/class/label': self._Int64Feature(bbox_classes), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[ - fields.InputDataFields.groundtruth_classes].get_shape().as_list()), - [2]) - - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual(bbox_classes, - tensor_dict[fields.InputDataFields.groundtruth_classes]) - - def testDecodeObjectLabelNoText(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - bbox_classes = [1, 2] - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/class/label': self._Int64Feature(bbox_classes), - })).SerializeToString() - label_map_string = """ - item { - id:1 - name:'cat' - } - item { - id:2 - name:'dog' - } - """ - label_map_path = os.path.join(self.get_temp_dir(), 'label_map.pbtxt') - with tf.gfile.Open(label_map_path, 'wb') as f: - f.write(label_map_string) - - example_decoder = tf_example_decoder.TfExampleDecoder( - label_map_proto_file=label_map_path) - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[ - fields.InputDataFields.groundtruth_classes].get_shape().as_list()), - [None]) - - init = tf.tables_initializer() - with self.test_session() as sess: - sess.run(init) - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual(bbox_classes, - tensor_dict[fields.InputDataFields.groundtruth_classes]) - - def testDecodeObjectLabelUnrecognizedName(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - bbox_classes_text = ['cat', 'cheetah'] - example = tf.train.Example( - features=tf.train.Features( - feature={ - 'image/encoded': - self._BytesFeature(encoded_jpeg), - 'image/format': - self._BytesFeature('jpeg'), - 'image/object/class/text': - self._BytesFeature(bbox_classes_text), - })).SerializeToString() - - label_map_string = """ - item { - id:2 - name:'cat' - } - item { - id:1 - name:'dog' - } - """ - label_map_path = os.path.join(self.get_temp_dir(), 'label_map.pbtxt') - with tf.gfile.Open(label_map_path, 'wb') as f: - f.write(label_map_string) - example_decoder = tf_example_decoder.TfExampleDecoder( - label_map_proto_file=label_map_path) - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[fields.InputDataFields.groundtruth_classes] - .get_shape().as_list()), [None]) - - with self.test_session() as sess: - sess.run(tf.tables_initializer()) - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual([2, -1], - tensor_dict[fields.InputDataFields.groundtruth_classes]) - - def testDecodeObjectLabelWithMapping(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - bbox_classes_text = ['cat', 'dog'] - example = tf.train.Example( - features=tf.train.Features( - feature={ - 'image/encoded': - self._BytesFeature(encoded_jpeg), - 'image/format': - self._BytesFeature('jpeg'), - 'image/object/class/text': - self._BytesFeature(bbox_classes_text), - })).SerializeToString() - - label_map_string = """ - item { - id:3 - name:'cat' - } - item { - id:1 - name:'dog' - } - """ - label_map_path = os.path.join(self.get_temp_dir(), 'label_map.pbtxt') - with tf.gfile.Open(label_map_path, 'wb') as f: - f.write(label_map_string) - example_decoder = tf_example_decoder.TfExampleDecoder( - label_map_proto_file=label_map_path) - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[fields.InputDataFields.groundtruth_classes] - .get_shape().as_list()), [None]) - - with self.test_session() as sess: - sess.run(tf.tables_initializer()) - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual([3, 1], - tensor_dict[fields.InputDataFields.groundtruth_classes]) - - @test_util.enable_c_shapes - def testDecodeObjectArea(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - object_area = [100., 174.] - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/area': self._FloatFeature(object_area), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[fields.InputDataFields.groundtruth_area]. - get_shape().as_list()), [2]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual(object_area, - tensor_dict[fields.InputDataFields.groundtruth_area]) - - @test_util.enable_c_shapes - def testDecodeObjectIsCrowd(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - object_is_crowd = [0, 1] - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/is_crowd': self._Int64Feature(object_is_crowd), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[ - fields.InputDataFields.groundtruth_is_crowd].get_shape().as_list()), - [2]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual([bool(item) for item in object_is_crowd], - tensor_dict[ - fields.InputDataFields.groundtruth_is_crowd]) - - @test_util.enable_c_shapes - def testDecodeObjectDifficult(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - object_difficult = [0, 1] - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/difficult': self._Int64Feature(object_difficult), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[ - fields.InputDataFields.groundtruth_difficult].get_shape().as_list()), - [2]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual([bool(item) for item in object_difficult], - tensor_dict[ - fields.InputDataFields.groundtruth_difficult]) - - @test_util.enable_c_shapes - def testDecodeObjectGroupOf(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - object_group_of = [0, 1] - example = tf.train.Example(features=tf.train.Features( - feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/group_of': self._Int64Feature(object_group_of), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[ - fields.InputDataFields.groundtruth_group_of].get_shape().as_list()), - [2]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual( - [bool(item) for item in object_group_of], - tensor_dict[fields.InputDataFields.groundtruth_group_of]) - - def testDecodeObjectWeight(self): - image_tensor = np.random.randint(256, size=(4, 5, 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - object_weights = [0.75, 1.0] - example = tf.train.Example(features=tf.train.Features( - feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/object/weight': self._FloatFeature(object_weights), - })).SerializeToString() - - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual((tensor_dict[ - fields.InputDataFields.groundtruth_weights].get_shape().as_list()), - [None]) - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual( - object_weights, - tensor_dict[fields.InputDataFields.groundtruth_weights]) - - @test_util.enable_c_shapes - def testDecodeInstanceSegmentation(self): - num_instances = 4 - image_height = 5 - image_width = 3 - - # Randomly generate image. - image_tensor = np.random.randint(256, size=(image_height, - image_width, - 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - - # Randomly generate instance segmentation masks. - instance_masks = ( - np.random.randint(2, size=(num_instances, - image_height, - image_width)).astype(np.float32)) - instance_masks_flattened = np.reshape(instance_masks, [-1]) - - # Randomly generate class labels for each instance. - object_classes = np.random.randint( - 100, size=(num_instances)).astype(np.int64) - - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/height': self._Int64Feature([image_height]), - 'image/width': self._Int64Feature([image_width]), - 'image/object/mask': self._FloatFeature(instance_masks_flattened), - 'image/object/class/label': self._Int64Feature( - object_classes)})).SerializeToString() - example_decoder = tf_example_decoder.TfExampleDecoder( - load_instance_masks=True) - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - - self.assertAllEqual(( - tensor_dict[fields.InputDataFields.groundtruth_instance_masks]. - get_shape().as_list()), [4, 5, 3]) - - self.assertAllEqual(( - tensor_dict[fields.InputDataFields.groundtruth_classes]. - get_shape().as_list()), [4]) - - with self.test_session() as sess: - tensor_dict = sess.run(tensor_dict) - - self.assertAllEqual( - instance_masks.astype(np.float32), - tensor_dict[fields.InputDataFields.groundtruth_instance_masks]) - self.assertAllEqual( - object_classes, - tensor_dict[fields.InputDataFields.groundtruth_classes]) - - def testInstancesNotAvailableByDefault(self): - num_instances = 4 - image_height = 5 - image_width = 3 - # Randomly generate image. - image_tensor = np.random.randint(256, size=(image_height, - image_width, - 3)).astype(np.uint8) - encoded_jpeg = self._EncodeImage(image_tensor) - - # Randomly generate instance segmentation masks. - instance_masks = ( - np.random.randint(2, size=(num_instances, - image_height, - image_width)).astype(np.float32)) - instance_masks_flattened = np.reshape(instance_masks, [-1]) - - # Randomly generate class labels for each instance. - object_classes = np.random.randint( - 100, size=(num_instances)).astype(np.int64) - - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': self._BytesFeature(encoded_jpeg), - 'image/format': self._BytesFeature('jpeg'), - 'image/height': self._Int64Feature([image_height]), - 'image/width': self._Int64Feature([image_width]), - 'image/object/mask': self._FloatFeature(instance_masks_flattened), - 'image/object/class/label': self._Int64Feature( - object_classes)})).SerializeToString() - example_decoder = tf_example_decoder.TfExampleDecoder() - tensor_dict = example_decoder.decode(tf.convert_to_tensor(example)) - self.assertTrue(fields.InputDataFields.groundtruth_instance_masks - not in tensor_dict) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/__init__.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_coco_tf_record.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_coco_tf_record.py deleted file mode 100644 index 9928443d8..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_coco_tf_record.py +++ /dev/null @@ -1,273 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -r"""Convert raw COCO dataset to TFRecord for object_detection. - -Example usage: - python create_coco_tf_record.py --logtostderr \ - --train_image_dir="${TRAIN_IMAGE_DIR}" \ - --val_image_dir="${VAL_IMAGE_DIR}" \ - --test_image_dir="${TEST_IMAGE_DIR}" \ - --train_annotations_file="${TRAIN_ANNOTATIONS_FILE}" \ - --val_annotations_file="${VAL_ANNOTATIONS_FILE}" \ - --testdev_annotations_file="${TESTDEV_ANNOTATIONS_FILE}" \ - --output_dir="${OUTPUT_DIR}" -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import hashlib -import io -import json -import os -import numpy as np -import PIL.Image - -from pycocotools import mask -import tensorflow as tf - -from object_detection.utils import dataset_util -from object_detection.utils import label_map_util - - -flags = tf.app.flags -tf.flags.DEFINE_boolean('include_masks', False, - 'Whether to include instance segmentations masks ' - '(PNG encoded) in the result. default: False.') -tf.flags.DEFINE_string('train_image_dir', '', - 'Training image directory.') -tf.flags.DEFINE_string('val_image_dir', '', - 'Validation image directory.') -tf.flags.DEFINE_string('test_image_dir', '', - 'Test image directory.') -tf.flags.DEFINE_string('train_annotations_file', '', - 'Training annotations JSON file.') -tf.flags.DEFINE_string('val_annotations_file', '', - 'Validation annotations JSON file.') -tf.flags.DEFINE_string('testdev_annotations_file', '', - 'Test-dev annotations JSON file.') -tf.flags.DEFINE_string('output_dir', '/tmp/', 'Output data directory.') - -FLAGS = flags.FLAGS - -tf.logging.set_verbosity(tf.logging.INFO) - - -def create_tf_example(image, - annotations_list, - image_dir, - category_index, - include_masks=False): - """Converts image and annotations to a tf.Example proto. - - Args: - image: dict with keys: - [u'license', u'file_name', u'coco_url', u'height', u'width', - u'date_captured', u'flickr_url', u'id'] - annotations_list: - list of dicts with keys: - [u'segmentation', u'area', u'iscrowd', u'image_id', - u'bbox', u'category_id', u'id'] - Notice that bounding box coordinates in the official COCO dataset are - given as [x, y, width, height] tuples using absolute coordinates where - x, y represent the top-left (0-indexed) corner. This function converts - to the format expected by the Tensorflow Object Detection API (which is - which is [ymin, xmin, ymax, xmax] with coordinates normalized relative - to image size). - image_dir: directory containing the image files. - category_index: a dict containing COCO category information keyed - by the 'id' field of each category. See the - label_map_util.create_category_index function. - include_masks: Whether to include instance segmentations masks - (PNG encoded) in the result. default: False. - Returns: - example: The converted tf.Example - num_annotations_skipped: Number of (invalid) annotations that were ignored. - - Raises: - ValueError: if the image pointed to by data['filename'] is not a valid JPEG - """ - image_height = image['height'] - image_width = image['width'] - filename = image['file_name'] - image_id = image['id'] - - full_path = os.path.join(image_dir, filename) - with tf.gfile.GFile(full_path, 'rb') as fid: - encoded_jpg = fid.read() - encoded_jpg_io = io.BytesIO(encoded_jpg) - image = PIL.Image.open(encoded_jpg_io) - key = hashlib.sha256(encoded_jpg).hexdigest() - - xmin = [] - xmax = [] - ymin = [] - ymax = [] - is_crowd = [] - category_names = [] - category_ids = [] - area = [] - encoded_mask_png = [] - num_annotations_skipped = 0 - for object_annotations in annotations_list: - (x, y, width, height) = tuple(object_annotations['bbox']) - if width <= 0 or height <= 0: - num_annotations_skipped += 1 - continue - if x + width > image_width or y + height > image_height: - num_annotations_skipped += 1 - continue - xmin.append(float(x) / image_width) - xmax.append(float(x + width) / image_width) - ymin.append(float(y) / image_height) - ymax.append(float(y + height) / image_height) - is_crowd.append(object_annotations['iscrowd']) - category_id = int(object_annotations['category_id']) - category_ids.append(category_id) - category_names.append(category_index[category_id]['name'].encode('utf8')) - area.append(object_annotations['area']) - - if include_masks: - run_len_encoding = mask.frPyObjects(object_annotations['segmentation'], - image_height, image_width) - binary_mask = mask.decode(run_len_encoding) - if not object_annotations['iscrowd']: - binary_mask = np.amax(binary_mask, axis=2) - pil_image = PIL.Image.fromarray(binary_mask) - output_io = io.BytesIO() - pil_image.save(output_io, format='PNG') - encoded_mask_png.append(output_io.getvalue()) - feature_dict = { - 'image/height': - dataset_util.int64_feature(image_height), - 'image/width': - dataset_util.int64_feature(image_width), - 'image/filename': - dataset_util.bytes_feature(filename.encode('utf8')), - 'image/source_id': - dataset_util.bytes_feature(str(image_id).encode('utf8')), - 'image/key/sha256': - dataset_util.bytes_feature(key.encode('utf8')), - 'image/encoded': - dataset_util.bytes_feature(encoded_jpg), - 'image/format': - dataset_util.bytes_feature('jpeg'.encode('utf8')), - 'image/object/bbox/xmin': - dataset_util.float_list_feature(xmin), - 'image/object/bbox/xmax': - dataset_util.float_list_feature(xmax), - 'image/object/bbox/ymin': - dataset_util.float_list_feature(ymin), - 'image/object/bbox/ymax': - dataset_util.float_list_feature(ymax), - 'image/object/class/label': - dataset_util.int64_list_feature(category_ids), - 'image/object/is_crowd': - dataset_util.int64_list_feature(is_crowd), - 'image/object/area': - dataset_util.float_list_feature(area), - } - if include_masks: - feature_dict['image/object/mask'] = ( - dataset_util.bytes_list_feature(encoded_mask_png)) - example = tf.train.Example(features=tf.train.Features(feature=feature_dict)) - return key, example, num_annotations_skipped - - -def _create_tf_record_from_coco_annotations( - annotations_file, image_dir, output_path, include_masks): - """Loads COCO annotation json files and converts to tf.Record format. - - Args: - annotations_file: JSON file containing bounding box annotations. - image_dir: Directory containing the image files. - output_path: Path to output tf.Record file. - include_masks: Whether to include instance segmentations masks - (PNG encoded) in the result. default: False. - """ - with tf.gfile.GFile(annotations_file, 'r') as fid: - groundtruth_data = json.load(fid) - images = groundtruth_data['images'] - category_index = label_map_util.create_category_index( - groundtruth_data['categories']) - - annotations_index = {} - if 'annotations' in groundtruth_data: - tf.logging.info( - 'Found groundtruth annotations. Building annotations index.') - for annotation in groundtruth_data['annotations']: - image_id = annotation['image_id'] - if image_id not in annotations_index: - annotations_index[image_id] = [] - annotations_index[image_id].append(annotation) - missing_annotation_count = 0 - for image in images: - image_id = image['id'] - if image_id not in annotations_index: - missing_annotation_count += 1 - annotations_index[image_id] = [] - tf.logging.info('%d images are missing annotations.', - missing_annotation_count) - - tf.logging.info('writing to output path: %s', output_path) - writer = tf.python_io.TFRecordWriter(output_path) - total_num_annotations_skipped = 0 - for idx, image in enumerate(images): - if idx % 100 == 0: - tf.logging.info('On image %d of %d', idx, len(images)) - annotations_list = annotations_index[image['id']] - _, tf_example, num_annotations_skipped = create_tf_example( - image, annotations_list, image_dir, category_index, include_masks) - total_num_annotations_skipped += num_annotations_skipped - writer.write(tf_example.SerializeToString()) - writer.close() - tf.logging.info('Finished writing, skipped %d annotations.', - total_num_annotations_skipped) - - -def main(_): - assert FLAGS.train_image_dir, '`train_image_dir` missing.' - assert FLAGS.val_image_dir, '`val_image_dir` missing.' - assert FLAGS.test_image_dir, '`test_image_dir` missing.' - assert FLAGS.train_annotations_file, '`train_annotations_file` missing.' - assert FLAGS.val_annotations_file, '`val_annotations_file` missing.' - assert FLAGS.testdev_annotations_file, '`testdev_annotations_file` missing.' - - if not tf.gfile.IsDirectory(FLAGS.output_dir): - tf.gfile.MakeDirs(FLAGS.output_dir) - train_output_path = os.path.join(FLAGS.output_dir, 'coco_train.record') - val_output_path = os.path.join(FLAGS.output_dir, 'coco_val.record') - testdev_output_path = os.path.join(FLAGS.output_dir, 'coco_testdev.record') - - _create_tf_record_from_coco_annotations( - FLAGS.train_annotations_file, - FLAGS.train_image_dir, - train_output_path, - FLAGS.include_masks) - _create_tf_record_from_coco_annotations( - FLAGS.val_annotations_file, - FLAGS.val_image_dir, - val_output_path, - FLAGS.include_masks) - _create_tf_record_from_coco_annotations( - FLAGS.testdev_annotations_file, - FLAGS.test_image_dir, - testdev_output_path, - FLAGS.include_masks) - - -if __name__ == '__main__': - tf.app.run() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_coco_tf_record_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_coco_tf_record_test.py deleted file mode 100644 index 45697eeff..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_coco_tf_record_test.py +++ /dev/null @@ -1,188 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Test for create_coco_tf_record.py.""" - -import io -import os - -import numpy as np -import PIL.Image -import tensorflow as tf - -from object_detection.dataset_tools import create_coco_tf_record - - -class CreateCocoTFRecordTest(tf.test.TestCase): - - def _assertProtoEqual(self, proto_field, expectation): - """Helper function to assert if a proto field equals some value. - - Args: - proto_field: The protobuf field to compare. - expectation: The expected value of the protobuf field. - """ - proto_list = [p for p in proto_field] - self.assertListEqual(proto_list, expectation) - - def test_create_tf_example(self): - image_file_name = 'tmp_image.jpg' - image_data = np.random.rand(256, 256, 3) - tmp_dir = self.get_temp_dir() - save_path = os.path.join(tmp_dir, image_file_name) - image = PIL.Image.fromarray(image_data, 'RGB') - image.save(save_path) - - image = { - 'file_name': image_file_name, - 'height': 256, - 'width': 256, - 'id': 11, - } - - annotations_list = [{ - 'area': .5, - 'iscrowd': False, - 'image_id': 11, - 'bbox': [64, 64, 128, 128], - 'category_id': 2, - 'id': 1000, - }] - - image_dir = tmp_dir - category_index = { - 1: { - 'name': 'dog', - 'id': 1 - }, - 2: { - 'name': 'cat', - 'id': 2 - }, - 3: { - 'name': 'human', - 'id': 3 - } - } - - (_, example, - num_annotations_skipped) = create_coco_tf_record.create_tf_example( - image, annotations_list, image_dir, category_index) - - self.assertEqual(num_annotations_skipped, 0) - self._assertProtoEqual( - example.features.feature['image/height'].int64_list.value, [256]) - self._assertProtoEqual( - example.features.feature['image/width'].int64_list.value, [256]) - self._assertProtoEqual( - example.features.feature['image/filename'].bytes_list.value, - [image_file_name]) - self._assertProtoEqual( - example.features.feature['image/source_id'].bytes_list.value, - [str(image['id'])]) - self._assertProtoEqual( - example.features.feature['image/format'].bytes_list.value, ['jpeg']) - self._assertProtoEqual( - example.features.feature['image/object/bbox/xmin'].float_list.value, - [0.25]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/ymin'].float_list.value, - [0.25]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/xmax'].float_list.value, - [0.75]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/ymax'].float_list.value, - [0.75]) - - def test_create_tf_example_with_instance_masks(self): - image_file_name = 'tmp_image.jpg' - image_data = np.random.rand(8, 8, 3) - tmp_dir = self.get_temp_dir() - save_path = os.path.join(tmp_dir, image_file_name) - image = PIL.Image.fromarray(image_data, 'RGB') - image.save(save_path) - - image = { - 'file_name': image_file_name, - 'height': 8, - 'width': 8, - 'id': 11, - } - - annotations_list = [{ - 'area': .5, - 'iscrowd': False, - 'image_id': 11, - 'bbox': [0, 0, 8, 8], - 'segmentation': [[4, 0, 0, 0, 0, 4], [8, 4, 4, 8, 8, 8]], - 'category_id': 1, - 'id': 1000, - }] - - image_dir = tmp_dir - category_index = { - 1: { - 'name': 'dog', - 'id': 1 - }, - } - - (_, example, - num_annotations_skipped) = create_coco_tf_record.create_tf_example( - image, annotations_list, image_dir, category_index, include_masks=True) - - self.assertEqual(num_annotations_skipped, 0) - self._assertProtoEqual( - example.features.feature['image/height'].int64_list.value, [8]) - self._assertProtoEqual( - example.features.feature['image/width'].int64_list.value, [8]) - self._assertProtoEqual( - example.features.feature['image/filename'].bytes_list.value, - [image_file_name]) - self._assertProtoEqual( - example.features.feature['image/source_id'].bytes_list.value, - [str(image['id'])]) - self._assertProtoEqual( - example.features.feature['image/format'].bytes_list.value, ['jpeg']) - self._assertProtoEqual( - example.features.feature['image/object/bbox/xmin'].float_list.value, - [0]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/ymin'].float_list.value, - [0]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/xmax'].float_list.value, - [1]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/ymax'].float_list.value, - [1]) - encoded_mask_pngs = [ - io.BytesIO(encoded_masks) for encoded_masks in example.features.feature[ - 'image/object/mask'].bytes_list.value - ] - pil_masks = [ - np.array(PIL.Image.open(encoded_mask_png)) - for encoded_mask_png in encoded_mask_pngs - ] - self.assertTrue(len(pil_masks) == 1) - self.assertAllEqual(pil_masks[0], - [[1, 1, 1, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0, 0], - [1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 1], - [0, 0, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 1, 1, 1, 1]]) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_kitti_tf_record.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_kitti_tf_record.py deleted file mode 100644 index c612db991..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_kitti_tf_record.py +++ /dev/null @@ -1,310 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -r"""Convert raw KITTI detection dataset to TFRecord for object_detection. - -Converts KITTI detection dataset to TFRecords with a standard format allowing - to use this dataset to train object detectors. The raw dataset can be - downloaded from: - http://kitti.is.tue.mpg.de/kitti/data_object_image_2.zip. - http://kitti.is.tue.mpg.de/kitti/data_object_label_2.zip - Permission can be requested at the main website. - - KITTI detection dataset contains 7481 training images. Using this code with - the default settings will set aside the first 500 images as a validation set. - This can be altered using the flags, see details below. - -Example usage: - python object_detection/dataset_tools/create_kitti_tf_record.py \ - --data_dir=/home/user/kitti \ - --output_path=/home/user/kitti.record -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - - -import hashlib -import io -import os - -import numpy as np -import PIL.Image as pil -import tensorflow as tf - -from object_detection.utils import dataset_util -from object_detection.utils import label_map_util -from object_detection.utils.np_box_ops import iou - -tf.app.flags.DEFINE_string('data_dir', '', 'Location of root directory for the ' - 'data. Folder structure is assumed to be:' - '/training/label_2 (annotations) and' - '/data_object_image_2/training/image_2' - '(images).') -tf.app.flags.DEFINE_string('output_path', '', 'Path to which TFRecord files' - 'will be written. The TFRecord with the training set' - 'will be located at: _train.tfrecord.' - 'And the TFRecord with the validation set will be' - 'located at: _val.tfrecord') -tf.app.flags.DEFINE_string('classes_to_use', 'car,pedestrian,dontcare', - 'Comma separated list of class names that will be' - 'used. Adding the dontcare class will remove all' - 'bboxs in the dontcare regions.') -tf.app.flags.DEFINE_string('label_map_path', 'data/kitti_label_map.pbtxt', - 'Path to label map proto.') -tf.app.flags.DEFINE_integer('validation_set_size', '500', 'Number of images to' - 'be used as a validation set.') -FLAGS = tf.app.flags.FLAGS - - -def convert_kitti_to_tfrecords(data_dir, output_path, classes_to_use, - label_map_path, validation_set_size): - """Convert the KITTI detection dataset to TFRecords. - - Args: - data_dir: The full path to the unzipped folder containing the unzipped data - from data_object_image_2 and data_object_label_2.zip. - Folder structure is assumed to be: data_dir/training/label_2 (annotations) - and data_dir/data_object_image_2/training/image_2 (images). - output_path: The path to which TFRecord files will be written. The TFRecord - with the training set will be located at: _train.tfrecord - And the TFRecord with the validation set will be located at: - _val.tfrecord - classes_to_use: List of strings naming the classes for which data should be - converted. Use the same names as presented in the KIITI README file. - Adding dontcare class will remove all other bounding boxes that overlap - with areas marked as dontcare regions. - label_map_path: Path to label map proto - validation_set_size: How many images should be left as the validation set. - (Ffirst `validation_set_size` examples are selected to be in the - validation set). - """ - label_map_dict = label_map_util.get_label_map_dict(label_map_path) - train_count = 0 - val_count = 0 - - annotation_dir = os.path.join(data_dir, - 'training', - 'label_2') - - image_dir = os.path.join(data_dir, - 'data_object_image_2', - 'training', - 'image_2') - - train_writer = tf.python_io.TFRecordWriter('%s_train.tfrecord'% - output_path) - val_writer = tf.python_io.TFRecordWriter('%s_val.tfrecord'% - output_path) - - images = sorted(tf.gfile.ListDirectory(image_dir)) - for img_name in images: - img_num = int(img_name.split('.')[0]) - is_validation_img = img_num < validation_set_size - img_anno = read_annotation_file(os.path.join(annotation_dir, - str(img_num).zfill(6)+'.txt')) - - image_path = os.path.join(image_dir, img_name) - - # Filter all bounding boxes of this frame that are of a legal class, and - # don't overlap with a dontcare region. - # TODO(talremez) filter out targets that are truncated or heavily occluded. - annotation_for_image = filter_annotations(img_anno, classes_to_use) - - example = prepare_example(image_path, annotation_for_image, label_map_dict) - if is_validation_img: - val_writer.write(example.SerializeToString()) - val_count += 1 - else: - train_writer.write(example.SerializeToString()) - train_count += 1 - - train_writer.close() - val_writer.close() - - -def prepare_example(image_path, annotations, label_map_dict): - """Converts a dictionary with annotations for an image to tf.Example proto. - - Args: - image_path: The complete path to image. - annotations: A dictionary representing the annotation of a single object - that appears in the image. - label_map_dict: A map from string label names to integer ids. - - Returns: - example: The converted tf.Example. - """ - with tf.gfile.GFile(image_path, 'rb') as fid: - encoded_png = fid.read() - encoded_png_io = io.BytesIO(encoded_png) - image = pil.open(encoded_png_io) - image = np.asarray(image) - - key = hashlib.sha256(encoded_png).hexdigest() - - width = int(image.shape[1]) - height = int(image.shape[0]) - - xmin_norm = annotations['2d_bbox_left'] / float(width) - ymin_norm = annotations['2d_bbox_top'] / float(height) - xmax_norm = annotations['2d_bbox_right'] / float(width) - ymax_norm = annotations['2d_bbox_bottom'] / float(height) - - difficult_obj = [0]*len(xmin_norm) - - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/height': dataset_util.int64_feature(height), - 'image/width': dataset_util.int64_feature(width), - 'image/filename': dataset_util.bytes_feature(image_path.encode('utf8')), - 'image/source_id': dataset_util.bytes_feature(image_path.encode('utf8')), - 'image/key/sha256': dataset_util.bytes_feature(key.encode('utf8')), - 'image/encoded': dataset_util.bytes_feature(encoded_png), - 'image/format': dataset_util.bytes_feature('png'.encode('utf8')), - 'image/object/bbox/xmin': dataset_util.float_list_feature(xmin_norm), - 'image/object/bbox/xmax': dataset_util.float_list_feature(xmax_norm), - 'image/object/bbox/ymin': dataset_util.float_list_feature(ymin_norm), - 'image/object/bbox/ymax': dataset_util.float_list_feature(ymax_norm), - 'image/object/class/text': dataset_util.bytes_list_feature( - [x.encode('utf8') for x in annotations['type']]), - 'image/object/class/label': dataset_util.int64_list_feature( - [label_map_dict[x] for x in annotations['type']]), - 'image/object/difficult': dataset_util.int64_list_feature(difficult_obj), - 'image/object/truncated': dataset_util.float_list_feature( - annotations['truncated']), - 'image/object/alpha': dataset_util.float_list_feature( - annotations['alpha']), - 'image/object/3d_bbox/height': dataset_util.float_list_feature( - annotations['3d_bbox_height']), - 'image/object/3d_bbox/width': dataset_util.float_list_feature( - annotations['3d_bbox_width']), - 'image/object/3d_bbox/length': dataset_util.float_list_feature( - annotations['3d_bbox_length']), - 'image/object/3d_bbox/x': dataset_util.float_list_feature( - annotations['3d_bbox_x']), - 'image/object/3d_bbox/y': dataset_util.float_list_feature( - annotations['3d_bbox_y']), - 'image/object/3d_bbox/z': dataset_util.float_list_feature( - annotations['3d_bbox_z']), - 'image/object/3d_bbox/rot_y': dataset_util.float_list_feature( - annotations['3d_bbox_rot_y']), - })) - - return example - - -def filter_annotations(img_all_annotations, used_classes): - """Filters out annotations from the unused classes and dontcare regions. - - Filters out the annotations that belong to classes we do now wish to use and - (optionally) also removes all boxes that overlap with dontcare regions. - - Args: - img_all_annotations: A list of annotation dictionaries. See documentation of - read_annotation_file for more details about the format of the annotations. - used_classes: A list of strings listing the classes we want to keep, if the - list contains "dontcare", all bounding boxes with overlapping with dont - care regions will also be filtered out. - - Returns: - img_filtered_annotations: A list of annotation dictionaries that have passed - the filtering. - """ - - img_filtered_annotations = {} - - # Filter the type of the objects. - relevant_annotation_indices = [ - i for i, x in enumerate(img_all_annotations['type']) if x in used_classes - ] - - for key in img_all_annotations.keys(): - img_filtered_annotations[key] = ( - img_all_annotations[key][relevant_annotation_indices]) - - if 'dontcare' in used_classes: - dont_care_indices = [i for i, - x in enumerate(img_filtered_annotations['type']) - if x == 'dontcare'] - - # bounding box format [y_min, x_min, y_max, x_max] - all_boxes = np.stack([img_filtered_annotations['2d_bbox_top'], - img_filtered_annotations['2d_bbox_left'], - img_filtered_annotations['2d_bbox_bottom'], - img_filtered_annotations['2d_bbox_right']], - axis=1) - - ious = iou(boxes1=all_boxes, - boxes2=all_boxes[dont_care_indices]) - - # Remove all bounding boxes that overlap with a dontcare region. - if ious.size > 0: - boxes_to_remove = np.amax(ious, axis=1) > 0.0 - for key in img_all_annotations.keys(): - img_filtered_annotations[key] = ( - img_filtered_annotations[key][np.logical_not(boxes_to_remove)]) - - return img_filtered_annotations - - -def read_annotation_file(filename): - """Reads a KITTI annotation file. - - Converts a KITTI annotation file into a dictionary containing all the - relevant information. - - Args: - filename: the path to the annotataion text file. - - Returns: - anno: A dictionary with the converted annotation information. See annotation - README file for details on the different fields. - """ - with open(filename) as f: - content = f.readlines() - content = [x.strip().split(' ') for x in content] - - anno = {} - anno['type'] = np.array([x[0].lower() for x in content]) - anno['truncated'] = np.array([float(x[1]) for x in content]) - anno['occluded'] = np.array([int(x[2]) for x in content]) - anno['alpha'] = np.array([float(x[3]) for x in content]) - - anno['2d_bbox_left'] = np.array([float(x[4]) for x in content]) - anno['2d_bbox_top'] = np.array([float(x[5]) for x in content]) - anno['2d_bbox_right'] = np.array([float(x[6]) for x in content]) - anno['2d_bbox_bottom'] = np.array([float(x[7]) for x in content]) - - anno['3d_bbox_height'] = np.array([float(x[8]) for x in content]) - anno['3d_bbox_width'] = np.array([float(x[9]) for x in content]) - anno['3d_bbox_length'] = np.array([float(x[10]) for x in content]) - anno['3d_bbox_x'] = np.array([float(x[11]) for x in content]) - anno['3d_bbox_y'] = np.array([float(x[12]) for x in content]) - anno['3d_bbox_z'] = np.array([float(x[13]) for x in content]) - anno['3d_bbox_rot_y'] = np.array([float(x[14]) for x in content]) - - return anno - - -def main(_): - convert_kitti_to_tfrecords( - data_dir=FLAGS.data_dir, - output_path=FLAGS.output_path, - classes_to_use=FLAGS.classes_to_use.split(','), - label_map_path=FLAGS.label_map_path, - validation_set_size=FLAGS.validation_set_size) - -if __name__ == '__main__': - tf.app.run() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_kitti_tf_record_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_kitti_tf_record_test.py deleted file mode 100644 index 37ac4b8b1..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_kitti_tf_record_test.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Test for create_kitti_tf_record.py.""" - -import os - -import numpy as np -import PIL.Image -import tensorflow as tf - -from object_detection.dataset_tools import create_kitti_tf_record - - -class CreateKittiTFRecordTest(tf.test.TestCase): - - def _assertProtoEqual(self, proto_field, expectation): - """Helper function to assert if a proto field equals some value. - - Args: - proto_field: The protobuf field to compare. - expectation: The expected value of the protobuf field. - """ - proto_list = [p for p in proto_field] - self.assertListEqual(proto_list, expectation) - - def test_dict_to_tf_example(self): - image_file_name = 'tmp_image.jpg' - image_data = np.random.rand(256, 256, 3) - save_path = os.path.join(self.get_temp_dir(), image_file_name) - image = PIL.Image.fromarray(image_data, 'RGB') - image.save(save_path) - - annotations = {} - annotations['2d_bbox_left'] = np.array([64]) - annotations['2d_bbox_top'] = np.array([64]) - annotations['2d_bbox_right'] = np.array([192]) - annotations['2d_bbox_bottom'] = np.array([192]) - annotations['type'] = ['car'] - annotations['truncated'] = np.array([1]) - annotations['alpha'] = np.array([2]) - annotations['3d_bbox_height'] = np.array([10]) - annotations['3d_bbox_width'] = np.array([11]) - annotations['3d_bbox_length'] = np.array([12]) - annotations['3d_bbox_x'] = np.array([13]) - annotations['3d_bbox_y'] = np.array([14]) - annotations['3d_bbox_z'] = np.array([15]) - annotations['3d_bbox_rot_y'] = np.array([4]) - - label_map_dict = { - 'background': 0, - 'car': 1, - } - - example = create_kitti_tf_record.prepare_example( - save_path, - annotations, - label_map_dict) - - self._assertProtoEqual( - example.features.feature['image/height'].int64_list.value, [256]) - self._assertProtoEqual( - example.features.feature['image/width'].int64_list.value, [256]) - self._assertProtoEqual( - example.features.feature['image/filename'].bytes_list.value, - [save_path]) - self._assertProtoEqual( - example.features.feature['image/source_id'].bytes_list.value, - [save_path]) - self._assertProtoEqual( - example.features.feature['image/format'].bytes_list.value, ['png']) - self._assertProtoEqual( - example.features.feature['image/object/bbox/xmin'].float_list.value, - [0.25]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/ymin'].float_list.value, - [0.25]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/xmax'].float_list.value, - [0.75]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/ymax'].float_list.value, - [0.75]) - self._assertProtoEqual( - example.features.feature['image/object/class/text'].bytes_list.value, - ['car']) - self._assertProtoEqual( - example.features.feature['image/object/class/label'].int64_list.value, - [1]) - self._assertProtoEqual( - example.features.feature['image/object/truncated'].float_list.value, - [1]) - self._assertProtoEqual( - example.features.feature['image/object/alpha'].float_list.value, - [2]) - self._assertProtoEqual(example.features.feature[ - 'image/object/3d_bbox/height'].float_list.value, [10]) - self._assertProtoEqual( - example.features.feature['image/object/3d_bbox/width'].float_list.value, - [11]) - self._assertProtoEqual(example.features.feature[ - 'image/object/3d_bbox/length'].float_list.value, [12]) - self._assertProtoEqual( - example.features.feature['image/object/3d_bbox/x'].float_list.value, - [13]) - self._assertProtoEqual( - example.features.feature['image/object/3d_bbox/y'].float_list.value, - [14]) - self._assertProtoEqual( - example.features.feature['image/object/3d_bbox/z'].float_list.value, - [15]) - self._assertProtoEqual( - example.features.feature['image/object/3d_bbox/rot_y'].float_list.value, - [4]) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_oid_tf_record.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_oid_tf_record.py deleted file mode 100644 index 26d9699c8..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_oid_tf_record.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -r"""Creates TFRecords of Open Images dataset for object detection. - -Example usage: - python object_detection/dataset_tools/create_oid_tf_record.py \ - --input_box_annotations_csv=/path/to/input/annotations-human-bbox.csv \ - --input_image_label_annotations_csv=/path/to/input/annotations-label.csv \ - --input_images_directory=/path/to/input/image_pixels_directory \ - --input_label_map=/path/to/input/labels_bbox_545.labelmap \ - --output_tf_record_path_prefix=/path/to/output/prefix.tfrecord - -CSVs with bounding box annotations and image metadata (including the image URLs) -can be downloaded from the Open Images GitHub repository: -https://github.com/openimages/dataset - -This script will include every image found in the input_images_directory in the -output TFRecord, even if the image has no corresponding bounding box annotations -in the input_annotations_csv. If input_image_label_annotations_csv is specified, -it will add image-level labels as well. Note that the information of whether a -label is positivelly or negativelly verified is NOT added to tfrecord. -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import os - -import contextlib2 -import pandas as pd -import tensorflow as tf - -from object_detection.dataset_tools import oid_tfrecord_creation -from object_detection.dataset_tools import tf_record_creation_util -from object_detection.utils import label_map_util - -tf.flags.DEFINE_string('input_box_annotations_csv', None, - 'Path to CSV containing image bounding box annotations') -tf.flags.DEFINE_string('input_images_directory', None, - 'Directory containing the image pixels ' - 'downloaded from the OpenImages GitHub repository.') -tf.flags.DEFINE_string('input_image_label_annotations_csv', None, - 'Path to CSV containing image-level labels annotations') -tf.flags.DEFINE_string('input_label_map', None, 'Path to the label map proto') -tf.flags.DEFINE_string( - 'output_tf_record_path_prefix', None, - 'Path to the output TFRecord. The shard index and the number of shards ' - 'will be appended for each output shard.') -tf.flags.DEFINE_integer('num_shards', 100, 'Number of TFRecord shards') - -FLAGS = tf.flags.FLAGS - - -def main(_): - tf.logging.set_verbosity(tf.logging.INFO) - - required_flags = [ - 'input_box_annotations_csv', 'input_images_directory', 'input_label_map', - 'output_tf_record_path_prefix' - ] - for flag_name in required_flags: - if not getattr(FLAGS, flag_name): - raise ValueError('Flag --{} is required'.format(flag_name)) - - label_map = label_map_util.get_label_map_dict(FLAGS.input_label_map) - all_box_annotations = pd.read_csv(FLAGS.input_box_annotations_csv) - if FLAGS.input_image_label_annotations_csv: - all_label_annotations = pd.read_csv(FLAGS.input_image_label_annotations_csv) - all_label_annotations.rename( - columns={'Confidence': 'ConfidenceImageLabel'}, inplace=True) - else: - all_label_annotations = None - all_images = tf.gfile.Glob( - os.path.join(FLAGS.input_images_directory, '*.jpg')) - all_image_ids = [os.path.splitext(os.path.basename(v))[0] for v in all_images] - all_image_ids = pd.DataFrame({'ImageID': all_image_ids}) - all_annotations = pd.concat( - [all_box_annotations, all_image_ids, all_label_annotations]) - - tf.logging.log(tf.logging.INFO, 'Found %d images...', len(all_image_ids)) - - with contextlib2.ExitStack() as tf_record_close_stack: - output_tfrecords = tf_record_creation_util.open_sharded_output_tfrecords( - tf_record_close_stack, FLAGS.output_tf_record_path_prefix, - FLAGS.num_shards) - - for counter, image_data in enumerate(all_annotations.groupby('ImageID')): - tf.logging.log_every_n(tf.logging.INFO, 'Processed %d images...', 1000, - counter) - - image_id, image_annotations = image_data - # In OID image file names are formed by appending ".jpg" to the image ID. - image_path = os.path.join(FLAGS.input_images_directory, image_id + '.jpg') - with tf.gfile.Open(image_path) as image_file: - encoded_image = image_file.read() - - tf_example = oid_tfrecord_creation.tf_example_from_annotations_data_frame( - image_annotations, label_map, encoded_image) - if tf_example: - shard_idx = int(image_id, 16) % FLAGS.num_shards - output_tfrecords[shard_idx].write(tf_example.SerializeToString()) - - -if __name__ == '__main__': - tf.app.run() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pascal_tf_record.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pascal_tf_record.py deleted file mode 100644 index 813071c92..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pascal_tf_record.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -r"""Convert raw PASCAL dataset to TFRecord for object_detection. - -Example usage: - python object_detection/dataset_tools/create_pascal_tf_record.py \ - --data_dir=/home/user/VOCdevkit \ - --year=VOC2012 \ - --output_path=/home/user/pascal.record -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import hashlib -import io -import logging -import os - -from lxml import etree -import PIL.Image -import tensorflow as tf - -from object_detection.utils import dataset_util -from object_detection.utils import label_map_util - - -flags = tf.app.flags -flags.DEFINE_string('data_dir', '', 'Root directory to raw PASCAL VOC dataset.') -flags.DEFINE_string('set', 'train', 'Convert training set, validation set or ' - 'merged set.') -flags.DEFINE_string('annotations_dir', 'Annotations', - '(Relative) path to annotations directory.') -flags.DEFINE_string('year', 'VOC2007', 'Desired challenge year.') -flags.DEFINE_string('output_path', '', 'Path to output TFRecord') -flags.DEFINE_string('label_map_path', 'data/pascal_label_map.pbtxt', - 'Path to label map proto') -flags.DEFINE_boolean('ignore_difficult_instances', False, 'Whether to ignore ' - 'difficult instances') -FLAGS = flags.FLAGS - -SETS = ['train', 'val', 'trainval', 'test'] -YEARS = ['VOC2007', 'VOC2012', 'merged'] - - -def dict_to_tf_example(data, - dataset_directory, - label_map_dict, - ignore_difficult_instances=False, - image_subdirectory='JPEGImages'): - """Convert XML derived dict to tf.Example proto. - - Notice that this function normalizes the bounding box coordinates provided - by the raw data. - - Args: - data: dict holding PASCAL XML fields for a single image (obtained by - running dataset_util.recursive_parse_xml_to_dict) - dataset_directory: Path to root directory holding PASCAL dataset - label_map_dict: A map from string label names to integers ids. - ignore_difficult_instances: Whether to skip difficult instances in the - dataset (default: False). - image_subdirectory: String specifying subdirectory within the - PASCAL dataset directory holding the actual image data. - - Returns: - example: The converted tf.Example. - - Raises: - ValueError: if the image pointed to by data['filename'] is not a valid JPEG - """ - img_path = os.path.join(data['folder'], image_subdirectory, data['filename']) - full_path = os.path.join(dataset_directory, img_path) - with tf.gfile.GFile(full_path, 'rb') as fid: - encoded_jpg = fid.read() - encoded_jpg_io = io.BytesIO(encoded_jpg) - image = PIL.Image.open(encoded_jpg_io) - if image.format != 'JPEG': - raise ValueError('Image format not JPEG') - key = hashlib.sha256(encoded_jpg).hexdigest() - - width = int(data['size']['width']) - height = int(data['size']['height']) - - xmin = [] - ymin = [] - xmax = [] - ymax = [] - classes = [] - classes_text = [] - truncated = [] - poses = [] - difficult_obj = [] - if 'object' in data: - for obj in data['object']: - difficult = bool(int(obj['difficult'])) - if ignore_difficult_instances and difficult: - continue - - difficult_obj.append(int(difficult)) - - xmin.append(float(obj['bndbox']['xmin']) / width) - ymin.append(float(obj['bndbox']['ymin']) / height) - xmax.append(float(obj['bndbox']['xmax']) / width) - ymax.append(float(obj['bndbox']['ymax']) / height) - classes_text.append(obj['name'].encode('utf8')) - classes.append(label_map_dict[obj['name']]) - truncated.append(int(obj['truncated'])) - poses.append(obj['pose'].encode('utf8')) - - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/height': dataset_util.int64_feature(height), - 'image/width': dataset_util.int64_feature(width), - 'image/filename': dataset_util.bytes_feature( - data['filename'].encode('utf8')), - 'image/source_id': dataset_util.bytes_feature( - data['filename'].encode('utf8')), - 'image/key/sha256': dataset_util.bytes_feature(key.encode('utf8')), - 'image/encoded': dataset_util.bytes_feature(encoded_jpg), - 'image/format': dataset_util.bytes_feature('jpeg'.encode('utf8')), - 'image/object/bbox/xmin': dataset_util.float_list_feature(xmin), - 'image/object/bbox/xmax': dataset_util.float_list_feature(xmax), - 'image/object/bbox/ymin': dataset_util.float_list_feature(ymin), - 'image/object/bbox/ymax': dataset_util.float_list_feature(ymax), - 'image/object/class/text': dataset_util.bytes_list_feature(classes_text), - 'image/object/class/label': dataset_util.int64_list_feature(classes), - 'image/object/difficult': dataset_util.int64_list_feature(difficult_obj), - 'image/object/truncated': dataset_util.int64_list_feature(truncated), - 'image/object/view': dataset_util.bytes_list_feature(poses), - })) - return example - - -def main(_): - if FLAGS.set not in SETS: - raise ValueError('set must be in : {}'.format(SETS)) - if FLAGS.year not in YEARS: - raise ValueError('year must be in : {}'.format(YEARS)) - - data_dir = FLAGS.data_dir - years = ['VOC2007', 'VOC2012'] - if FLAGS.year != 'merged': - years = [FLAGS.year] - - writer = tf.python_io.TFRecordWriter(FLAGS.output_path) - - label_map_dict = label_map_util.get_label_map_dict(FLAGS.label_map_path) - - for year in years: - logging.info('Reading from PASCAL %s dataset.', year) - examples_path = os.path.join(data_dir, year, 'ImageSets', 'Main', - 'aeroplane_' + FLAGS.set + '.txt') - annotations_dir = os.path.join(data_dir, year, FLAGS.annotations_dir) - examples_list = dataset_util.read_examples_list(examples_path) - for idx, example in enumerate(examples_list): - if idx % 100 == 0: - logging.info('On image %d of %d', idx, len(examples_list)) - path = os.path.join(annotations_dir, example + '.xml') - with tf.gfile.GFile(path, 'r') as fid: - xml_str = fid.read() - xml = etree.fromstring(xml_str) - data = dataset_util.recursive_parse_xml_to_dict(xml)['annotation'] - - tf_example = dict_to_tf_example(data, FLAGS.data_dir, label_map_dict, - FLAGS.ignore_difficult_instances) - writer.write(tf_example.SerializeToString()) - - writer.close() - - -if __name__ == '__main__': - tf.app.run() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pascal_tf_record_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pascal_tf_record_test.py deleted file mode 100644 index 66929bd46..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pascal_tf_record_test.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Test for create_pascal_tf_record.py.""" - -import os - -import numpy as np -import PIL.Image -import tensorflow as tf - -from object_detection.dataset_tools import create_pascal_tf_record - - -class CreatePascalTFRecordTest(tf.test.TestCase): - - def _assertProtoEqual(self, proto_field, expectation): - """Helper function to assert if a proto field equals some value. - - Args: - proto_field: The protobuf field to compare. - expectation: The expected value of the protobuf field. - """ - proto_list = [p for p in proto_field] - self.assertListEqual(proto_list, expectation) - - def test_dict_to_tf_example(self): - image_file_name = 'tmp_image.jpg' - image_data = np.random.rand(256, 256, 3) - save_path = os.path.join(self.get_temp_dir(), image_file_name) - image = PIL.Image.fromarray(image_data, 'RGB') - image.save(save_path) - - data = { - 'folder': '', - 'filename': image_file_name, - 'size': { - 'height': 256, - 'width': 256, - }, - 'object': [ - { - 'difficult': 1, - 'bndbox': { - 'xmin': 64, - 'ymin': 64, - 'xmax': 192, - 'ymax': 192, - }, - 'name': 'person', - 'truncated': 0, - 'pose': '', - }, - ], - } - - label_map_dict = { - 'background': 0, - 'person': 1, - 'notperson': 2, - } - - example = create_pascal_tf_record.dict_to_tf_example( - data, self.get_temp_dir(), label_map_dict, image_subdirectory='') - self._assertProtoEqual( - example.features.feature['image/height'].int64_list.value, [256]) - self._assertProtoEqual( - example.features.feature['image/width'].int64_list.value, [256]) - self._assertProtoEqual( - example.features.feature['image/filename'].bytes_list.value, - [image_file_name]) - self._assertProtoEqual( - example.features.feature['image/source_id'].bytes_list.value, - [image_file_name]) - self._assertProtoEqual( - example.features.feature['image/format'].bytes_list.value, ['jpeg']) - self._assertProtoEqual( - example.features.feature['image/object/bbox/xmin'].float_list.value, - [0.25]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/ymin'].float_list.value, - [0.25]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/xmax'].float_list.value, - [0.75]) - self._assertProtoEqual( - example.features.feature['image/object/bbox/ymax'].float_list.value, - [0.75]) - self._assertProtoEqual( - example.features.feature['image/object/class/text'].bytes_list.value, - ['person']) - self._assertProtoEqual( - example.features.feature['image/object/class/label'].int64_list.value, - [1]) - self._assertProtoEqual( - example.features.feature['image/object/difficult'].int64_list.value, - [1]) - self._assertProtoEqual( - example.features.feature['image/object/truncated'].int64_list.value, - [0]) - self._assertProtoEqual( - example.features.feature['image/object/view'].bytes_list.value, ['']) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pet_tf_record.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pet_tf_record.py deleted file mode 100644 index 9b3b55c60..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/create_pet_tf_record.py +++ /dev/null @@ -1,318 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -r"""Convert the Oxford pet dataset to TFRecord for object_detection. - -See: O. M. Parkhi, A. Vedaldi, A. Zisserman, C. V. Jawahar - Cats and Dogs - IEEE Conference on Computer Vision and Pattern Recognition, 2012 - http://www.robots.ox.ac.uk/~vgg/data/pets/ - -Example usage: - python object_detection/dataset_tools/create_pet_tf_record.py \ - --data_dir=/home/user/pet \ - --output_dir=/home/user/pet/output -""" - -import hashlib -import io -import logging -import os -import random -import re - -import contextlib2 -from lxml import etree -import numpy as np -import PIL.Image -import tensorflow as tf - -from object_detection.dataset_tools import tf_record_creation_util -from object_detection.utils import dataset_util -from object_detection.utils import label_map_util - -flags = tf.app.flags -flags.DEFINE_string('data_dir', '', 'Root directory to raw pet dataset.') -flags.DEFINE_string('output_dir', '', 'Path to directory to output TFRecords.') -flags.DEFINE_string('label_map_path', 'data/pet_label_map.pbtxt', - 'Path to label map proto') -flags.DEFINE_boolean('faces_only', True, 'If True, generates bounding boxes ' - 'for pet faces. Otherwise generates bounding boxes (as ' - 'well as segmentations for full pet bodies). Note that ' - 'in the latter case, the resulting files are much larger.') -flags.DEFINE_string('mask_type', 'png', 'How to represent instance ' - 'segmentation masks. Options are "png" or "numerical".') -flags.DEFINE_integer('num_shards', 10, 'Number of TFRecord shards') - -FLAGS = flags.FLAGS - - -def get_class_name_from_filename(file_name): - """Gets the class name from a file. - - Args: - file_name: The file name to get the class name from. - ie. "american_pit_bull_terrier_105.jpg" - - Returns: - A string of the class name. - """ - match = re.match(r'([A-Za-z_]+)(_[0-9]+\.jpg)', file_name, re.I) - return match.groups()[0] - - -def dict_to_tf_example(data, - mask_path, - label_map_dict, - image_subdirectory, - ignore_difficult_instances=False, - faces_only=True, - mask_type='png'): - """Convert XML derived dict to tf.Example proto. - - Notice that this function normalizes the bounding box coordinates provided - by the raw data. - - Args: - data: dict holding PASCAL XML fields for a single image (obtained by - running dataset_util.recursive_parse_xml_to_dict) - mask_path: String path to PNG encoded mask. - label_map_dict: A map from string label names to integers ids. - image_subdirectory: String specifying subdirectory within the - Pascal dataset directory holding the actual image data. - ignore_difficult_instances: Whether to skip difficult instances in the - dataset (default: False). - faces_only: If True, generates bounding boxes for pet faces. Otherwise - generates bounding boxes (as well as segmentations for full pet bodies). - mask_type: 'numerical' or 'png'. 'png' is recommended because it leads to - smaller file sizes. - - Returns: - example: The converted tf.Example. - - Raises: - ValueError: if the image pointed to by data['filename'] is not a valid JPEG - """ - img_path = os.path.join(image_subdirectory, data['filename']) - with tf.gfile.GFile(img_path, 'rb') as fid: - encoded_jpg = fid.read() - encoded_jpg_io = io.BytesIO(encoded_jpg) - image = PIL.Image.open(encoded_jpg_io) - if image.format != 'JPEG': - raise ValueError('Image format not JPEG') - key = hashlib.sha256(encoded_jpg).hexdigest() - - with tf.gfile.GFile(mask_path, 'rb') as fid: - encoded_mask_png = fid.read() - encoded_png_io = io.BytesIO(encoded_mask_png) - mask = PIL.Image.open(encoded_png_io) - if mask.format != 'PNG': - raise ValueError('Mask format not PNG') - - mask_np = np.asarray(mask) - nonbackground_indices_x = np.any(mask_np != 2, axis=0) - nonbackground_indices_y = np.any(mask_np != 2, axis=1) - nonzero_x_indices = np.where(nonbackground_indices_x) - nonzero_y_indices = np.where(nonbackground_indices_y) - - width = int(data['size']['width']) - height = int(data['size']['height']) - - xmins = [] - ymins = [] - xmaxs = [] - ymaxs = [] - classes = [] - classes_text = [] - truncated = [] - poses = [] - difficult_obj = [] - masks = [] - if 'object' in data: - for obj in data['object']: - difficult = bool(int(obj['difficult'])) - if ignore_difficult_instances and difficult: - continue - difficult_obj.append(int(difficult)) - - if faces_only: - xmin = float(obj['bndbox']['xmin']) - xmax = float(obj['bndbox']['xmax']) - ymin = float(obj['bndbox']['ymin']) - ymax = float(obj['bndbox']['ymax']) - else: - xmin = float(np.min(nonzero_x_indices)) - xmax = float(np.max(nonzero_x_indices)) - ymin = float(np.min(nonzero_y_indices)) - ymax = float(np.max(nonzero_y_indices)) - - xmins.append(xmin / width) - ymins.append(ymin / height) - xmaxs.append(xmax / width) - ymaxs.append(ymax / height) - class_name = get_class_name_from_filename(data['filename']) - classes_text.append(class_name.encode('utf8')) - classes.append(label_map_dict[class_name]) - truncated.append(int(obj['truncated'])) - poses.append(obj['pose'].encode('utf8')) - if not faces_only: - mask_remapped = (mask_np != 2).astype(np.uint8) - masks.append(mask_remapped) - - feature_dict = { - 'image/height': dataset_util.int64_feature(height), - 'image/width': dataset_util.int64_feature(width), - 'image/filename': dataset_util.bytes_feature( - data['filename'].encode('utf8')), - 'image/source_id': dataset_util.bytes_feature( - data['filename'].encode('utf8')), - 'image/key/sha256': dataset_util.bytes_feature(key.encode('utf8')), - 'image/encoded': dataset_util.bytes_feature(encoded_jpg), - 'image/format': dataset_util.bytes_feature('jpeg'.encode('utf8')), - 'image/object/bbox/xmin': dataset_util.float_list_feature(xmins), - 'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs), - 'image/object/bbox/ymin': dataset_util.float_list_feature(ymins), - 'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs), - 'image/object/class/text': dataset_util.bytes_list_feature(classes_text), - 'image/object/class/label': dataset_util.int64_list_feature(classes), - 'image/object/difficult': dataset_util.int64_list_feature(difficult_obj), - 'image/object/truncated': dataset_util.int64_list_feature(truncated), - 'image/object/view': dataset_util.bytes_list_feature(poses), - } - if not faces_only: - if mask_type == 'numerical': - mask_stack = np.stack(masks).astype(np.float32) - masks_flattened = np.reshape(mask_stack, [-1]) - feature_dict['image/object/mask'] = ( - dataset_util.float_list_feature(masks_flattened.tolist())) - elif mask_type == 'png': - encoded_mask_png_list = [] - for mask in masks: - img = PIL.Image.fromarray(mask) - output = io.BytesIO() - img.save(output, format='PNG') - encoded_mask_png_list.append(output.getvalue()) - feature_dict['image/object/mask'] = ( - dataset_util.bytes_list_feature(encoded_mask_png_list)) - - example = tf.train.Example(features=tf.train.Features(feature=feature_dict)) - return example - - -def create_tf_record(output_filename, - num_shards, - label_map_dict, - annotations_dir, - image_dir, - examples, - faces_only=True, - mask_type='png'): - """Creates a TFRecord file from examples. - - Args: - output_filename: Path to where output file is saved. - num_shards: Number of shards for output file. - label_map_dict: The label map dictionary. - annotations_dir: Directory where annotation files are stored. - image_dir: Directory where image files are stored. - examples: Examples to parse and save to tf record. - faces_only: If True, generates bounding boxes for pet faces. Otherwise - generates bounding boxes (as well as segmentations for full pet bodies). - mask_type: 'numerical' or 'png'. 'png' is recommended because it leads to - smaller file sizes. - """ - with contextlib2.ExitStack() as tf_record_close_stack: - output_tfrecords = tf_record_creation_util.open_sharded_output_tfrecords( - tf_record_close_stack, output_filename, num_shards) - for idx, example in enumerate(examples): - if idx % 100 == 0: - logging.info('On image %d of %d', idx, len(examples)) - xml_path = os.path.join(annotations_dir, 'xmls', example + '.xml') - mask_path = os.path.join(annotations_dir, 'trimaps', example + '.png') - - if not os.path.exists(xml_path): - logging.warning('Could not find %s, ignoring example.', xml_path) - continue - with tf.gfile.GFile(xml_path, 'r') as fid: - xml_str = fid.read() - xml = etree.fromstring(xml_str) - data = dataset_util.recursive_parse_xml_to_dict(xml)['annotation'] - - try: - tf_example = dict_to_tf_example( - data, - mask_path, - label_map_dict, - image_dir, - faces_only=faces_only, - mask_type=mask_type) - if tf_example: - shard_idx = idx % num_shards - output_tfrecords[shard_idx].write(tf_example.SerializeToString()) - except ValueError: - logging.warning('Invalid example: %s, ignoring.', xml_path) - - -# TODO(derekjchow): Add test for pet/PASCAL main files. -def main(_): - data_dir = FLAGS.data_dir - label_map_dict = label_map_util.get_label_map_dict(FLAGS.label_map_path) - - logging.info('Reading from Pet dataset.') - image_dir = os.path.join(data_dir, 'images') - annotations_dir = os.path.join(data_dir, 'annotations') - examples_path = os.path.join(annotations_dir, 'trainval.txt') - examples_list = dataset_util.read_examples_list(examples_path) - - # Test images are not included in the downloaded data set, so we shall perform - # our own split. - random.seed(42) - random.shuffle(examples_list) - num_examples = len(examples_list) - num_train = int(0.7 * num_examples) - train_examples = examples_list[:num_train] - val_examples = examples_list[num_train:] - logging.info('%d training and %d validation examples.', - len(train_examples), len(val_examples)) - - train_output_path = os.path.join(FLAGS.output_dir, 'pet_faces_train.record') - val_output_path = os.path.join(FLAGS.output_dir, 'pet_faces_val.record') - if not FLAGS.faces_only: - train_output_path = os.path.join(FLAGS.output_dir, - 'pets_fullbody_with_masks_train.record') - val_output_path = os.path.join(FLAGS.output_dir, - 'pets_fullbody_with_masks_val.record') - create_tf_record( - train_output_path, - FLAGS.num_shards, - label_map_dict, - annotations_dir, - image_dir, - train_examples, - faces_only=FLAGS.faces_only, - mask_type=FLAGS.mask_type) - create_tf_record( - val_output_path, - FLAGS.num_shards, - label_map_dict, - annotations_dir, - image_dir, - val_examples, - faces_only=FLAGS.faces_only, - mask_type=FLAGS.mask_type) - - -if __name__ == '__main__': - tf.app.run() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/download_and_preprocess_mscoco.sh b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/download_and_preprocess_mscoco.sh deleted file mode 100644 index 843ba8693..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/download_and_preprocess_mscoco.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/bash -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -# Script to download and preprocess the MSCOCO data set for detection. -# -# The outputs of this script are TFRecord files containing serialized -# tf.Example protocol buffers. See create_coco_tf_record.py for details of how -# the tf.Example protocol buffers are constructed and see -# http://cocodataset.org/#overview for an overview of the dataset. -# -# usage: -# bash object_detection/dataset_tools/download_and_preprocess_mscoco.sh \ -# /tmp/mscoco -set -e - -if [ -z "$1" ]; then - echo "usage download_and_preprocess_mscoco.sh [data dir]" - exit -fi - -if [ "$(uname)" == "Darwin" ]; then - UNZIP="tar -xf" -else - UNZIP="unzip -nq" -fi - -# Create the output directories. -OUTPUT_DIR="${1%/}" -SCRATCH_DIR="${OUTPUT_DIR}/raw-data" -mkdir -p "${OUTPUT_DIR}" -mkdir -p "${SCRATCH_DIR}" -CURRENT_DIR=$(pwd) - -# Helper function to download and unpack a .zip file. -function download_and_unzip() { - local BASE_URL=${1} - local FILENAME=${2} - - if [ ! -f ${FILENAME} ]; then - echo "Downloading ${FILENAME} to $(pwd)" - wget -nd -c "${BASE_URL}/${FILENAME}" - else - echo "Skipping download of ${FILENAME}" - fi - echo "Unzipping ${FILENAME}" - ${UNZIP} ${FILENAME} -} - -cd ${SCRATCH_DIR} - -# Download the images. -BASE_IMAGE_URL="http://images.cocodataset.org/zips" - -TRAIN_IMAGE_FILE="train2017.zip" -download_and_unzip ${BASE_IMAGE_URL} ${TRAIN_IMAGE_FILE} -TRAIN_IMAGE_DIR="${SCRATCH_DIR}/train2017" - -VAL_IMAGE_FILE="val2017.zip" -download_and_unzip ${BASE_IMAGE_URL} ${VAL_IMAGE_FILE} -VAL_IMAGE_DIR="${SCRATCH_DIR}/val2017" - -TEST_IMAGE_FILE="test2017.zip" -download_and_unzip ${BASE_IMAGE_URL} ${TEST_IMAGE_FILE} -TEST_IMAGE_DIR="${SCRATCH_DIR}/test2017" - -# Download the annotations. -BASE_INSTANCES_URL="http://images.cocodataset.org/annotations" -INSTANCES_FILE="annotations_trainval2017.zip" -download_and_unzip ${BASE_INSTANCES_URL} ${INSTANCES_FILE} - -TRAIN_ANNOTATIONS_FILE="${SCRATCH_DIR}/annotations/instances_train2017.json" -VAL_ANNOTATIONS_FILE="${SCRATCH_DIR}/annotations/instances_val2017.json" - -# Download the test image info. -BASE_IMAGE_INFO_URL="http://images.cocodataset.org/annotations" -IMAGE_INFO_FILE="image_info_test2017.zip" -download_and_unzip ${BASE_IMAGE_INFO_URL} ${IMAGE_INFO_FILE} - -TESTDEV_ANNOTATIONS_FILE="${SCRATCH_DIR}/annotations/image_info_test-dev2017.json" - -# Build TFRecords of the image data. -cd "${CURRENT_DIR}" -python object_detection/dataset_tools/create_coco_tf_record.py \ - --logtostderr \ - --include_masks \ - --train_image_dir="${TRAIN_IMAGE_DIR}" \ - --val_image_dir="${VAL_IMAGE_DIR}" \ - --test_image_dir="${TEST_IMAGE_DIR}" \ - --train_annotations_file="${TRAIN_ANNOTATIONS_FILE}" \ - --val_annotations_file="${VAL_ANNOTATIONS_FILE}" \ - --testdev_annotations_file="${TESTDEV_ANNOTATIONS_FILE}" \ - --output_dir="${OUTPUT_DIR}" - diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_hierarchical_labels_expansion.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_hierarchical_labels_expansion.py deleted file mode 100644 index 6c00ac429..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_hierarchical_labels_expansion.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""A class and executable to expand hierarchically image-level labels and boxes. - -Example usage: - ./hierarchical_labels_expansion - [optional]labels_file -""" - -import json -import sys - - -def _update_dict(initial_dict, update): - """Updates dictionary with update content. - - Args: - initial_dict: initial dictionary. - update: updated dictionary. - """ - - for key, value_list in update.iteritems(): - if key in initial_dict: - initial_dict[key].extend(value_list) - else: - initial_dict[key] = value_list - - -def _build_plain_hierarchy(hierarchy, skip_root=False): - """Expands tree hierarchy representation to parent-child dictionary. - - Args: - hierarchy: labels hierarchy as JSON file. - skip_root: if true skips root from the processing (done for the case when all - classes under hierarchy are collected under virtual node). - - Returns: - keyed_parent - dictionary of parent - all its children nodes. - keyed_child - dictionary of children - all its parent nodes - children - all children of the current node. - """ - all_children = [] - all_keyed_parent = {} - all_keyed_child = {} - if 'Subcategory' in hierarchy: - for node in hierarchy['Subcategory']: - keyed_parent, keyed_child, children = _build_plain_hierarchy(node) - # Update is not done through dict.update() since some children have multi- - # ple parents in the hiearchy. - _update_dict(all_keyed_parent, keyed_parent) - _update_dict(all_keyed_child, keyed_child) - all_children.extend(children) - - if not skip_root: - all_keyed_parent[hierarchy['LabelName']] = all_children - all_children = [hierarchy['LabelName']] + all_children - for child, _ in all_keyed_child.iteritems(): - all_keyed_child[child].append(hierarchy['LabelName']) - all_keyed_child[hierarchy['LabelName']] = [] - - return all_keyed_parent, all_keyed_child, all_children - - -class OIDHierarchicalLabelsExpansion(object): - """ Main class to perform labels hierachical expansion.""" - - def __init__(self, hierarchy): - """Constructor. - - Args: - hierarchy: labels hierarchy as JSON file. - """ - - self._hierarchy_keyed_parent, self._hierarchy_keyed_child, _ = ( - _build_plain_hierarchy(hierarchy, skip_root=True)) - - def expand_boxes_from_csv(self, csv_row): - """Expands a row containing bounding boxes from CSV file. - - Args: - csv_row: a single row of Open Images released groundtruth file. - - Returns: - a list of strings (including the initial row) corresponding to the ground - truth expanded to multiple annotation for evaluation with Open Images - Challenge 2018 metric. - """ - # Row header is expected to be exactly: - # ImageID,Source,LabelName,Confidence,XMin,XMax,YMin,YMax,IsOccluded, - # IsTruncated,IsGroupOf,IsDepiction,IsInside - cvs_row_splited = csv_row.split(',') - assert len(cvs_row_splited) == 13 - result = [csv_row] - assert cvs_row_splited[2] in self._hierarchy_keyed_child - parent_nodes = self._hierarchy_keyed_child[cvs_row_splited[2]] - for parent_node in parent_nodes: - cvs_row_splited[2] = parent_node - result.append(','.join(cvs_row_splited)) - return result - - def expand_labels_from_csv(self, csv_row): - """Expands a row containing bounding boxes from CSV file. - - Args: - csv_row: a single row of Open Images released groundtruth file. - - Returns: - a list of strings (including the initial row) corresponding to the ground - truth expanded to multiple annotation for evaluation with Open Images - Challenge 2018 metric. - """ - # Row header is expected to be exactly: - # ImageID,Source,LabelName,Confidence - cvs_row_splited = csv_row.split(',') - assert len(cvs_row_splited) == 4 - result = [csv_row] - if int(cvs_row_splited[3]) == 1: - assert cvs_row_splited[2] in self._hierarchy_keyed_child - parent_nodes = self._hierarchy_keyed_child[cvs_row_splited[2]] - for parent_node in parent_nodes: - cvs_row_splited[2] = parent_node - result.append(','.join(cvs_row_splited)) - else: - assert cvs_row_splited[2] in self._hierarchy_keyed_parent - child_nodes = self._hierarchy_keyed_parent[cvs_row_splited[2]] - for child_node in child_nodes: - cvs_row_splited[2] = child_node - result.append(','.join(cvs_row_splited)) - return result - - -def main(argv): - - if len(argv) < 4: - print """Missing arguments. \n - Usage: ./hierarchical_labels_expansion - [optional]labels_file""" - return - with open(argv[1]) as f: - hierarchy = json.load(f) - expansion_generator = OIDHierarchicalLabelsExpansion(hierarchy) - labels_file = False - if len(argv) > 4 and argv[4] == 'labels_file': - labels_file = True - with open(argv[2], 'r') as source: - with open(argv[3], 'w') as target: - header_skipped = False - for line in source: - if not header_skipped: - header_skipped = True - continue - if labels_file: - expanded_lines = expansion_generator.expand_labels_from_csv(line) - else: - expanded_lines = expansion_generator.expand_boxes_from_csv(line) - target.writelines(expanded_lines) - - -if __name__ == '__main__': - main(sys.argv) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_hierarchical_labels_expansion_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_hierarchical_labels_expansion_test.py deleted file mode 100644 index cd62b9cff..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_hierarchical_labels_expansion_test.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the OpenImages label expansion (OIDHierarchicalLabelsExpansion).""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import tensorflow as tf - -from object_detection.dataset_tools import oid_hierarchical_labels_expansion - - -def create_test_data(): - hierarchy = { - 'LabelName': - 'a', - 'Subcategory': [{ - 'LabelName': 'b' - }, { - 'LabelName': 'c', - 'Subcategory': [{ - 'LabelName': 'd' - }, { - 'LabelName': 'e' - }] - }, { - 'LabelName': 'f', - 'Subcategory': [{ - 'LabelName': 'd' - },] - }] - } - bbox_rows = [ - '123,xclick,b,1,0.1,0.2,0.1,0.2,1,1,0,0,0', - '123,xclick,d,1,0.2,0.3,0.1,0.2,1,1,0,0,0' - ] - label_rows = [ - '123,verification,b,0', '123,verification,c,0', '124,verification,d,1' - ] - return hierarchy, bbox_rows, label_rows - - -class HierarchicalLabelsExpansionTest(tf.test.TestCase): - - def test_bbox_expansion(self): - hierarchy, bbox_rows, _ = create_test_data() - expansion_generator = ( - oid_hierarchical_labels_expansion.OIDHierarchicalLabelsExpansion( - hierarchy)) - all_result_rows = [] - for row in bbox_rows: - all_result_rows.extend(expansion_generator.expand_boxes_from_csv(row)) - self.assertItemsEqual([ - '123,xclick,b,1,0.1,0.2,0.1,0.2,1,1,0,0,0', - '123,xclick,d,1,0.2,0.3,0.1,0.2,1,1,0,0,0', - '123,xclick,f,1,0.2,0.3,0.1,0.2,1,1,0,0,0', - '123,xclick,c,1,0.2,0.3,0.1,0.2,1,1,0,0,0' - ], all_result_rows) - - def test_labels_expansion(self): - hierarchy, _, label_rows = create_test_data() - expansion_generator = ( - oid_hierarchical_labels_expansion.OIDHierarchicalLabelsExpansion( - hierarchy)) - all_result_rows = [] - for row in label_rows: - all_result_rows.extend(expansion_generator.expand_labels_from_csv(row)) - self.assertItemsEqual([ - '123,verification,b,0', '123,verification,c,0', '123,verification,d,0', - '123,verification,e,0', '124,verification,d,1', '124,verification,f,1', - '124,verification,c,1' - ], all_result_rows) - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_tfrecord_creation.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_tfrecord_creation.py deleted file mode 100644 index 706280985..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_tfrecord_creation.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -r"""Utilities for creating TFRecords of TF examples for the Open Images dataset. -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import tensorflow as tf - -from object_detection.core import standard_fields -from object_detection.utils import dataset_util - - -def tf_example_from_annotations_data_frame(annotations_data_frame, label_map, - encoded_image): - """Populates a TF Example message with image annotations from a data frame. - - Args: - annotations_data_frame: Data frame containing the annotations for a single - image. - label_map: String to integer label map. - encoded_image: The encoded image string - - Returns: - The populated TF Example, if the label of at least one object is present in - label_map. Otherwise, returns None. - """ - - filtered_data_frame = annotations_data_frame[ - annotations_data_frame.LabelName.isin(label_map)] - filtered_data_frame_boxes = filtered_data_frame[ - ~filtered_data_frame.YMin.isnull()] - filtered_data_frame_labels = filtered_data_frame[ - filtered_data_frame.YMin.isnull()] - image_id = annotations_data_frame.ImageID.iloc[0] - - feature_map = { - standard_fields.TfExampleFields.object_bbox_ymin: - dataset_util.float_list_feature( - filtered_data_frame_boxes.YMin.as_matrix()), - standard_fields.TfExampleFields.object_bbox_xmin: - dataset_util.float_list_feature( - filtered_data_frame_boxes.XMin.as_matrix()), - standard_fields.TfExampleFields.object_bbox_ymax: - dataset_util.float_list_feature( - filtered_data_frame_boxes.YMax.as_matrix()), - standard_fields.TfExampleFields.object_bbox_xmax: - dataset_util.float_list_feature( - filtered_data_frame_boxes.XMax.as_matrix()), - standard_fields.TfExampleFields.object_class_text: - dataset_util.bytes_list_feature( - filtered_data_frame_boxes.LabelName.as_matrix()), - standard_fields.TfExampleFields.object_class_label: - dataset_util.int64_list_feature( - filtered_data_frame_boxes.LabelName.map(lambda x: label_map[x]) - .as_matrix()), - standard_fields.TfExampleFields.filename: - dataset_util.bytes_feature('{}.jpg'.format(image_id)), - standard_fields.TfExampleFields.source_id: - dataset_util.bytes_feature(image_id), - standard_fields.TfExampleFields.image_encoded: - dataset_util.bytes_feature(encoded_image), - } - - if 'IsGroupOf' in filtered_data_frame.columns: - feature_map[standard_fields.TfExampleFields. - object_group_of] = dataset_util.int64_list_feature( - filtered_data_frame_boxes.IsGroupOf.as_matrix().astype(int)) - if 'IsOccluded' in filtered_data_frame.columns: - feature_map[standard_fields.TfExampleFields. - object_occluded] = dataset_util.int64_list_feature( - filtered_data_frame_boxes.IsOccluded.as_matrix().astype( - int)) - if 'IsTruncated' in filtered_data_frame.columns: - feature_map[standard_fields.TfExampleFields. - object_truncated] = dataset_util.int64_list_feature( - filtered_data_frame_boxes.IsTruncated.as_matrix().astype( - int)) - if 'IsDepiction' in filtered_data_frame.columns: - feature_map[standard_fields.TfExampleFields. - object_depiction] = dataset_util.int64_list_feature( - filtered_data_frame_boxes.IsDepiction.as_matrix().astype( - int)) - - if 'ConfidenceImageLabel' in filtered_data_frame_labels.columns: - feature_map[standard_fields.TfExampleFields. - image_class_label] = dataset_util.int64_list_feature( - filtered_data_frame_labels.LabelName.map( - lambda x: label_map[x]).as_matrix()) - feature_map[standard_fields.TfExampleFields. - image_class_text] = dataset_util.bytes_list_feature( - filtered_data_frame_labels.LabelName.as_matrix()), - return tf.train.Example(features=tf.train.Features(feature=feature_map)) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_tfrecord_creation_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_tfrecord_creation_test.py deleted file mode 100644 index 44ef85216..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/oid_tfrecord_creation_test.py +++ /dev/null @@ -1,200 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for oid_tfrecord_creation.py.""" - -import pandas as pd -import tensorflow as tf - -from object_detection.dataset_tools import oid_tfrecord_creation - - -def create_test_data(): - data = { - 'ImageID': ['i1', 'i1', 'i1', 'i1', 'i1', 'i2', 'i2'], - 'LabelName': ['a', 'a', 'b', 'b', 'c', 'b', 'c'], - 'YMin': [0.3, 0.6, 0.8, 0.1, None, 0.0, 0.0], - 'XMin': [0.1, 0.3, 0.7, 0.0, None, 0.1, 0.1], - 'XMax': [0.2, 0.3, 0.8, 0.5, None, 0.9, 0.9], - 'YMax': [0.3, 0.6, 1, 0.8, None, 0.8, 0.8], - 'IsOccluded': [0, 1, 1, 0, None, 0, 0], - 'IsTruncated': [0, 0, 0, 1, None, 0, 0], - 'IsGroupOf': [0, 0, 0, 0, None, 0, 1], - 'IsDepiction': [1, 0, 0, 0, None, 0, 0], - 'ConfidenceImageLabel': [None, None, None, None, 0, None, None], - } - df = pd.DataFrame(data=data) - label_map = {'a': 0, 'b': 1, 'c': 2} - return label_map, df - - -class TfExampleFromAnnotationsDataFrameTests(tf.test.TestCase): - - def test_simple(self): - label_map, df = create_test_data() - - tf_example = oid_tfrecord_creation.tf_example_from_annotations_data_frame( - df[df.ImageID == 'i1'], label_map, 'encoded_image_test') - self.assertProtoEquals( - """ - features { - feature { - key: "image/encoded" - value { bytes_list { value: "encoded_image_test" } } } - feature { - key: "image/filename" - value { bytes_list { value: "i1.jpg" } } } - feature { - key: "image/object/bbox/ymin" - value { float_list { value: [0.3, 0.6, 0.8, 0.1] } } } - feature { - key: "image/object/bbox/xmin" - value { float_list { value: [0.1, 0.3, 0.7, 0.0] } } } - feature { - key: "image/object/bbox/ymax" - value { float_list { value: [0.3, 0.6, 1.0, 0.8] } } } - feature { - key: "image/object/bbox/xmax" - value { float_list { value: [0.2, 0.3, 0.8, 0.5] } } } - feature { - key: "image/object/class/label" - value { int64_list { value: [0, 0, 1, 1] } } } - feature { - key: "image/object/class/text" - value { bytes_list { value: ["a", "a", "b", "b"] } } } - feature { - key: "image/source_id" - value { bytes_list { value: "i1" } } } - feature { - key: "image/object/depiction" - value { int64_list { value: [1, 0, 0, 0] } } } - feature { - key: "image/object/group_of" - value { int64_list { value: [0, 0, 0, 0] } } } - feature { - key: "image/object/occluded" - value { int64_list { value: [0, 1, 1, 0] } } } - feature { - key: "image/object/truncated" - value { int64_list { value: [0, 0, 0, 1] } } } - feature { - key: "image/class/label" - value { int64_list { value: [2] } } } - feature { - key: "image/class/text" - value { bytes_list { value: ["c"] } } } } - """, tf_example) - - def test_no_attributes(self): - label_map, df = create_test_data() - - del df['IsDepiction'] - del df['IsGroupOf'] - del df['IsOccluded'] - del df['IsTruncated'] - del df['ConfidenceImageLabel'] - - tf_example = oid_tfrecord_creation.tf_example_from_annotations_data_frame( - df[df.ImageID == 'i2'], label_map, 'encoded_image_test') - self.assertProtoEquals(""" - features { - feature { - key: "image/encoded" - value { bytes_list { value: "encoded_image_test" } } } - feature { - key: "image/filename" - value { bytes_list { value: "i2.jpg" } } } - feature { - key: "image/object/bbox/ymin" - value { float_list { value: [0.0, 0.0] } } } - feature { - key: "image/object/bbox/xmin" - value { float_list { value: [0.1, 0.1] } } } - feature { - key: "image/object/bbox/ymax" - value { float_list { value: [0.8, 0.8] } } } - feature { - key: "image/object/bbox/xmax" - value { float_list { value: [0.9, 0.9] } } } - feature { - key: "image/object/class/label" - value { int64_list { value: [1, 2] } } } - feature { - key: "image/object/class/text" - value { bytes_list { value: ["b", "c"] } } } - feature { - key: "image/source_id" - value { bytes_list { value: "i2" } } } } - """, tf_example) - - def test_label_filtering(self): - label_map, df = create_test_data() - - label_map = {'a': 0} - - tf_example = oid_tfrecord_creation.tf_example_from_annotations_data_frame( - df[df.ImageID == 'i1'], label_map, 'encoded_image_test') - self.assertProtoEquals( - """ - features { - feature { - key: "image/encoded" - value { bytes_list { value: "encoded_image_test" } } } - feature { - key: "image/filename" - value { bytes_list { value: "i1.jpg" } } } - feature { - key: "image/object/bbox/ymin" - value { float_list { value: [0.3, 0.6] } } } - feature { - key: "image/object/bbox/xmin" - value { float_list { value: [0.1, 0.3] } } } - feature { - key: "image/object/bbox/ymax" - value { float_list { value: [0.3, 0.6] } } } - feature { - key: "image/object/bbox/xmax" - value { float_list { value: [0.2, 0.3] } } } - feature { - key: "image/object/class/label" - value { int64_list { value: [0, 0] } } } - feature { - key: "image/object/class/text" - value { bytes_list { value: ["a", "a"] } } } - feature { - key: "image/source_id" - value { bytes_list { value: "i1" } } } - feature { - key: "image/object/depiction" - value { int64_list { value: [1, 0] } } } - feature { - key: "image/object/group_of" - value { int64_list { value: [0, 0] } } } - feature { - key: "image/object/occluded" - value { int64_list { value: [0, 1] } } } - feature { - key: "image/object/truncated" - value { int64_list { value: [0, 0] } } } - feature { - key: "image/class/label" - value { int64_list { } } } - feature { - key: "image/class/text" - value { bytes_list { } } } } - """, tf_example) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/tf_record_creation_util.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/tf_record_creation_util.py deleted file mode 100644 index e8da2291d..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/tf_record_creation_util.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2018 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -r"""Utilities for creating TFRecords of TF examples for the Open Images dataset. -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import tensorflow as tf - - -def open_sharded_output_tfrecords(exit_stack, base_path, num_shards): - """Opens all TFRecord shards for writing and adds them to an exit stack. - - Args: - exit_stack: A context2.ExitStack used to automatically closed the TFRecords - opened in this function. - base_path: The base path for all shards - num_shards: The number of shards - - Returns: - The list of opened TFRecords. Position k in the list corresponds to shard k. - """ - tf_record_output_filenames = [ - '{}-{:05d}-of-{:05d}'.format(base_path, idx, num_shards) - for idx in range(num_shards) - ] - - tfrecords = [ - exit_stack.enter_context(tf.python_io.TFRecordWriter(file_name)) - for file_name in tf_record_output_filenames - ] - - return tfrecords diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/tf_record_creation_util_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/tf_record_creation_util_test.py deleted file mode 100644 index f1231f8bb..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/dataset_tools/tf_record_creation_util_test.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2018 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for tf_record_creation_util.py.""" - -import os -import contextlib2 -import tensorflow as tf - -from object_detection.dataset_tools import tf_record_creation_util - - -class OpenOutputTfrecordsTests(tf.test.TestCase): - - def test_sharded_tfrecord_writes(self): - with contextlib2.ExitStack() as tf_record_close_stack: - output_tfrecords = tf_record_creation_util.open_sharded_output_tfrecords( - tf_record_close_stack, - os.path.join(tf.test.get_temp_dir(), 'test.tfrec'), 10) - for idx in range(10): - output_tfrecords[idx].write('test_{}'.format(idx)) - - for idx in range(10): - tf_record_path = '{}-{:05d}-of-00010'.format( - os.path.join(tf.test.get_temp_dir(), 'test.tfrec'), idx) - records = list(tf.python_io.tf_record_iterator(tf_record_path)) - self.assertAllEqual(records, ['test_{}'.format(idx)]) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/eval.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/eval.py deleted file mode 100644 index f546442e2..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/eval.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -r"""Evaluation executable for detection models. - -This executable is used to evaluate DetectionModels. There are two ways of -configuring the eval job. - -1) A single pipeline_pb2.TrainEvalPipelineConfig file maybe specified instead. -In this mode, the --eval_training_data flag may be given to force the pipeline -to evaluate on training data instead. - -Example usage: - ./eval \ - --logtostderr \ - --checkpoint_dir=path/to/checkpoint_dir \ - --eval_dir=path/to/eval_dir \ - --pipeline_config_path=pipeline_config.pbtxt - -2) Three configuration files may be provided: a model_pb2.DetectionModel -configuration file to define what type of DetectionModel is being evaluated, an -input_reader_pb2.InputReader file to specify what data the model is evaluating -and an eval_pb2.EvalConfig file to configure evaluation parameters. - -Example usage: - ./eval \ - --logtostderr \ - --checkpoint_dir=path/to/checkpoint_dir \ - --eval_dir=path/to/eval_dir \ - --eval_config_path=eval_config.pbtxt \ - --model_config_path=model_config.pbtxt \ - --input_config_path=eval_input_config.pbtxt -""" -import functools -import os -import tensorflow as tf - -from object_detection import evaluator -from object_detection.builders import dataset_builder -from object_detection.builders import graph_rewriter_builder -from object_detection.builders import model_builder -from object_detection.utils import config_util -from object_detection.utils import dataset_util -from object_detection.utils import label_map_util - - -tf.logging.set_verbosity(tf.logging.INFO) - -flags = tf.app.flags -flags.DEFINE_boolean('eval_training_data', False, - 'If training data should be evaluated for this job.') -flags.DEFINE_string('checkpoint_dir', '', - 'Directory containing checkpoints to evaluate, typically ' - 'set to `train_dir` used in the training job.') -flags.DEFINE_string('eval_dir', '', - 'Directory to write eval summaries to.') -flags.DEFINE_string('pipeline_config_path', '', - 'Path to a pipeline_pb2.TrainEvalPipelineConfig config ' - 'file. If provided, other configs are ignored') -flags.DEFINE_string('eval_config_path', '', - 'Path to an eval_pb2.EvalConfig config file.') -flags.DEFINE_string('input_config_path', '', - 'Path to an input_reader_pb2.InputReader config file.') -flags.DEFINE_string('model_config_path', '', - 'Path to a model_pb2.DetectionModel config file.') -flags.DEFINE_boolean('run_once', False, 'Option to only run a single pass of ' - 'evaluation. Overrides the `max_evals` parameter in the ' - 'provided config.') -FLAGS = flags.FLAGS - - -def main(unused_argv): - assert FLAGS.checkpoint_dir, '`checkpoint_dir` is missing.' - assert FLAGS.eval_dir, '`eval_dir` is missing.' - tf.gfile.MakeDirs(FLAGS.eval_dir) - if FLAGS.pipeline_config_path: - configs = config_util.get_configs_from_pipeline_file( - FLAGS.pipeline_config_path) - tf.gfile.Copy(FLAGS.pipeline_config_path, - os.path.join(FLAGS.eval_dir, 'pipeline.config'), - overwrite=True) - else: - configs = config_util.get_configs_from_multiple_files( - model_config_path=FLAGS.model_config_path, - eval_config_path=FLAGS.eval_config_path, - eval_input_config_path=FLAGS.input_config_path) - for name, config in [('model.config', FLAGS.model_config_path), - ('eval.config', FLAGS.eval_config_path), - ('input.config', FLAGS.input_config_path)]: - tf.gfile.Copy(config, - os.path.join(FLAGS.eval_dir, name), - overwrite=True) - - model_config = configs['model'] - eval_config = configs['eval_config'] - input_config = configs['eval_input_config'] - if FLAGS.eval_training_data: - input_config = configs['train_input_config'] - - model_fn = functools.partial( - model_builder.build, - model_config=model_config, - is_training=False) - - def get_next(config): - return dataset_util.make_initializable_iterator( - dataset_builder.build(config)).get_next() - - create_input_dict_fn = functools.partial(get_next, input_config) - - label_map = label_map_util.load_labelmap(input_config.label_map_path) - max_num_classes = max([item.id for item in label_map.item]) - categories = label_map_util.convert_label_map_to_categories( - label_map, max_num_classes) - - if FLAGS.run_once: - eval_config.max_evals = 1 - - graph_rewriter_fn = None - if 'graph_rewriter_config' in configs: - graph_rewriter_fn = graph_rewriter_builder.build( - configs['graph_rewriter_config'], is_training=False) - - evaluator.evaluate( - create_input_dict_fn, - model_fn, - eval_config, - categories, - FLAGS.checkpoint_dir, - FLAGS.eval_dir, - graph_hook_fn=graph_rewriter_fn) - - -if __name__ == '__main__': - tf.app.run() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/eval_util.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/eval_util.py deleted file mode 100644 index 67b62a442..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/eval_util.py +++ /dev/null @@ -1,645 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Common utility functions for evaluation.""" -import collections -import logging -import os -import time - -import numpy as np -import tensorflow as tf - -from object_detection.core import box_list -from object_detection.core import box_list_ops -from object_detection.core import keypoint_ops -from object_detection.core import standard_fields as fields -from object_detection.metrics import coco_evaluation -from object_detection.utils import label_map_util -from object_detection.utils import ops -from object_detection.utils import visualization_utils as vis_utils - -slim = tf.contrib.slim - - -def write_metrics(metrics, global_step, summary_dir): - """Write metrics to a summary directory. - - Args: - metrics: A dictionary containing metric names and values. - global_step: Global step at which the metrics are computed. - summary_dir: Directory to write tensorflow summaries to. - """ - logging.info('Writing metrics to tf summary.') - summary_writer = tf.summary.FileWriterCache.get(summary_dir) - for key in sorted(metrics): - summary = tf.Summary(value=[ - tf.Summary.Value(tag=key, simple_value=metrics[key]), - ]) - summary_writer.add_summary(summary, global_step) - logging.info('%s: %f', key, metrics[key]) - logging.info('Metrics written to tf summary.') - - -# TODO(rathodv): Add tests. -def visualize_detection_results(result_dict, - tag, - global_step, - categories, - summary_dir='', - export_dir='', - agnostic_mode=False, - show_groundtruth=False, - groundtruth_box_visualization_color='black', - min_score_thresh=.5, - max_num_predictions=20, - skip_scores=False, - skip_labels=False, - keep_image_id_for_visualization_export=False): - """Visualizes detection results and writes visualizations to image summaries. - - This function visualizes an image with its detected bounding boxes and writes - to image summaries which can be viewed on tensorboard. It optionally also - writes images to a directory. In the case of missing entry in the label map, - unknown class name in the visualization is shown as "N/A". - - Args: - result_dict: a dictionary holding groundtruth and detection - data corresponding to each image being evaluated. The following keys - are required: - 'original_image': a numpy array representing the image with shape - [1, height, width, 3] or [1, height, width, 1] - 'detection_boxes': a numpy array of shape [N, 4] - 'detection_scores': a numpy array of shape [N] - 'detection_classes': a numpy array of shape [N] - The following keys are optional: - 'groundtruth_boxes': a numpy array of shape [N, 4] - 'groundtruth_keypoints': a numpy array of shape [N, num_keypoints, 2] - Detections are assumed to be provided in decreasing order of score and for - display, and we assume that scores are probabilities between 0 and 1. - tag: tensorboard tag (string) to associate with image. - global_step: global step at which the visualization are generated. - categories: a list of dictionaries representing all possible categories. - Each dict in this list has the following keys: - 'id': (required) an integer id uniquely identifying this category - 'name': (required) string representing category name - e.g., 'cat', 'dog', 'pizza' - 'supercategory': (optional) string representing the supercategory - e.g., 'animal', 'vehicle', 'food', etc - summary_dir: the output directory to which the image summaries are written. - export_dir: the output directory to which images are written. If this is - empty (default), then images are not exported. - agnostic_mode: boolean (default: False) controlling whether to evaluate in - class-agnostic mode or not. - show_groundtruth: boolean (default: False) controlling whether to show - groundtruth boxes in addition to detected boxes - groundtruth_box_visualization_color: box color for visualizing groundtruth - boxes - min_score_thresh: minimum score threshold for a box to be visualized - max_num_predictions: maximum number of detections to visualize - skip_scores: whether to skip score when drawing a single detection - skip_labels: whether to skip label when drawing a single detection - keep_image_id_for_visualization_export: whether to keep image identifier in - filename when exported to export_dir - Raises: - ValueError: if result_dict does not contain the expected keys (i.e., - 'original_image', 'detection_boxes', 'detection_scores', - 'detection_classes') - """ - detection_fields = fields.DetectionResultFields - input_fields = fields.InputDataFields - if not set([ - input_fields.original_image, - detection_fields.detection_boxes, - detection_fields.detection_scores, - detection_fields.detection_classes, - ]).issubset(set(result_dict.keys())): - raise ValueError('result_dict does not contain all expected keys.') - if show_groundtruth and input_fields.groundtruth_boxes not in result_dict: - raise ValueError('If show_groundtruth is enabled, result_dict must contain ' - 'groundtruth_boxes.') - logging.info('Creating detection visualizations.') - category_index = label_map_util.create_category_index(categories) - - image = np.squeeze(result_dict[input_fields.original_image], axis=0) - if image.shape[2] == 1: # If one channel image, repeat in RGB. - image = np.tile(image, [1, 1, 3]) - detection_boxes = result_dict[detection_fields.detection_boxes] - detection_scores = result_dict[detection_fields.detection_scores] - detection_classes = np.int32((result_dict[ - detection_fields.detection_classes])) - detection_keypoints = result_dict.get(detection_fields.detection_keypoints) - detection_masks = result_dict.get(detection_fields.detection_masks) - detection_boundaries = result_dict.get(detection_fields.detection_boundaries) - - # Plot groundtruth underneath detections - if show_groundtruth: - groundtruth_boxes = result_dict[input_fields.groundtruth_boxes] - groundtruth_keypoints = result_dict.get(input_fields.groundtruth_keypoints) - vis_utils.visualize_boxes_and_labels_on_image_array( - image=image, - boxes=groundtruth_boxes, - classes=None, - scores=None, - category_index=category_index, - keypoints=groundtruth_keypoints, - use_normalized_coordinates=False, - max_boxes_to_draw=None, - groundtruth_box_visualization_color=groundtruth_box_visualization_color) - vis_utils.visualize_boxes_and_labels_on_image_array( - image, - detection_boxes, - detection_classes, - detection_scores, - category_index, - instance_masks=detection_masks, - instance_boundaries=detection_boundaries, - keypoints=detection_keypoints, - use_normalized_coordinates=False, - max_boxes_to_draw=max_num_predictions, - min_score_thresh=min_score_thresh, - agnostic_mode=agnostic_mode, - skip_scores=skip_scores, - skip_labels=skip_labels) - - if export_dir: - if keep_image_id_for_visualization_export and result_dict[fields. - InputDataFields() - .key]: - export_path = os.path.join(export_dir, 'export-{}-{}.png'.format( - tag, result_dict[fields.InputDataFields().key])) - else: - export_path = os.path.join(export_dir, 'export-{}.png'.format(tag)) - vis_utils.save_image_array_as_png(image, export_path) - - summary = tf.Summary(value=[ - tf.Summary.Value( - tag=tag, - image=tf.Summary.Image( - encoded_image_string=vis_utils.encode_image_array_as_png_str( - image))) - ]) - summary_writer = tf.summary.FileWriterCache.get(summary_dir) - summary_writer.add_summary(summary, global_step) - - logging.info('Detection visualizations written to summary with tag %s.', tag) - - -def _run_checkpoint_once(tensor_dict, - evaluators=None, - batch_processor=None, - checkpoint_dirs=None, - variables_to_restore=None, - restore_fn=None, - num_batches=1, - master='', - save_graph=False, - save_graph_dir='', - losses_dict=None): - """Evaluates metrics defined in evaluators and returns summaries. - - This function loads the latest checkpoint in checkpoint_dirs and evaluates - all metrics defined in evaluators. The metrics are processed in batch by the - batch_processor. - - Args: - tensor_dict: a dictionary holding tensors representing a batch of detections - and corresponding groundtruth annotations. - evaluators: a list of object of type DetectionEvaluator to be used for - evaluation. Note that the metric names produced by different evaluators - must be unique. - batch_processor: a function taking four arguments: - 1. tensor_dict: the same tensor_dict that is passed in as the first - argument to this function. - 2. sess: a tensorflow session - 3. batch_index: an integer representing the index of the batch amongst - all batches - By default, batch_processor is None, which defaults to running: - return sess.run(tensor_dict) - To skip an image, it suffices to return an empty dictionary in place of - result_dict. - checkpoint_dirs: list of directories to load into an EnsembleModel. If it - has only one directory, EnsembleModel will not be used -- - a DetectionModel - will be instantiated directly. Not used if restore_fn is set. - variables_to_restore: None, or a dictionary mapping variable names found in - a checkpoint to model variables. The dictionary would normally be - generated by creating a tf.train.ExponentialMovingAverage object and - calling its variables_to_restore() method. Not used if restore_fn is set. - restore_fn: None, or a function that takes a tf.Session object and correctly - restores all necessary variables from the correct checkpoint file. If - None, attempts to restore from the first directory in checkpoint_dirs. - num_batches: the number of batches to use for evaluation. - master: the location of the Tensorflow session. - save_graph: whether or not the Tensorflow graph is stored as a pbtxt file. - save_graph_dir: where to store the Tensorflow graph on disk. If save_graph - is True this must be non-empty. - losses_dict: optional dictionary of scalar detection losses. - - Returns: - global_step: the count of global steps. - all_evaluator_metrics: A dictionary containing metric names and values. - - Raises: - ValueError: if restore_fn is None and checkpoint_dirs doesn't have at least - one element. - ValueError: if save_graph is True and save_graph_dir is not defined. - """ - if save_graph and not save_graph_dir: - raise ValueError('`save_graph_dir` must be defined.') - sess = tf.Session(master, graph=tf.get_default_graph()) - sess.run(tf.global_variables_initializer()) - sess.run(tf.local_variables_initializer()) - sess.run(tf.tables_initializer()) - if restore_fn: - restore_fn(sess) - else: - if not checkpoint_dirs: - raise ValueError('`checkpoint_dirs` must have at least one entry.') - checkpoint_file = tf.train.latest_checkpoint(checkpoint_dirs[0]) - saver = tf.train.Saver(variables_to_restore) - saver.restore(sess, checkpoint_file) - - if save_graph: - tf.train.write_graph(sess.graph_def, save_graph_dir, 'eval.pbtxt') - - counters = {'skipped': 0, 'success': 0} - aggregate_result_losses_dict = collections.defaultdict(list) - with tf.contrib.slim.queues.QueueRunners(sess): - try: - for batch in range(int(num_batches)): - if (batch + 1) % 100 == 0: - logging.info('Running eval ops batch %d/%d', batch + 1, num_batches) - if not batch_processor: - try: - if not losses_dict: - losses_dict = {} - result_dict, result_losses_dict = sess.run([tensor_dict, - losses_dict]) - counters['success'] += 1 - except tf.errors.InvalidArgumentError: - logging.info('Skipping image') - counters['skipped'] += 1 - result_dict = {} - else: - result_dict, result_losses_dict = batch_processor( - tensor_dict, sess, batch, counters, losses_dict=losses_dict) - if not result_dict: - continue - for key, value in iter(result_losses_dict.items()): - aggregate_result_losses_dict[key].append(value) - for evaluator in evaluators: - # TODO(b/65130867): Use image_id tensor once we fix the input data - # decoders to return correct image_id. - # TODO(akuznetsa): result_dict contains batches of images, while - # add_single_ground_truth_image_info expects a single image. Fix - evaluator.add_single_ground_truth_image_info( - image_id=batch, groundtruth_dict=result_dict) - evaluator.add_single_detected_image_info( - image_id=batch, detections_dict=result_dict) - logging.info('Running eval batches done.') - except tf.errors.OutOfRangeError: - logging.info('Done evaluating -- epoch limit reached') - finally: - # When done, ask the threads to stop. - logging.info('# success: %d', counters['success']) - logging.info('# skipped: %d', counters['skipped']) - all_evaluator_metrics = {} - for evaluator in evaluators: - metrics = evaluator.evaluate() - evaluator.clear() - if any(key in all_evaluator_metrics for key in metrics): - raise ValueError('Metric names between evaluators must not collide.') - all_evaluator_metrics.update(metrics) - global_step = tf.train.global_step(sess, tf.train.get_global_step()) - - for key, value in iter(aggregate_result_losses_dict.items()): - all_evaluator_metrics['Losses/' + key] = np.mean(value) - sess.close() - return (global_step, all_evaluator_metrics) - - -# TODO(rathodv): Add tests. -def repeated_checkpoint_run(tensor_dict, - summary_dir, - evaluators, - batch_processor=None, - checkpoint_dirs=None, - variables_to_restore=None, - restore_fn=None, - num_batches=1, - eval_interval_secs=120, - max_number_of_evaluations=None, - master='', - save_graph=False, - save_graph_dir='', - losses_dict=None): - """Periodically evaluates desired tensors using checkpoint_dirs or restore_fn. - - This function repeatedly loads a checkpoint and evaluates a desired - set of tensors (provided by tensor_dict) and hands the resulting numpy - arrays to a function result_processor which can be used to further - process/save/visualize the results. - - Args: - tensor_dict: a dictionary holding tensors representing a batch of detections - and corresponding groundtruth annotations. - summary_dir: a directory to write metrics summaries. - evaluators: a list of object of type DetectionEvaluator to be used for - evaluation. Note that the metric names produced by different evaluators - must be unique. - batch_processor: a function taking three arguments: - 1. tensor_dict: the same tensor_dict that is passed in as the first - argument to this function. - 2. sess: a tensorflow session - 3. batch_index: an integer representing the index of the batch amongst - all batches - By default, batch_processor is None, which defaults to running: - return sess.run(tensor_dict) - checkpoint_dirs: list of directories to load into a DetectionModel or an - EnsembleModel if restore_fn isn't set. Also used to determine when to run - next evaluation. Must have at least one element. - variables_to_restore: None, or a dictionary mapping variable names found in - a checkpoint to model variables. The dictionary would normally be - generated by creating a tf.train.ExponentialMovingAverage object and - calling its variables_to_restore() method. Not used if restore_fn is set. - restore_fn: a function that takes a tf.Session object and correctly restores - all necessary variables from the correct checkpoint file. - num_batches: the number of batches to use for evaluation. - eval_interval_secs: the number of seconds between each evaluation run. - max_number_of_evaluations: the max number of iterations of the evaluation. - If the value is left as None the evaluation continues indefinitely. - master: the location of the Tensorflow session. - save_graph: whether or not the Tensorflow graph is saved as a pbtxt file. - save_graph_dir: where to save on disk the Tensorflow graph. If store_graph - is True this must be non-empty. - losses_dict: optional dictionary of scalar detection losses. - - Returns: - metrics: A dictionary containing metric names and values in the latest - evaluation. - - Raises: - ValueError: if max_num_of_evaluations is not None or a positive number. - ValueError: if checkpoint_dirs doesn't have at least one element. - """ - if max_number_of_evaluations and max_number_of_evaluations <= 0: - raise ValueError( - '`number_of_steps` must be either None or a positive number.') - - if not checkpoint_dirs: - raise ValueError('`checkpoint_dirs` must have at least one entry.') - - last_evaluated_model_path = None - number_of_evaluations = 0 - while True: - start = time.time() - logging.info('Starting evaluation at ' + time.strftime( - '%Y-%m-%d-%H:%M:%S', time.gmtime())) - model_path = tf.train.latest_checkpoint(checkpoint_dirs[0]) - if not model_path: - logging.info('No model found in %s. Will try again in %d seconds', - checkpoint_dirs[0], eval_interval_secs) - elif model_path == last_evaluated_model_path: - logging.info('Found already evaluated checkpoint. Will try again in %d ' - 'seconds', eval_interval_secs) - else: - last_evaluated_model_path = model_path - global_step, metrics = _run_checkpoint_once(tensor_dict, evaluators, - batch_processor, - checkpoint_dirs, - variables_to_restore, - restore_fn, num_batches, - master, save_graph, - save_graph_dir, - losses_dict=losses_dict) - write_metrics(metrics, global_step, summary_dir) - number_of_evaluations += 1 - - if (max_number_of_evaluations and - number_of_evaluations >= max_number_of_evaluations): - logging.info('Finished evaluation!') - break - time_to_next_eval = start + eval_interval_secs - time.time() - if time_to_next_eval > 0: - time.sleep(time_to_next_eval) - - return metrics - - -def result_dict_for_single_example(image, - key, - detections, - groundtruth=None, - class_agnostic=False, - scale_to_absolute=False): - """Merges all detection and groundtruth information for a single example. - - Note that evaluation tools require classes that are 1-indexed, and so this - function performs the offset. If `class_agnostic` is True, all output classes - have label 1. - - Args: - image: A single 4D uint8 image tensor of shape [1, H, W, C]. - key: A single string tensor identifying the image. - detections: A dictionary of detections, returned from - DetectionModel.postprocess(). - groundtruth: (Optional) Dictionary of groundtruth items, with fields: - 'groundtruth_boxes': [num_boxes, 4] float32 tensor of boxes, in - normalized coordinates. - 'groundtruth_classes': [num_boxes] int64 tensor of 1-indexed classes. - 'groundtruth_area': [num_boxes] float32 tensor of bbox area. (Optional) - 'groundtruth_is_crowd': [num_boxes] int64 tensor. (Optional) - 'groundtruth_difficult': [num_boxes] int64 tensor. (Optional) - 'groundtruth_group_of': [num_boxes] int64 tensor. (Optional) - 'groundtruth_instance_masks': 3D int64 tensor of instance masks - (Optional). - class_agnostic: Boolean indicating whether the detections are class-agnostic - (i.e. binary). Default False. - scale_to_absolute: Boolean indicating whether boxes and keypoints should be - scaled to absolute coordinates. Note that for IoU based evaluations, it - does not matter whether boxes are expressed in absolute or relative - coordinates. Default False. - - Returns: - A dictionary with: - 'original_image': A [1, H, W, C] uint8 image tensor. - 'key': A string tensor with image identifier. - 'detection_boxes': [max_detections, 4] float32 tensor of boxes, in - normalized or absolute coordinates, depending on the value of - `scale_to_absolute`. - 'detection_scores': [max_detections] float32 tensor of scores. - 'detection_classes': [max_detections] int64 tensor of 1-indexed classes. - 'detection_masks': [max_detections, H, W] float32 tensor of binarized - masks, reframed to full image masks. - 'groundtruth_boxes': [num_boxes, 4] float32 tensor of boxes, in - normalized or absolute coordinates, depending on the value of - `scale_to_absolute`. (Optional) - 'groundtruth_classes': [num_boxes] int64 tensor of 1-indexed classes. - (Optional) - 'groundtruth_area': [num_boxes] float32 tensor of bbox area. (Optional) - 'groundtruth_is_crowd': [num_boxes] int64 tensor. (Optional) - 'groundtruth_difficult': [num_boxes] int64 tensor. (Optional) - 'groundtruth_group_of': [num_boxes] int64 tensor. (Optional) - 'groundtruth_instance_masks': 3D int64 tensor of instance masks - (Optional). - - """ - label_id_offset = 1 # Applying label id offset (b/63711816) - - input_data_fields = fields.InputDataFields - output_dict = { - input_data_fields.original_image: image, - input_data_fields.key: key, - } - - detection_fields = fields.DetectionResultFields - detection_boxes = detections[detection_fields.detection_boxes][0] - image_shape = tf.shape(image) - detection_scores = detections[detection_fields.detection_scores][0] - - if class_agnostic: - detection_classes = tf.ones_like(detection_scores, dtype=tf.int64) - else: - detection_classes = ( - tf.to_int64(detections[detection_fields.detection_classes][0]) + - label_id_offset) - - num_detections = tf.to_int32(detections[detection_fields.num_detections][0]) - detection_boxes = tf.slice( - detection_boxes, begin=[0, 0], size=[num_detections, -1]) - detection_classes = tf.slice( - detection_classes, begin=[0], size=[num_detections]) - detection_scores = tf.slice( - detection_scores, begin=[0], size=[num_detections]) - - if scale_to_absolute: - absolute_detection_boxlist = box_list_ops.to_absolute_coordinates( - box_list.BoxList(detection_boxes), image_shape[1], image_shape[2]) - output_dict[detection_fields.detection_boxes] = ( - absolute_detection_boxlist.get()) - else: - output_dict[detection_fields.detection_boxes] = detection_boxes - output_dict[detection_fields.detection_classes] = detection_classes - output_dict[detection_fields.detection_scores] = detection_scores - - if detection_fields.detection_masks in detections: - detection_masks = detections[detection_fields.detection_masks][0] - # TODO(rathodv): This should be done in model's postprocess - # function ideally. - detection_masks = tf.slice( - detection_masks, begin=[0, 0, 0], size=[num_detections, -1, -1]) - detection_masks_reframed = ops.reframe_box_masks_to_image_masks( - detection_masks, detection_boxes, image_shape[1], image_shape[2]) - detection_masks_reframed = tf.cast( - tf.greater(detection_masks_reframed, 0.5), tf.uint8) - output_dict[detection_fields.detection_masks] = detection_masks_reframed - if detection_fields.detection_keypoints in detections: - detection_keypoints = detections[detection_fields.detection_keypoints][0] - output_dict[detection_fields.detection_keypoints] = detection_keypoints - if scale_to_absolute: - absolute_detection_keypoints = keypoint_ops.scale( - detection_keypoints, image_shape[1], image_shape[2]) - output_dict[detection_fields.detection_keypoints] = ( - absolute_detection_keypoints) - - if groundtruth: - if input_data_fields.groundtruth_instance_masks in groundtruth: - groundtruth[input_data_fields.groundtruth_instance_masks] = tf.cast( - groundtruth[input_data_fields.groundtruth_instance_masks], tf.uint8) - output_dict.update(groundtruth) - if scale_to_absolute: - groundtruth_boxes = groundtruth[input_data_fields.groundtruth_boxes] - absolute_gt_boxlist = box_list_ops.to_absolute_coordinates( - box_list.BoxList(groundtruth_boxes), image_shape[1], image_shape[2]) - output_dict[input_data_fields.groundtruth_boxes] = ( - absolute_gt_boxlist.get()) - # For class-agnostic models, groundtruth classes all become 1. - if class_agnostic: - groundtruth_classes = groundtruth[input_data_fields.groundtruth_classes] - groundtruth_classes = tf.ones_like(groundtruth_classes, dtype=tf.int64) - output_dict[input_data_fields.groundtruth_classes] = groundtruth_classes - - return output_dict - - -def get_eval_metric_ops_for_evaluators(evaluation_metrics, - categories, - eval_dict, - include_metrics_per_category=False): - """Returns a dictionary of eval metric ops to use with `tf.EstimatorSpec`. - - Args: - evaluation_metrics: List of evaluation metric names. Current options are - 'coco_detection_metrics' and 'coco_mask_metrics'. - categories: A list of dicts, each of which has the following keys - - 'id': (required) an integer id uniquely identifying this category. - 'name': (required) string representing category name e.g., 'cat', 'dog'. - eval_dict: An evaluation dictionary, returned from - result_dict_for_single_example(). - include_metrics_per_category: If True, additionally include per-category - metrics. - - Returns: - A dictionary of metric names to tuple of value_op and update_op that can be - used as eval metric ops in tf.EstimatorSpec. - - Raises: - ValueError: If any of the metrics in `evaluation_metric` is not - 'coco_detection_metrics' or 'coco_mask_metrics'. - """ - evaluation_metrics = list(set(evaluation_metrics)) - - input_data_fields = fields.InputDataFields - detection_fields = fields.DetectionResultFields - eval_metric_ops = {} - for metric in evaluation_metrics: - if metric == 'coco_detection_metrics': - coco_evaluator = coco_evaluation.CocoDetectionEvaluator( - categories, include_metrics_per_category=include_metrics_per_category) - eval_metric_ops.update( - coco_evaluator.get_estimator_eval_metric_ops( - image_id=eval_dict[input_data_fields.key], - groundtruth_boxes=eval_dict[input_data_fields.groundtruth_boxes], - groundtruth_classes=eval_dict[ - input_data_fields.groundtruth_classes], - detection_boxes=eval_dict[detection_fields.detection_boxes], - detection_scores=eval_dict[detection_fields.detection_scores], - detection_classes=eval_dict[detection_fields.detection_classes], - groundtruth_is_crowd=eval_dict.get( - input_data_fields.groundtruth_is_crowd))) - elif metric == 'coco_mask_metrics': - coco_mask_evaluator = coco_evaluation.CocoMaskEvaluator( - categories, include_metrics_per_category=include_metrics_per_category) - eval_metric_ops.update( - coco_mask_evaluator.get_estimator_eval_metric_ops( - image_id=eval_dict[input_data_fields.key], - groundtruth_boxes=eval_dict[input_data_fields.groundtruth_boxes], - groundtruth_classes=eval_dict[ - input_data_fields.groundtruth_classes], - groundtruth_instance_masks=eval_dict[ - input_data_fields.groundtruth_instance_masks], - detection_scores=eval_dict[detection_fields.detection_scores], - detection_classes=eval_dict[detection_fields.detection_classes], - detection_masks=eval_dict[detection_fields.detection_masks], - groundtruth_is_crowd=eval_dict.get( - input_data_fields.groundtruth_is_crowd),)) - else: - raise ValueError('The only evaluation metrics supported are ' - '"coco_detection_metrics" and "coco_mask_metrics". ' - 'Found {} in the evaluation metrics'.format(metric)) - - return eval_metric_ops - - diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/eval_util_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/eval_util_test.py deleted file mode 100644 index e4b0ca3d8..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/eval_util_test.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for eval_util.""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import tensorflow as tf - - -from object_detection import eval_util -from object_detection.core import standard_fields as fields - - -class EvalUtilTest(tf.test.TestCase): - - def _get_categories_list(self): - return [{'id': 0, 'name': 'person'}, - {'id': 1, 'name': 'dog'}, - {'id': 2, 'name': 'cat'}] - - def _make_evaluation_dict(self): - input_data_fields = fields.InputDataFields - detection_fields = fields.DetectionResultFields - - image = tf.zeros(shape=[1, 20, 20, 3], dtype=tf.uint8) - key = tf.constant('image1') - detection_boxes = tf.constant([[[0., 0., 1., 1.]]]) - detection_scores = tf.constant([[0.8]]) - detection_classes = tf.constant([[0]]) - detection_masks = tf.ones(shape=[1, 1, 20, 20], dtype=tf.float32) - num_detections = tf.constant([1]) - groundtruth_boxes = tf.constant([[0., 0., 1., 1.]]) - groundtruth_classes = tf.constant([1]) - groundtruth_instance_masks = tf.ones(shape=[1, 20, 20], dtype=tf.uint8) - detections = { - detection_fields.detection_boxes: detection_boxes, - detection_fields.detection_scores: detection_scores, - detection_fields.detection_classes: detection_classes, - detection_fields.detection_masks: detection_masks, - detection_fields.num_detections: num_detections - } - groundtruth = { - input_data_fields.groundtruth_boxes: groundtruth_boxes, - input_data_fields.groundtruth_classes: groundtruth_classes, - input_data_fields.groundtruth_instance_masks: groundtruth_instance_masks - } - return eval_util.result_dict_for_single_example(image, key, detections, - groundtruth) - - def test_get_eval_metric_ops_for_coco_detections(self): - evaluation_metrics = ['coco_detection_metrics'] - categories = self._get_categories_list() - eval_dict = self._make_evaluation_dict() - metric_ops = eval_util.get_eval_metric_ops_for_evaluators( - evaluation_metrics, categories, eval_dict) - _, update_op = metric_ops['DetectionBoxes_Precision/mAP'] - - with self.test_session() as sess: - metrics = {} - for key, (value_op, _) in metric_ops.iteritems(): - metrics[key] = value_op - sess.run(update_op) - metrics = sess.run(metrics) - print(metrics) - self.assertAlmostEqual(1.0, metrics['DetectionBoxes_Precision/mAP']) - self.assertNotIn('DetectionMasks_Precision/mAP', metrics) - - def test_get_eval_metric_ops_for_coco_detections_and_masks(self): - evaluation_metrics = ['coco_detection_metrics', - 'coco_mask_metrics'] - categories = self._get_categories_list() - eval_dict = self._make_evaluation_dict() - metric_ops = eval_util.get_eval_metric_ops_for_evaluators( - evaluation_metrics, categories, eval_dict) - _, update_op_boxes = metric_ops['DetectionBoxes_Precision/mAP'] - _, update_op_masks = metric_ops['DetectionMasks_Precision/mAP'] - - with self.test_session() as sess: - metrics = {} - for key, (value_op, _) in metric_ops.iteritems(): - metrics[key] = value_op - sess.run(update_op_boxes) - sess.run(update_op_masks) - metrics = sess.run(metrics) - self.assertAlmostEqual(1.0, metrics['DetectionBoxes_Precision/mAP']) - self.assertAlmostEqual(1.0, metrics['DetectionMasks_Precision/mAP']) - - def test_get_eval_metric_ops_raises_error_with_unsupported_metric(self): - evaluation_metrics = ['unsupported_metrics'] - categories = self._get_categories_list() - eval_dict = self._make_evaluation_dict() - with self.assertRaises(ValueError): - eval_util.get_eval_metric_ops_for_evaluators( - evaluation_metrics, categories, eval_dict) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/evaluator.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/evaluator.py deleted file mode 100644 index 7352af522..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/evaluator.py +++ /dev/null @@ -1,278 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Detection model evaluator. - -This file provides a generic evaluation method that can be used to evaluate a -DetectionModel. -""" - -import logging -import tensorflow as tf - -from object_detection import eval_util -from object_detection.core import prefetcher -from object_detection.core import standard_fields as fields -from object_detection.metrics import coco_evaluation -from object_detection.utils import object_detection_evaluation - -# A dictionary of metric names to classes that implement the metric. The classes -# in the dictionary must implement -# utils.object_detection_evaluation.DetectionEvaluator interface. -EVAL_METRICS_CLASS_DICT = { - 'pascal_voc_detection_metrics': - object_detection_evaluation.PascalDetectionEvaluator, - 'weighted_pascal_voc_detection_metrics': - object_detection_evaluation.WeightedPascalDetectionEvaluator, - 'pascal_voc_instance_segmentation_metrics': - object_detection_evaluation.PascalInstanceSegmentationEvaluator, - 'weighted_pascal_voc_instance_segmentation_metrics': - object_detection_evaluation.WeightedPascalInstanceSegmentationEvaluator, - 'open_images_V2_detection_metrics': - object_detection_evaluation.OpenImagesDetectionEvaluator, - 'coco_detection_metrics': - coco_evaluation.CocoDetectionEvaluator, - 'coco_mask_metrics': - coco_evaluation.CocoMaskEvaluator, - 'oid_challenge_object_detection_metrics': - object_detection_evaluation.OpenImagesDetectionChallengeEvaluator, -} - -EVAL_DEFAULT_METRIC = 'pascal_voc_detection_metrics' - - -def _extract_predictions_and_losses(model, - create_input_dict_fn, - ignore_groundtruth=False): - """Constructs tensorflow detection graph and returns output tensors. - - Args: - model: model to perform predictions with. - create_input_dict_fn: function to create input tensor dictionaries. - ignore_groundtruth: whether groundtruth should be ignored. - - Returns: - prediction_groundtruth_dict: A dictionary with postprocessed tensors (keyed - by standard_fields.DetectionResultsFields) and optional groundtruth - tensors (keyed by standard_fields.InputDataFields). - losses_dict: A dictionary containing detection losses. This is empty when - ignore_groundtruth is true. - """ - input_dict = create_input_dict_fn() - prefetch_queue = prefetcher.prefetch(input_dict, capacity=500) - input_dict = prefetch_queue.dequeue() - original_image = tf.expand_dims(input_dict[fields.InputDataFields.image], 0) - preprocessed_image, true_image_shapes = model.preprocess( - tf.to_float(original_image)) - prediction_dict = model.predict(preprocessed_image, true_image_shapes) - detections = model.postprocess(prediction_dict, true_image_shapes) - - groundtruth = None - losses_dict = {} - if not ignore_groundtruth: - groundtruth = { - fields.InputDataFields.groundtruth_boxes: - input_dict[fields.InputDataFields.groundtruth_boxes], - fields.InputDataFields.groundtruth_classes: - input_dict[fields.InputDataFields.groundtruth_classes], - fields.InputDataFields.groundtruth_area: - input_dict[fields.InputDataFields.groundtruth_area], - fields.InputDataFields.groundtruth_is_crowd: - input_dict[fields.InputDataFields.groundtruth_is_crowd], - fields.InputDataFields.groundtruth_difficult: - input_dict[fields.InputDataFields.groundtruth_difficult] - } - if fields.InputDataFields.groundtruth_group_of in input_dict: - groundtruth[fields.InputDataFields.groundtruth_group_of] = ( - input_dict[fields.InputDataFields.groundtruth_group_of]) - groundtruth_masks_list = None - if fields.DetectionResultFields.detection_masks in detections: - groundtruth[fields.InputDataFields.groundtruth_instance_masks] = ( - input_dict[fields.InputDataFields.groundtruth_instance_masks]) - groundtruth_masks_list = [ - input_dict[fields.InputDataFields.groundtruth_instance_masks]] - groundtruth_keypoints_list = None - if fields.DetectionResultFields.detection_keypoints in detections: - groundtruth[fields.InputDataFields.groundtruth_keypoints] = ( - input_dict[fields.InputDataFields.groundtruth_keypoints]) - groundtruth_keypoints_list = [ - input_dict[fields.InputDataFields.groundtruth_keypoints]] - label_id_offset = 1 - model.provide_groundtruth( - [input_dict[fields.InputDataFields.groundtruth_boxes]], - [tf.one_hot(input_dict[fields.InputDataFields.groundtruth_classes] - - label_id_offset, depth=model.num_classes)], - groundtruth_masks_list, groundtruth_keypoints_list) - losses_dict.update(model.loss(prediction_dict, true_image_shapes)) - - result_dict = eval_util.result_dict_for_single_example( - original_image, - input_dict[fields.InputDataFields.source_id], - detections, - groundtruth, - class_agnostic=( - fields.DetectionResultFields.detection_classes not in detections), - scale_to_absolute=True) - return result_dict, losses_dict - - -def get_evaluators(eval_config, categories): - """Returns the evaluator class according to eval_config, valid for categories. - - Args: - eval_config: evaluation configurations. - categories: a list of categories to evaluate. - Returns: - An list of instances of DetectionEvaluator. - - Raises: - ValueError: if metric is not in the metric class dictionary. - """ - eval_metric_fn_keys = eval_config.metrics_set - if not eval_metric_fn_keys: - eval_metric_fn_keys = [EVAL_DEFAULT_METRIC] - evaluators_list = [] - for eval_metric_fn_key in eval_metric_fn_keys: - if eval_metric_fn_key not in EVAL_METRICS_CLASS_DICT: - raise ValueError('Metric not found: {}'.format(eval_metric_fn_key)) - evaluators_list.append( - EVAL_METRICS_CLASS_DICT[eval_metric_fn_key](categories=categories)) - return evaluators_list - - -def evaluate(create_input_dict_fn, create_model_fn, eval_config, categories, - checkpoint_dir, eval_dir, graph_hook_fn=None, evaluator_list=None): - """Evaluation function for detection models. - - Args: - create_input_dict_fn: a function to create a tensor input dictionary. - create_model_fn: a function that creates a DetectionModel. - eval_config: a eval_pb2.EvalConfig protobuf. - categories: a list of category dictionaries. Each dict in the list should - have an integer 'id' field and string 'name' field. - checkpoint_dir: directory to load the checkpoints to evaluate from. - eval_dir: directory to write evaluation metrics summary to. - graph_hook_fn: Optional function that is called after the training graph is - completely built. This is helpful to perform additional changes to the - training graph such as optimizing batchnorm. The function should modify - the default graph. - evaluator_list: Optional list of instances of DetectionEvaluator. If not - given, this list of metrics is created according to the eval_config. - - Returns: - metrics: A dictionary containing metric names and values from the latest - run. - """ - with tf.Graph().as_default(): - model = create_model_fn() - - if eval_config.ignore_groundtruth and not eval_config.export_path: - logging.fatal('If ignore_groundtruth=True then an export_path is ' - 'required. Aborting!!!') - - tensor_dict, losses_dict = _extract_predictions_and_losses( - model=model, - create_input_dict_fn=create_input_dict_fn, - ignore_groundtruth=eval_config.ignore_groundtruth) - - def _process_batch(tensor_dict, sess, batch_index, counters, - losses_dict=None): - """Evaluates tensors in tensor_dict, losses_dict and visualizes examples. - - This function calls sess.run on tensor_dict, evaluating the original_image - tensor only on the first K examples and visualizing detections overlaid - on this original_image. - - Args: - tensor_dict: a dictionary of tensors - sess: tensorflow session - batch_index: the index of the batch amongst all batches in the run. - counters: a dictionary holding 'success' and 'skipped' fields which can - be updated to keep track of number of successful and failed runs, - respectively. If these fields are not updated, then the success/skipped - counter values shown at the end of evaluation will be incorrect. - losses_dict: Optional dictonary of scalar loss tensors. - - Returns: - result_dict: a dictionary of numpy arrays - result_losses_dict: a dictionary of scalar losses. This is empty if input - losses_dict is None. - """ - try: - if not losses_dict: - losses_dict = {} - result_dict, result_losses_dict = sess.run([tensor_dict, losses_dict]) - counters['success'] += 1 - except tf.errors.InvalidArgumentError: - logging.info('Skipping image') - counters['skipped'] += 1 - return {}, {} - global_step = tf.train.global_step(sess, tf.train.get_global_step()) - if batch_index < eval_config.num_visualizations: - tag = 'image-{}'.format(batch_index) - eval_util.visualize_detection_results( - result_dict, - tag, - global_step, - categories=categories, - summary_dir=eval_dir, - export_dir=eval_config.visualization_export_dir, - show_groundtruth=eval_config.visualize_groundtruth_boxes, - groundtruth_box_visualization_color=eval_config. - groundtruth_box_visualization_color, - min_score_thresh=eval_config.min_score_threshold, - max_num_predictions=eval_config.max_num_boxes_to_visualize, - skip_scores=eval_config.skip_scores, - skip_labels=eval_config.skip_labels, - keep_image_id_for_visualization_export=eval_config. - keep_image_id_for_visualization_export) - return result_dict, result_losses_dict - - variables_to_restore = tf.global_variables() - global_step = tf.train.get_or_create_global_step() - variables_to_restore.append(global_step) - - if graph_hook_fn: graph_hook_fn() - - if eval_config.use_moving_averages: - variable_averages = tf.train.ExponentialMovingAverage(0.0) - variables_to_restore = variable_averages.variables_to_restore() - saver = tf.train.Saver(variables_to_restore) - - def _restore_latest_checkpoint(sess): - latest_checkpoint = tf.train.latest_checkpoint(checkpoint_dir) - saver.restore(sess, latest_checkpoint) - - if not evaluator_list: - evaluator_list = get_evaluators(eval_config, categories) - - metrics = eval_util.repeated_checkpoint_run( - tensor_dict=tensor_dict, - summary_dir=eval_dir, - evaluators=evaluator_list, - batch_processor=_process_batch, - checkpoint_dirs=[checkpoint_dir], - variables_to_restore=None, - restore_fn=_restore_latest_checkpoint, - num_batches=eval_config.num_examples, - eval_interval_secs=eval_config.eval_interval_secs, - max_number_of_evaluations=(1 if eval_config.ignore_groundtruth else - eval_config.max_evals - if eval_config.max_evals else None), - master=eval_config.eval_master, - save_graph=eval_config.save_graph, - save_graph_dir=(eval_dir if eval_config.save_graph else ''), - losses_dict=losses_dict) - - return metrics diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/export_inference_graph.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/export_inference_graph.py deleted file mode 100644 index 5d0699f19..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/export_inference_graph.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -r"""Tool to export an object detection model for inference. - -Prepares an object detection tensorflow graph for inference using model -configuration and an optional trained checkpoint. Outputs inference -graph, associated checkpoint files, a frozen inference graph and a -SavedModel (https://tensorflow.github.io/serving/serving_basic.html). - -The inference graph contains one of three input nodes depending on the user -specified option. - * `image_tensor`: Accepts a uint8 4-D tensor of shape [None, None, None, 3] - * `encoded_image_string_tensor`: Accepts a 1-D string tensor of shape [None] - containing encoded PNG or JPEG images. Image resolutions are expected to be - the same if more than 1 image is provided. - * `tf_example`: Accepts a 1-D string tensor of shape [None] containing - serialized TFExample protos. Image resolutions are expected to be the same - if more than 1 image is provided. - -and the following output nodes returned by the model.postprocess(..): - * `num_detections`: Outputs float32 tensors of the form [batch] - that specifies the number of valid boxes per image in the batch. - * `detection_boxes`: Outputs float32 tensors of the form - [batch, num_boxes, 4] containing detected boxes. - * `detection_scores`: Outputs float32 tensors of the form - [batch, num_boxes] containing class scores for the detections. - * `detection_classes`: Outputs float32 tensors of the form - [batch, num_boxes] containing classes for the detections. - * `detection_masks`: Outputs float32 tensors of the form - [batch, num_boxes, mask_height, mask_width] containing predicted instance - masks for each box if its present in the dictionary of postprocessed - tensors returned by the model. - -Notes: - * This tool uses `use_moving_averages` from eval_config to decide which - weights to freeze. - -Example Usage: --------------- -python export_inference_graph \ - --input_type image_tensor \ - --pipeline_config_path path/to/ssd_inception_v2.config \ - --trained_checkpoint_prefix path/to/model.ckpt \ - --output_directory path/to/exported_model_directory - -The expected output would be in the directory -path/to/exported_model_directory (which is created if it does not exist) -with contents: - - graph.pbtxt - - model.ckpt.data-00000-of-00001 - - model.ckpt.info - - model.ckpt.meta - - frozen_inference_graph.pb - + saved_model (a directory) - -Config overrides (see the `config_override` flag) are text protobufs -(also of type pipeline_pb2.TrainEvalPipelineConfig) which are used to override -certain fields in the provided pipeline_config_path. These are useful for -making small changes to the inference graph that differ from the training or -eval config. - -Example Usage (in which we change the second stage post-processing score -threshold to be 0.5): - -python export_inference_graph \ - --input_type image_tensor \ - --pipeline_config_path path/to/ssd_inception_v2.config \ - --trained_checkpoint_prefix path/to/model.ckpt \ - --output_directory path/to/exported_model_directory \ - --config_override " \ - model{ \ - faster_rcnn { \ - second_stage_post_processing { \ - batch_non_max_suppression { \ - score_threshold: 0.5 \ - } \ - } \ - } \ - }" -""" -import tensorflow as tf -from google.protobuf import text_format -from object_detection import exporter -from object_detection.protos import pipeline_pb2 - -slim = tf.contrib.slim -flags = tf.app.flags - -flags.DEFINE_string('input_type', 'image_tensor', 'Type of input node. Can be ' - 'one of [`image_tensor`, `encoded_image_string_tensor`, ' - '`tf_example`]') -flags.DEFINE_string('input_shape', None, - 'If input_type is `image_tensor`, this can explicitly set ' - 'the shape of this input tensor to a fixed size. The ' - 'dimensions are to be provided as a comma-separated list ' - 'of integers. A value of -1 can be used for unknown ' - 'dimensions. If not specified, for an `image_tensor, the ' - 'default shape will be partially specified as ' - '`[None, None, None, 3]`.') -flags.DEFINE_string('pipeline_config_path', None, - 'Path to a pipeline_pb2.TrainEvalPipelineConfig config ' - 'file.') -flags.DEFINE_string('trained_checkpoint_prefix', None, - 'Path to trained checkpoint, typically of the form ' - 'path/to/model.ckpt') -flags.DEFINE_string('output_directory', None, 'Path to write outputs.') -flags.DEFINE_string('config_override', '', - 'pipeline_pb2.TrainEvalPipelineConfig ' - 'text proto to override pipeline_config_path.') -tf.app.flags.mark_flag_as_required('pipeline_config_path') -tf.app.flags.mark_flag_as_required('trained_checkpoint_prefix') -tf.app.flags.mark_flag_as_required('output_directory') -FLAGS = flags.FLAGS - - -def main(_): - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - with tf.gfile.GFile(FLAGS.pipeline_config_path, 'r') as f: - text_format.Merge(f.read(), pipeline_config) - text_format.Merge(FLAGS.config_override, pipeline_config) - if FLAGS.input_shape: - input_shape = [ - int(dim) if dim != '-1' else None - for dim in FLAGS.input_shape.split(',') - ] - else: - input_shape = None - exporter.export_inference_graph(FLAGS.input_type, pipeline_config, - FLAGS.trained_checkpoint_prefix, - FLAGS.output_directory, input_shape) - - -if __name__ == '__main__': - tf.app.run() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/exporter.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/exporter.py deleted file mode 100644 index 05b09b1f7..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/exporter.py +++ /dev/null @@ -1,465 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Functions to export object detection inference graph.""" -import logging -import os -import tempfile -import tensorflow as tf -from google.protobuf import text_format -from tensorflow.core.protobuf import saver_pb2 -from tensorflow.python import pywrap_tensorflow -from tensorflow.python.client import session -from tensorflow.python.framework import graph_util -from tensorflow.python.platform import gfile -from tensorflow.python.saved_model import signature_constants -from tensorflow.python.training import saver as saver_lib -from object_detection.builders import model_builder -from object_detection.core import standard_fields as fields -from object_detection.data_decoders import tf_example_decoder - -slim = tf.contrib.slim - - -# TODO(derekjchow): Replace with freeze_graph.freeze_graph_with_def_protos when -# newer version of Tensorflow becomes more common. -def freeze_graph_with_def_protos( - input_graph_def, - input_saver_def, - input_checkpoint, - output_node_names, - restore_op_name, - filename_tensor_name, - clear_devices, - initializer_nodes, - variable_names_blacklist=''): - """Converts all variables in a graph and checkpoint into constants.""" - del restore_op_name, filename_tensor_name # Unused by updated loading code. - - # 'input_checkpoint' may be a prefix if we're using Saver V2 format - if not saver_lib.checkpoint_exists(input_checkpoint): - raise ValueError( - 'Input checkpoint "' + input_checkpoint + '" does not exist!') - - if not output_node_names: - raise ValueError( - 'You must supply the name of a node to --output_node_names.') - - # Remove all the explicit device specifications for this node. This helps to - # make the graph more portable. - if clear_devices: - for node in input_graph_def.node: - node.device = '' - - with tf.Graph().as_default(): - tf.import_graph_def(input_graph_def, name='') - config = tf.ConfigProto(graph_options=tf.GraphOptions()) - with session.Session(config=config) as sess: - if input_saver_def: - saver = saver_lib.Saver(saver_def=input_saver_def) - saver.restore(sess, input_checkpoint) - else: - var_list = {} - reader = pywrap_tensorflow.NewCheckpointReader(input_checkpoint) - var_to_shape_map = reader.get_variable_to_shape_map() - for key in var_to_shape_map: - try: - tensor = sess.graph.get_tensor_by_name(key + ':0') - except KeyError: - # This tensor doesn't exist in the graph (for example it's - # 'global_step' or a similar housekeeping element) so skip it. - continue - var_list[key] = tensor - saver = saver_lib.Saver(var_list=var_list) - saver.restore(sess, input_checkpoint) - if initializer_nodes: - sess.run(initializer_nodes) - - variable_names_blacklist = (variable_names_blacklist.split(',') if - variable_names_blacklist else None) - output_graph_def = graph_util.convert_variables_to_constants( - sess, - input_graph_def, - output_node_names.split(','), - variable_names_blacklist=variable_names_blacklist) - - return output_graph_def - - -def replace_variable_values_with_moving_averages(graph, - current_checkpoint_file, - new_checkpoint_file): - """Replaces variable values in the checkpoint with their moving averages. - - If the current checkpoint has shadow variables maintaining moving averages of - the variables defined in the graph, this function generates a new checkpoint - where the variables contain the values of their moving averages. - - Args: - graph: a tf.Graph object. - current_checkpoint_file: a checkpoint containing both original variables and - their moving averages. - new_checkpoint_file: file path to write a new checkpoint. - """ - with graph.as_default(): - variable_averages = tf.train.ExponentialMovingAverage(0.0) - ema_variables_to_restore = variable_averages.variables_to_restore() - with tf.Session() as sess: - read_saver = tf.train.Saver(ema_variables_to_restore) - read_saver.restore(sess, current_checkpoint_file) - write_saver = tf.train.Saver() - write_saver.save(sess, new_checkpoint_file) - - -def _image_tensor_input_placeholder(input_shape=None): - """Returns input placeholder and a 4-D uint8 image tensor.""" - if input_shape is None: - input_shape = (None, None, None, 3) - input_tensor = tf.placeholder( - dtype=tf.uint8, shape=input_shape, name='image_tensor') - return input_tensor, input_tensor - - -def _tf_example_input_placeholder(): - """Returns input that accepts a batch of strings with tf examples. - - Returns: - a tuple of input placeholder and the output decoded images. - """ - batch_tf_example_placeholder = tf.placeholder( - tf.string, shape=[None], name='tf_example') - def decode(tf_example_string_tensor): - tensor_dict = tf_example_decoder.TfExampleDecoder().decode( - tf_example_string_tensor) - image_tensor = tensor_dict[fields.InputDataFields.image] - return image_tensor - return (batch_tf_example_placeholder, - tf.map_fn(decode, - elems=batch_tf_example_placeholder, - dtype=tf.uint8, - parallel_iterations=32, - back_prop=False)) - - -def _encoded_image_string_tensor_input_placeholder(): - """Returns input that accepts a batch of PNG or JPEG strings. - - Returns: - a tuple of input placeholder and the output decoded images. - """ - batch_image_str_placeholder = tf.placeholder( - dtype=tf.string, - shape=[None], - name='encoded_image_string_tensor') - def decode(encoded_image_string_tensor): - image_tensor = tf.image.decode_image(encoded_image_string_tensor, - channels=3) - image_tensor.set_shape((None, None, 3)) - return image_tensor - return (batch_image_str_placeholder, - tf.map_fn( - decode, - elems=batch_image_str_placeholder, - dtype=tf.uint8, - parallel_iterations=32, - back_prop=False)) - - -input_placeholder_fn_map = { - 'image_tensor': _image_tensor_input_placeholder, - 'encoded_image_string_tensor': - _encoded_image_string_tensor_input_placeholder, - 'tf_example': _tf_example_input_placeholder, -} - - -def _add_output_tensor_nodes(postprocessed_tensors, - output_collection_name='inference_op'): - """Adds output nodes for detection boxes and scores. - - Adds the following nodes for output tensors - - * num_detections: float32 tensor of shape [batch_size]. - * detection_boxes: float32 tensor of shape [batch_size, num_boxes, 4] - containing detected boxes. - * detection_scores: float32 tensor of shape [batch_size, num_boxes] - containing scores for the detected boxes. - * detection_classes: float32 tensor of shape [batch_size, num_boxes] - containing class predictions for the detected boxes. - * detection_keypoints: (Optional) float32 tensor of shape - [batch_size, num_boxes, num_keypoints, 2] containing keypoints for each - detection box. - * detection_masks: (Optional) float32 tensor of shape - [batch_size, num_boxes, mask_height, mask_width] containing masks for each - detection box. - - Args: - postprocessed_tensors: a dictionary containing the following fields - 'detection_boxes': [batch, max_detections, 4] - 'detection_scores': [batch, max_detections] - 'detection_classes': [batch, max_detections] - 'detection_masks': [batch, max_detections, mask_height, mask_width] - (optional). - 'num_detections': [batch] - output_collection_name: Name of collection to add output tensors to. - - Returns: - A tensor dict containing the added output tensor nodes. - """ - detection_fields = fields.DetectionResultFields - label_id_offset = 1 - boxes = postprocessed_tensors.get(detection_fields.detection_boxes) - scores = postprocessed_tensors.get(detection_fields.detection_scores) - classes = postprocessed_tensors.get( - detection_fields.detection_classes) + label_id_offset - keypoints = postprocessed_tensors.get(detection_fields.detection_keypoints) - masks = postprocessed_tensors.get(detection_fields.detection_masks) - num_detections = postprocessed_tensors.get(detection_fields.num_detections) - outputs = {} - outputs[detection_fields.detection_boxes] = tf.identity( - boxes, name=detection_fields.detection_boxes) - outputs[detection_fields.detection_scores] = tf.identity( - scores, name=detection_fields.detection_scores) - outputs[detection_fields.detection_classes] = tf.identity( - classes, name=detection_fields.detection_classes) - outputs[detection_fields.num_detections] = tf.identity( - num_detections, name=detection_fields.num_detections) - if keypoints is not None: - outputs[detection_fields.detection_keypoints] = tf.identity( - keypoints, name=detection_fields.detection_keypoints) - if masks is not None: - outputs[detection_fields.detection_masks] = tf.identity( - masks, name=detection_fields.detection_masks) - for output_key in outputs: - tf.add_to_collection(output_collection_name, outputs[output_key]) - if masks is not None: - tf.add_to_collection(output_collection_name, - outputs[detection_fields.detection_masks]) - return outputs - - -def write_frozen_graph(frozen_graph_path, frozen_graph_def): - """Writes frozen graph to disk. - - Args: - frozen_graph_path: Path to write inference graph. - frozen_graph_def: tf.GraphDef holding frozen graph. - """ - with gfile.GFile(frozen_graph_path, 'wb') as f: - f.write(frozen_graph_def.SerializeToString()) - logging.info('%d ops in the final graph.', len(frozen_graph_def.node)) - - -def write_saved_model(saved_model_path, - frozen_graph_def, - inputs, - outputs): - """Writes SavedModel to disk. - - If checkpoint_path is not None bakes the weights into the graph thereby - eliminating the need of checkpoint files during inference. If the model - was trained with moving averages, setting use_moving_averages to true - restores the moving averages, otherwise the original set of variables - is restored. - - Args: - saved_model_path: Path to write SavedModel. - frozen_graph_def: tf.GraphDef holding frozen graph. - inputs: The input image tensor to use for detection. - outputs: A tensor dictionary containing the outputs of a DetectionModel. - """ - with tf.Graph().as_default(): - with session.Session() as sess: - - tf.import_graph_def(frozen_graph_def, name='') - - builder = tf.saved_model.builder.SavedModelBuilder(saved_model_path) - - tensor_info_inputs = { - 'inputs': tf.saved_model.utils.build_tensor_info(inputs)} - tensor_info_outputs = {} - for k, v in outputs.items(): - tensor_info_outputs[k] = tf.saved_model.utils.build_tensor_info(v) - - detection_signature = ( - tf.saved_model.signature_def_utils.build_signature_def( - inputs=tensor_info_inputs, - outputs=tensor_info_outputs, - method_name=signature_constants.PREDICT_METHOD_NAME)) - - builder.add_meta_graph_and_variables( - sess, [tf.saved_model.tag_constants.SERVING], - signature_def_map={ - signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: - detection_signature, - }, - ) - builder.save() - - -def write_graph_and_checkpoint(inference_graph_def, - model_path, - input_saver_def, - trained_checkpoint_prefix): - """Writes the graph and the checkpoint into disk.""" - for node in inference_graph_def.node: - node.device = '' - with tf.Graph().as_default(): - tf.import_graph_def(inference_graph_def, name='') - with session.Session() as sess: - saver = saver_lib.Saver(saver_def=input_saver_def, - save_relative_paths=True) - saver.restore(sess, trained_checkpoint_prefix) - saver.save(sess, model_path) - - -def _get_outputs_from_inputs(input_tensors, detection_model, - output_collection_name): - inputs = tf.to_float(input_tensors) - preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs) - output_tensors = detection_model.predict( - preprocessed_inputs, true_image_shapes) - postprocessed_tensors = detection_model.postprocess( - output_tensors, true_image_shapes) - return _add_output_tensor_nodes(postprocessed_tensors, - output_collection_name) - - -def _build_detection_graph(input_type, detection_model, input_shape, - output_collection_name, graph_hook_fn): - """Build the detection graph.""" - if input_type not in input_placeholder_fn_map: - raise ValueError('Unknown input type: {}'.format(input_type)) - placeholder_args = {} - if input_shape is not None: - if input_type != 'image_tensor': - raise ValueError('Can only specify input shape for `image_tensor` ' - 'inputs.') - placeholder_args['input_shape'] = input_shape - placeholder_tensor, input_tensors = input_placeholder_fn_map[input_type]( - **placeholder_args) - outputs = _get_outputs_from_inputs( - input_tensors=input_tensors, - detection_model=detection_model, - output_collection_name=output_collection_name) - - # Add global step to the graph. - slim.get_or_create_global_step() - - if graph_hook_fn: graph_hook_fn() - - return outputs, placeholder_tensor - - -def _export_inference_graph(input_type, - detection_model, - use_moving_averages, - trained_checkpoint_prefix, - output_directory, - additional_output_tensor_names=None, - input_shape=None, - output_collection_name='inference_op', - graph_hook_fn=None): - """Export helper.""" - tf.gfile.MakeDirs(output_directory) - frozen_graph_path = os.path.join(output_directory, - 'frozen_inference_graph.pb') - saved_model_path = os.path.join(output_directory, 'saved_model') - model_path = os.path.join(output_directory, 'model.ckpt') - - outputs, placeholder_tensor = _build_detection_graph( - input_type=input_type, - detection_model=detection_model, - input_shape=input_shape, - output_collection_name=output_collection_name, - graph_hook_fn=graph_hook_fn) - - saver_kwargs = {} - if use_moving_averages: - # This check is to be compatible with both version of SaverDef. - if os.path.isfile(trained_checkpoint_prefix): - saver_kwargs['write_version'] = saver_pb2.SaverDef.V1 - temp_checkpoint_prefix = tempfile.NamedTemporaryFile().name - else: - temp_checkpoint_prefix = tempfile.mkdtemp() - replace_variable_values_with_moving_averages( - tf.get_default_graph(), trained_checkpoint_prefix, - temp_checkpoint_prefix) - checkpoint_to_use = temp_checkpoint_prefix - else: - checkpoint_to_use = trained_checkpoint_prefix - - saver = tf.train.Saver(**saver_kwargs) - input_saver_def = saver.as_saver_def() - - write_graph_and_checkpoint( - inference_graph_def=tf.get_default_graph().as_graph_def(), - model_path=model_path, - input_saver_def=input_saver_def, - trained_checkpoint_prefix=checkpoint_to_use) - - if additional_output_tensor_names is not None: - output_node_names = ','.join(outputs.keys()+additional_output_tensor_names) - else: - output_node_names = ','.join(outputs.keys()) - - frozen_graph_def = freeze_graph_with_def_protos( - input_graph_def=tf.get_default_graph().as_graph_def(), - input_saver_def=input_saver_def, - input_checkpoint=checkpoint_to_use, - output_node_names=output_node_names, - restore_op_name='save/restore_all', - filename_tensor_name='save/Const:0', - clear_devices=True, - initializer_nodes='') - write_frozen_graph(frozen_graph_path, frozen_graph_def) - write_saved_model(saved_model_path, frozen_graph_def, - placeholder_tensor, outputs) - - -def export_inference_graph(input_type, - pipeline_config, - trained_checkpoint_prefix, - output_directory, - input_shape=None, - output_collection_name='inference_op', - additional_output_tensor_names=None): - """Exports inference graph for the model specified in the pipeline config. - - Args: - input_type: Type of input for the graph. Can be one of [`image_tensor`, - `tf_example`]. - pipeline_config: pipeline_pb2.TrainAndEvalPipelineConfig proto. - trained_checkpoint_prefix: Path to the trained checkpoint file. - output_directory: Path to write outputs. - input_shape: Sets a fixed shape for an `image_tensor` input. If not - specified, will default to [None, None, None, 3]. - output_collection_name: Name of collection to add output tensors to. - If None, does not add output tensors to a collection. - additional_output_tensor_names: list of additional output - tensors to include in the frozen graph. - """ - detection_model = model_builder.build(pipeline_config.model, - is_training=False) - _export_inference_graph(input_type, detection_model, - pipeline_config.eval_config.use_moving_averages, - trained_checkpoint_prefix, - output_directory, additional_output_tensor_names, - input_shape, output_collection_name, - graph_hook_fn=None) - pipeline_config.eval_config.use_moving_averages = False - config_text = text_format.MessageToString(pipeline_config) - with tf.gfile.Open( - os.path.join(output_directory, 'pipeline.config'), 'wb') as f: - f.write(config_text) diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/exporter_test.py b/research/mlperf_object_detection/Mask_RCNN/object_detection/exporter_test.py deleted file mode 100644 index cf6e85b20..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/exporter_test.py +++ /dev/null @@ -1,864 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -"""Tests for object_detection.export_inference_graph.""" -import os -import numpy as np -import six -import tensorflow as tf -from google.protobuf import text_format -from object_detection import exporter -from object_detection.builders import model_builder -from object_detection.core import model -from object_detection.protos import pipeline_pb2 - -if six.PY2: - import mock # pylint: disable=g-import-not-at-top -else: - from unittest import mock # pylint: disable=g-import-not-at-top - -slim = tf.contrib.slim - - -class FakeModel(model.DetectionModel): - - def __init__(self, add_detection_keypoints=False, add_detection_masks=False): - self._add_detection_keypoints = add_detection_keypoints - self._add_detection_masks = add_detection_masks - - def preprocess(self, inputs): - true_image_shapes = [] # Doesn't matter for the fake model. - return tf.identity(inputs), true_image_shapes - - def predict(self, preprocessed_inputs, true_image_shapes): - return {'image': tf.layers.conv2d(preprocessed_inputs, 3, 1)} - - def postprocess(self, prediction_dict, true_image_shapes): - with tf.control_dependencies(prediction_dict.values()): - postprocessed_tensors = { - 'detection_boxes': tf.constant([[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]], tf.float32), - 'detection_scores': tf.constant([[0.7, 0.6], - [0.9, 0.0]], tf.float32), - 'detection_classes': tf.constant([[0, 1], - [1, 0]], tf.float32), - 'num_detections': tf.constant([2, 1], tf.float32) - } - if self._add_detection_keypoints: - postprocessed_tensors['detection_keypoints'] = tf.constant( - np.arange(48).reshape([2, 2, 6, 2]), tf.float32) - if self._add_detection_masks: - postprocessed_tensors['detection_masks'] = tf.constant( - np.arange(64).reshape([2, 2, 4, 4]), tf.float32) - return postprocessed_tensors - - def restore_map(self, checkpoint_path, fine_tune_checkpoint_type): - pass - - def loss(self, prediction_dict, true_image_shapes): - pass - - -class ExportInferenceGraphTest(tf.test.TestCase): - - def _save_checkpoint_from_mock_model(self, checkpoint_path, - use_moving_averages): - g = tf.Graph() - with g.as_default(): - mock_model = FakeModel() - preprocessed_inputs, true_image_shapes = mock_model.preprocess( - tf.placeholder(tf.float32, shape=[None, None, None, 3])) - predictions = mock_model.predict(preprocessed_inputs, true_image_shapes) - mock_model.postprocess(predictions, true_image_shapes) - if use_moving_averages: - tf.train.ExponentialMovingAverage(0.0).apply() - slim.get_or_create_global_step() - saver = tf.train.Saver() - init = tf.global_variables_initializer() - with self.test_session() as sess: - sess.run(init) - saver.save(sess, checkpoint_path) - - def _load_inference_graph(self, inference_graph_path): - od_graph = tf.Graph() - with od_graph.as_default(): - od_graph_def = tf.GraphDef() - with tf.gfile.GFile(inference_graph_path) as fid: - serialized_graph = fid.read() - od_graph_def.ParseFromString(serialized_graph) - tf.import_graph_def(od_graph_def, name='') - return od_graph - - def _create_tf_example(self, image_array): - with self.test_session(): - encoded_image = tf.image.encode_jpeg(tf.constant(image_array)).eval() - def _bytes_feature(value): - return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/encoded': _bytes_feature(encoded_image), - 'image/format': _bytes_feature('jpg'), - 'image/source_id': _bytes_feature('image_id') - })).SerializeToString() - return example - - def test_export_graph_with_image_tensor_input(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=False) - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel() - output_directory = os.path.join(tmp_dir, 'output') - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='image_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - self.assertTrue(os.path.exists(os.path.join( - output_directory, 'saved_model', 'saved_model.pb'))) - - def test_export_graph_with_fixed_size_image_tensor_input(self): - input_shape = [1, 320, 320, 3] - - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model( - trained_checkpoint_prefix, use_moving_averages=False) - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel() - output_directory = os.path.join(tmp_dir, 'output') - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='image_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory, - input_shape=input_shape) - saved_model_path = os.path.join(output_directory, 'saved_model') - self.assertTrue( - os.path.exists(os.path.join(saved_model_path, 'saved_model.pb'))) - - with tf.Graph().as_default() as od_graph: - with self.test_session(graph=od_graph) as sess: - meta_graph = tf.saved_model.loader.load( - sess, [tf.saved_model.tag_constants.SERVING], saved_model_path) - signature = meta_graph.signature_def['serving_default'] - input_tensor_name = signature.inputs['inputs'].name - image_tensor = od_graph.get_tensor_by_name(input_tensor_name) - self.assertSequenceEqual(image_tensor.get_shape().as_list(), - input_shape) - - def test_export_graph_with_tf_example_input(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=False) - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel() - output_directory = os.path.join(tmp_dir, 'output') - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='tf_example', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - self.assertTrue(os.path.exists(os.path.join( - output_directory, 'saved_model', 'saved_model.pb'))) - - def test_export_graph_with_encoded_image_string_input(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=False) - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel() - output_directory = os.path.join(tmp_dir, 'output') - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='encoded_image_string_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - self.assertTrue(os.path.exists(os.path.join( - output_directory, 'saved_model', 'saved_model.pb'))) - - def _get_variables_in_checkpoint(self, checkpoint_file): - return set([ - var_name - for var_name, _ in tf.train.list_variables(checkpoint_file)]) - - def test_replace_variable_values_with_moving_averages(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - new_checkpoint_prefix = os.path.join(tmp_dir, 'new.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - graph = tf.Graph() - with graph.as_default(): - fake_model = FakeModel() - preprocessed_inputs, true_image_shapes = fake_model.preprocess( - tf.placeholder(dtype=tf.float32, shape=[None, None, None, 3])) - predictions = fake_model.predict(preprocessed_inputs, true_image_shapes) - fake_model.postprocess(predictions, true_image_shapes) - exporter.replace_variable_values_with_moving_averages( - graph, trained_checkpoint_prefix, new_checkpoint_prefix) - - expected_variables = set(['conv2d/bias', 'conv2d/kernel']) - variables_in_old_ckpt = self._get_variables_in_checkpoint( - trained_checkpoint_prefix) - self.assertIn('conv2d/bias/ExponentialMovingAverage', - variables_in_old_ckpt) - self.assertIn('conv2d/kernel/ExponentialMovingAverage', - variables_in_old_ckpt) - variables_in_new_ckpt = self._get_variables_in_checkpoint( - new_checkpoint_prefix) - self.assertTrue(expected_variables.issubset(variables_in_new_ckpt)) - self.assertNotIn('conv2d/bias/ExponentialMovingAverage', - variables_in_new_ckpt) - self.assertNotIn('conv2d/kernel/ExponentialMovingAverage', - variables_in_new_ckpt) - - def test_export_graph_with_moving_averages(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel() - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = True - exporter.export_inference_graph( - input_type='image_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - self.assertTrue(os.path.exists(os.path.join( - output_directory, 'saved_model', 'saved_model.pb'))) - expected_variables = set(['conv2d/bias', 'conv2d/kernel', 'global_step']) - actual_variables = set( - [var_name for var_name, _ in tf.train.list_variables(output_directory)]) - self.assertTrue(expected_variables.issubset(actual_variables)) - - def test_export_model_with_all_output_nodes(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - inference_graph_path = os.path.join(output_directory, - 'frozen_inference_graph.pb') - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - exporter.export_inference_graph( - input_type='image_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - inference_graph = self._load_inference_graph(inference_graph_path) - with self.test_session(graph=inference_graph): - inference_graph.get_tensor_by_name('image_tensor:0') - inference_graph.get_tensor_by_name('detection_boxes:0') - inference_graph.get_tensor_by_name('detection_scores:0') - inference_graph.get_tensor_by_name('detection_classes:0') - inference_graph.get_tensor_by_name('detection_keypoints:0') - inference_graph.get_tensor_by_name('detection_masks:0') - inference_graph.get_tensor_by_name('num_detections:0') - - def test_export_model_with_detection_only_nodes(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - inference_graph_path = os.path.join(output_directory, - 'frozen_inference_graph.pb') - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel(add_detection_masks=False) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - exporter.export_inference_graph( - input_type='image_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - inference_graph = self._load_inference_graph(inference_graph_path) - with self.test_session(graph=inference_graph): - inference_graph.get_tensor_by_name('image_tensor:0') - inference_graph.get_tensor_by_name('detection_boxes:0') - inference_graph.get_tensor_by_name('detection_scores:0') - inference_graph.get_tensor_by_name('detection_classes:0') - inference_graph.get_tensor_by_name('num_detections:0') - with self.assertRaises(KeyError): - inference_graph.get_tensor_by_name('detection_keypoints:0') - inference_graph.get_tensor_by_name('detection_masks:0') - - def test_export_and_run_inference_with_image_tensor(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - inference_graph_path = os.path.join(output_directory, - 'frozen_inference_graph.pb') - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='image_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - - inference_graph = self._load_inference_graph(inference_graph_path) - with self.test_session(graph=inference_graph) as sess: - image_tensor = inference_graph.get_tensor_by_name('image_tensor:0') - boxes = inference_graph.get_tensor_by_name('detection_boxes:0') - scores = inference_graph.get_tensor_by_name('detection_scores:0') - classes = inference_graph.get_tensor_by_name('detection_classes:0') - keypoints = inference_graph.get_tensor_by_name('detection_keypoints:0') - masks = inference_graph.get_tensor_by_name('detection_masks:0') - num_detections = inference_graph.get_tensor_by_name('num_detections:0') - (boxes_np, scores_np, classes_np, keypoints_np, masks_np, - num_detections_np) = sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={image_tensor: np.ones((2, 4, 4, 3)).astype(np.uint8)}) - self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]]) - self.assertAllClose(scores_np, [[0.7, 0.6], - [0.9, 0.0]]) - self.assertAllClose(classes_np, [[1, 2], - [2, 1]]) - self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2])) - self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4])) - self.assertAllClose(num_detections_np, [2, 1]) - - def _create_encoded_image_string(self, image_array_np, encoding_format): - od_graph = tf.Graph() - with od_graph.as_default(): - if encoding_format == 'jpg': - encoded_string = tf.image.encode_jpeg(image_array_np) - elif encoding_format == 'png': - encoded_string = tf.image.encode_png(image_array_np) - else: - raise ValueError('Supports only the following formats: `jpg`, `png`') - with self.test_session(graph=od_graph): - return encoded_string.eval() - - def test_export_and_run_inference_with_encoded_image_string_tensor(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - inference_graph_path = os.path.join(output_directory, - 'frozen_inference_graph.pb') - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='encoded_image_string_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - - inference_graph = self._load_inference_graph(inference_graph_path) - jpg_image_str = self._create_encoded_image_string( - np.ones((4, 4, 3)).astype(np.uint8), 'jpg') - png_image_str = self._create_encoded_image_string( - np.ones((4, 4, 3)).astype(np.uint8), 'png') - with self.test_session(graph=inference_graph) as sess: - image_str_tensor = inference_graph.get_tensor_by_name( - 'encoded_image_string_tensor:0') - boxes = inference_graph.get_tensor_by_name('detection_boxes:0') - scores = inference_graph.get_tensor_by_name('detection_scores:0') - classes = inference_graph.get_tensor_by_name('detection_classes:0') - keypoints = inference_graph.get_tensor_by_name('detection_keypoints:0') - masks = inference_graph.get_tensor_by_name('detection_masks:0') - num_detections = inference_graph.get_tensor_by_name('num_detections:0') - for image_str in [jpg_image_str, png_image_str]: - image_str_batch_np = np.hstack([image_str]* 2) - (boxes_np, scores_np, classes_np, keypoints_np, masks_np, - num_detections_np) = sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={image_str_tensor: image_str_batch_np}) - self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]]) - self.assertAllClose(scores_np, [[0.7, 0.6], - [0.9, 0.0]]) - self.assertAllClose(classes_np, [[1, 2], - [2, 1]]) - self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2])) - self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4])) - self.assertAllClose(num_detections_np, [2, 1]) - - def test_raise_runtime_error_on_images_with_different_sizes(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - inference_graph_path = os.path.join(output_directory, - 'frozen_inference_graph.pb') - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='encoded_image_string_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - - inference_graph = self._load_inference_graph(inference_graph_path) - large_image = self._create_encoded_image_string( - np.ones((4, 4, 3)).astype(np.uint8), 'jpg') - small_image = self._create_encoded_image_string( - np.ones((2, 2, 3)).astype(np.uint8), 'jpg') - - image_str_batch_np = np.hstack([large_image, small_image]) - with self.test_session(graph=inference_graph) as sess: - image_str_tensor = inference_graph.get_tensor_by_name( - 'encoded_image_string_tensor:0') - boxes = inference_graph.get_tensor_by_name('detection_boxes:0') - scores = inference_graph.get_tensor_by_name('detection_scores:0') - classes = inference_graph.get_tensor_by_name('detection_classes:0') - keypoints = inference_graph.get_tensor_by_name('detection_keypoints:0') - masks = inference_graph.get_tensor_by_name('detection_masks:0') - num_detections = inference_graph.get_tensor_by_name('num_detections:0') - with self.assertRaisesRegexp(tf.errors.InvalidArgumentError, - 'TensorArray.*shape'): - sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={image_str_tensor: image_str_batch_np}) - - def test_export_and_run_inference_with_tf_example(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - inference_graph_path = os.path.join(output_directory, - 'frozen_inference_graph.pb') - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='tf_example', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - - inference_graph = self._load_inference_graph(inference_graph_path) - tf_example_np = np.expand_dims(self._create_tf_example( - np.ones((4, 4, 3)).astype(np.uint8)), axis=0) - with self.test_session(graph=inference_graph) as sess: - tf_example = inference_graph.get_tensor_by_name('tf_example:0') - boxes = inference_graph.get_tensor_by_name('detection_boxes:0') - scores = inference_graph.get_tensor_by_name('detection_scores:0') - classes = inference_graph.get_tensor_by_name('detection_classes:0') - keypoints = inference_graph.get_tensor_by_name('detection_keypoints:0') - masks = inference_graph.get_tensor_by_name('detection_masks:0') - num_detections = inference_graph.get_tensor_by_name('num_detections:0') - (boxes_np, scores_np, classes_np, keypoints_np, masks_np, - num_detections_np) = sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={tf_example: tf_example_np}) - self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]]) - self.assertAllClose(scores_np, [[0.7, 0.6], - [0.9, 0.0]]) - self.assertAllClose(classes_np, [[1, 2], - [2, 1]]) - self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2])) - self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4])) - self.assertAllClose(num_detections_np, [2, 1]) - - def test_write_frozen_graph(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - inference_graph_path = os.path.join(output_directory, - 'frozen_inference_graph.pb') - tf.gfile.MakeDirs(output_directory) - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - detection_model = model_builder.build(pipeline_config.model, - is_training=False) - outputs, _ = exporter._build_detection_graph( - input_type='tf_example', - detection_model=detection_model, - input_shape=None, - output_collection_name='inference_op', - graph_hook_fn=None) - output_node_names = ','.join(outputs.keys()) - saver = tf.train.Saver() - input_saver_def = saver.as_saver_def() - frozen_graph_def = exporter.freeze_graph_with_def_protos( - input_graph_def=tf.get_default_graph().as_graph_def(), - input_saver_def=input_saver_def, - input_checkpoint=trained_checkpoint_prefix, - output_node_names=output_node_names, - restore_op_name='save/restore_all', - filename_tensor_name='save/Const:0', - clear_devices=True, - initializer_nodes='') - exporter.write_frozen_graph(inference_graph_path, frozen_graph_def) - - inference_graph = self._load_inference_graph(inference_graph_path) - tf_example_np = np.expand_dims(self._create_tf_example( - np.ones((4, 4, 3)).astype(np.uint8)), axis=0) - with self.test_session(graph=inference_graph) as sess: - tf_example = inference_graph.get_tensor_by_name('tf_example:0') - boxes = inference_graph.get_tensor_by_name('detection_boxes:0') - scores = inference_graph.get_tensor_by_name('detection_scores:0') - classes = inference_graph.get_tensor_by_name('detection_classes:0') - keypoints = inference_graph.get_tensor_by_name('detection_keypoints:0') - masks = inference_graph.get_tensor_by_name('detection_masks:0') - num_detections = inference_graph.get_tensor_by_name('num_detections:0') - (boxes_np, scores_np, classes_np, keypoints_np, masks_np, - num_detections_np) = sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={tf_example: tf_example_np}) - self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]]) - self.assertAllClose(scores_np, [[0.7, 0.6], - [0.9, 0.0]]) - self.assertAllClose(classes_np, [[1, 2], - [2, 1]]) - self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2])) - self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4])) - self.assertAllClose(num_detections_np, [2, 1]) - - def test_export_graph_saves_pipeline_file(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=True) - output_directory = os.path.join(tmp_dir, 'output') - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel() - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - exporter.export_inference_graph( - input_type='image_tensor', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - expected_pipeline_path = os.path.join( - output_directory, 'pipeline.config') - self.assertTrue(os.path.exists(expected_pipeline_path)) - - written_pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - with tf.gfile.GFile(expected_pipeline_path, 'r') as f: - proto_str = f.read() - text_format.Merge(proto_str, written_pipeline_config) - self.assertProtoEquals(pipeline_config, written_pipeline_config) - - def test_export_saved_model_and_run_inference(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=False) - output_directory = os.path.join(tmp_dir, 'output') - saved_model_path = os.path.join(output_directory, 'saved_model') - - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='tf_example', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - - tf_example_np = np.hstack([self._create_tf_example( - np.ones((4, 4, 3)).astype(np.uint8))] * 2) - with tf.Graph().as_default() as od_graph: - with self.test_session(graph=od_graph) as sess: - meta_graph = tf.saved_model.loader.load( - sess, [tf.saved_model.tag_constants.SERVING], saved_model_path) - - signature = meta_graph.signature_def['serving_default'] - input_tensor_name = signature.inputs['inputs'].name - tf_example = od_graph.get_tensor_by_name(input_tensor_name) - - boxes = od_graph.get_tensor_by_name( - signature.outputs['detection_boxes'].name) - scores = od_graph.get_tensor_by_name( - signature.outputs['detection_scores'].name) - classes = od_graph.get_tensor_by_name( - signature.outputs['detection_classes'].name) - keypoints = od_graph.get_tensor_by_name( - signature.outputs['detection_keypoints'].name) - masks = od_graph.get_tensor_by_name( - signature.outputs['detection_masks'].name) - num_detections = od_graph.get_tensor_by_name( - signature.outputs['num_detections'].name) - - (boxes_np, scores_np, classes_np, keypoints_np, masks_np, - num_detections_np) = sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={tf_example: tf_example_np}) - self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]]) - self.assertAllClose(scores_np, [[0.7, 0.6], - [0.9, 0.0]]) - self.assertAllClose(classes_np, [[1, 2], - [2, 1]]) - self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2])) - self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4])) - self.assertAllClose(num_detections_np, [2, 1]) - - def test_write_saved_model(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=False) - output_directory = os.path.join(tmp_dir, 'output') - saved_model_path = os.path.join(output_directory, 'saved_model') - tf.gfile.MakeDirs(output_directory) - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - detection_model = model_builder.build(pipeline_config.model, - is_training=False) - outputs, placeholder_tensor = exporter._build_detection_graph( - input_type='tf_example', - detection_model=detection_model, - input_shape=None, - output_collection_name='inference_op', - graph_hook_fn=None) - output_node_names = ','.join(outputs.keys()) - saver = tf.train.Saver() - input_saver_def = saver.as_saver_def() - frozen_graph_def = exporter.freeze_graph_with_def_protos( - input_graph_def=tf.get_default_graph().as_graph_def(), - input_saver_def=input_saver_def, - input_checkpoint=trained_checkpoint_prefix, - output_node_names=output_node_names, - restore_op_name='save/restore_all', - filename_tensor_name='save/Const:0', - clear_devices=True, - initializer_nodes='') - exporter.write_saved_model( - saved_model_path=saved_model_path, - frozen_graph_def=frozen_graph_def, - inputs=placeholder_tensor, - outputs=outputs) - - tf_example_np = np.hstack([self._create_tf_example( - np.ones((4, 4, 3)).astype(np.uint8))] * 2) - with tf.Graph().as_default() as od_graph: - with self.test_session(graph=od_graph) as sess: - meta_graph = tf.saved_model.loader.load( - sess, [tf.saved_model.tag_constants.SERVING], saved_model_path) - - signature = meta_graph.signature_def['serving_default'] - input_tensor_name = signature.inputs['inputs'].name - tf_example = od_graph.get_tensor_by_name(input_tensor_name) - - boxes = od_graph.get_tensor_by_name( - signature.outputs['detection_boxes'].name) - scores = od_graph.get_tensor_by_name( - signature.outputs['detection_scores'].name) - classes = od_graph.get_tensor_by_name( - signature.outputs['detection_classes'].name) - keypoints = od_graph.get_tensor_by_name( - signature.outputs['detection_keypoints'].name) - masks = od_graph.get_tensor_by_name( - signature.outputs['detection_masks'].name) - num_detections = od_graph.get_tensor_by_name( - signature.outputs['num_detections'].name) - - (boxes_np, scores_np, classes_np, keypoints_np, masks_np, - num_detections_np) = sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={tf_example: tf_example_np}) - self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]]) - self.assertAllClose(scores_np, [[0.7, 0.6], - [0.9, 0.0]]) - self.assertAllClose(classes_np, [[1, 2], - [2, 1]]) - self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2])) - self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4])) - self.assertAllClose(num_detections_np, [2, 1]) - - def test_export_checkpoint_and_run_inference(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=False) - output_directory = os.path.join(tmp_dir, 'output') - model_path = os.path.join(output_directory, 'model.ckpt') - meta_graph_path = model_path + '.meta' - - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - exporter.export_inference_graph( - input_type='tf_example', - pipeline_config=pipeline_config, - trained_checkpoint_prefix=trained_checkpoint_prefix, - output_directory=output_directory) - - tf_example_np = np.hstack([self._create_tf_example( - np.ones((4, 4, 3)).astype(np.uint8))] * 2) - with tf.Graph().as_default() as od_graph: - with self.test_session(graph=od_graph) as sess: - new_saver = tf.train.import_meta_graph(meta_graph_path) - new_saver.restore(sess, model_path) - - tf_example = od_graph.get_tensor_by_name('tf_example:0') - boxes = od_graph.get_tensor_by_name('detection_boxes:0') - scores = od_graph.get_tensor_by_name('detection_scores:0') - classes = od_graph.get_tensor_by_name('detection_classes:0') - keypoints = od_graph.get_tensor_by_name('detection_keypoints:0') - masks = od_graph.get_tensor_by_name('detection_masks:0') - num_detections = od_graph.get_tensor_by_name('num_detections:0') - (boxes_np, scores_np, classes_np, keypoints_np, masks_np, - num_detections_np) = sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={tf_example: tf_example_np}) - self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]]) - self.assertAllClose(scores_np, [[0.7, 0.6], - [0.9, 0.0]]) - self.assertAllClose(classes_np, [[1, 2], - [2, 1]]) - self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2])) - self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4])) - self.assertAllClose(num_detections_np, [2, 1]) - - def test_write_graph_and_checkpoint(self): - tmp_dir = self.get_temp_dir() - trained_checkpoint_prefix = os.path.join(tmp_dir, 'model.ckpt') - self._save_checkpoint_from_mock_model(trained_checkpoint_prefix, - use_moving_averages=False) - output_directory = os.path.join(tmp_dir, 'output') - model_path = os.path.join(output_directory, 'model.ckpt') - meta_graph_path = model_path + '.meta' - tf.gfile.MakeDirs(output_directory) - with mock.patch.object( - model_builder, 'build', autospec=True) as mock_builder: - mock_builder.return_value = FakeModel( - add_detection_keypoints=True, add_detection_masks=True) - pipeline_config = pipeline_pb2.TrainEvalPipelineConfig() - pipeline_config.eval_config.use_moving_averages = False - detection_model = model_builder.build(pipeline_config.model, - is_training=False) - exporter._build_detection_graph( - input_type='tf_example', - detection_model=detection_model, - input_shape=None, - output_collection_name='inference_op', - graph_hook_fn=None) - saver = tf.train.Saver() - input_saver_def = saver.as_saver_def() - exporter.write_graph_and_checkpoint( - inference_graph_def=tf.get_default_graph().as_graph_def(), - model_path=model_path, - input_saver_def=input_saver_def, - trained_checkpoint_prefix=trained_checkpoint_prefix) - - tf_example_np = np.hstack([self._create_tf_example( - np.ones((4, 4, 3)).astype(np.uint8))] * 2) - with tf.Graph().as_default() as od_graph: - with self.test_session(graph=od_graph) as sess: - new_saver = tf.train.import_meta_graph(meta_graph_path) - new_saver.restore(sess, model_path) - - tf_example = od_graph.get_tensor_by_name('tf_example:0') - boxes = od_graph.get_tensor_by_name('detection_boxes:0') - scores = od_graph.get_tensor_by_name('detection_scores:0') - classes = od_graph.get_tensor_by_name('detection_classes:0') - keypoints = od_graph.get_tensor_by_name('detection_keypoints:0') - masks = od_graph.get_tensor_by_name('detection_masks:0') - num_detections = od_graph.get_tensor_by_name('num_detections:0') - (boxes_np, scores_np, classes_np, keypoints_np, masks_np, - num_detections_np) = sess.run( - [boxes, scores, classes, keypoints, masks, num_detections], - feed_dict={tf_example: tf_example_np}) - self.assertAllClose(boxes_np, [[[0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 0.8, 0.8]], - [[0.5, 0.5, 1.0, 1.0], - [0.0, 0.0, 0.0, 0.0]]]) - self.assertAllClose(scores_np, [[0.7, 0.6], - [0.9, 0.0]]) - self.assertAllClose(classes_np, [[1, 2], - [2, 1]]) - self.assertAllClose(keypoints_np, np.arange(48).reshape([2, 2, 6, 2])) - self.assertAllClose(masks_np, np.arange(64).reshape([2, 2, 4, 4])) - self.assertAllClose(num_detections_np, [2, 1]) - - -if __name__ == '__main__': - tf.test.main() diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/configuring_jobs.md b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/configuring_jobs.md deleted file mode 100644 index 9b042625b..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/configuring_jobs.md +++ /dev/null @@ -1,162 +0,0 @@ -# Configuring the Object Detection Training Pipeline - -## Overview - -The Tensorflow Object Detection API uses protobuf files to configure the -training and evaluation process. The schema for the training pipeline can be -found in object_detection/protos/pipeline.proto. At a high level, the config -file is split into 5 parts: - -1. The `model` configuration. This defines what type of model will be trained -(ie. meta-architecture, feature extractor). -2. The `train_config`, which decides what parameters should be used to train -model parameters (ie. SGD parameters, input preprocessing and feature extractor -initialization values). -3. The `eval_config`, which determines what set of metrics will be reported for -evaluation (currently we only support the PASCAL VOC metrics). -4. The `train_input_config`, which defines what dataset the model should be -trained on. -5. The `eval_input_config`, which defines what dataset the model will be -evaluated on. Typically this should be different than the training input -dataset. - -A skeleton configuration file is shown below: - -``` -model { -(... Add model config here...) -} - -train_config : { -(... Add train_config here...) -} - -train_input_reader: { -(... Add train_input configuration here...) -} - -eval_config: { -} - -eval_input_reader: { -(... Add eval_input configuration here...) -} -``` - -## Picking Model Parameters - -There are a large number of model parameters to configure. The best settings -will depend on your given application. Faster R-CNN models are better suited to -cases where high accuracy is desired and latency is of lower priority. -Conversely, if processing time is the most important factor, SSD models are -recommended. Read [our paper](https://arxiv.org/abs/1611.10012) for a more -detailed discussion on the speed vs accuracy tradeoff. - -To help new users get started, sample model configurations have been provided -in the object_detection/samples/configs folder. The contents of these -configuration files can be pasted into `model` field of the skeleton -configuration. Users should note that the `num_classes` field should be changed -to a value suited for the dataset the user is training on. - -## Defining Inputs - -The Tensorflow Object Detection API accepts inputs in the TFRecord file format. -Users must specify the locations of both the training and evaluation files. -Additionally, users should also specify a label map, which define the mapping -between a class id and class name. The label map should be identical between -training and evaluation datasets. - -An example input configuration looks as follows: - -``` -tf_record_input_reader { - input_path: "/usr/home/username/data/train.record" -} -label_map_path: "/usr/home/username/data/label_map.pbtxt" -``` - -Users should substitute the `input_path` and `label_map_path` arguments and -insert the input configuration into the `train_input_reader` and -`eval_input_reader` fields in the skeleton configuration. Note that the paths -can also point to Google Cloud Storage buckets (ie. -"gs://project_bucket/train.record") for use on Google Cloud. - -## Configuring the Trainer - -The `train_config` defines parts of the training process: - -1. Model parameter initialization. -2. Input preprocessing. -3. SGD parameters. - -A sample `train_config` is below: - -``` -batch_size: 1 -optimizer { - momentum_optimizer: { - learning_rate: { - manual_step_learning_rate { - initial_learning_rate: 0.0002 - schedule { - step: 0 - learning_rate: .0002 - } - schedule { - step: 900000 - learning_rate: .00002 - } - schedule { - step: 1200000 - learning_rate: .000002 - } - } - } - momentum_optimizer_value: 0.9 - } - use_moving_average: false -} -fine_tune_checkpoint: "/usr/home/username/tmp/model.ckpt-#####" -from_detection_checkpoint: true -gradient_clipping_by_norm: 10.0 -data_augmentation_options { - random_horizontal_flip { - } -} -``` - -### Model Parameter Initialization - -While optional, it is highly recommended that users utilize other object -detection checkpoints. Training an object detector from scratch can take days. -To speed up the training process, it is recommended that users re-use the -feature extractor parameters from a pre-existing object classification or -detection checkpoint. `train_config` provides two fields to specify -pre-existing checkpoints: `fine_tune_checkpoint` and -`from_detection_checkpoint`. `fine_tune_checkpoint` should provide a path to -the pre-existing checkpoint -(ie:"/usr/home/username/checkpoint/model.ckpt-#####"). -`from_detection_checkpoint` is a boolean value. If false, it assumes the -checkpoint was from an object classification checkpoint. Note that starting -from a detection checkpoint will usually result in a faster training job than -a classification checkpoint. - -The list of provided checkpoints can be found [here](detection_model_zoo.md). - -### Input Preprocessing - -The `data_augmentation_options` in `train_config` can be used to specify -how training data can be modified. This field is optional. - -### SGD Parameters - -The remainings parameters in `train_config` are hyperparameters for gradient -descent. Please note that the optimal learning rates provided in these -configuration files may depend on the specifics of the training setup (e.g. -number of workers, gpu type). - -## Configuring the Evaluator - -Currently evaluation is fixed to generating metrics as defined by the PASCAL VOC -challenge. The parameters for `eval_config` are set to reasonable defaults and -typically do not need to be configured. diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/defining_your_own_model.md b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/defining_your_own_model.md deleted file mode 100644 index 865f6af16..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/defining_your_own_model.md +++ /dev/null @@ -1,137 +0,0 @@ -# So you want to create a new model! - -In this section, we discuss some of the abstractions that we use -for defining detection models. If you would like to define a new model -architecture for detection and use it in the Tensorflow Detection API, -then this section should also serve as a high level guide to the files that you -will need to edit to get your new model working. - -## DetectionModels (`object_detection/core/model.py`) - -In order to be trained, evaluated, and exported for serving using our -provided binaries, all models under the Tensorflow Object Detection API must -implement the `DetectionModel` interface (see the full definition in `object_detection/core/model.py`). In particular, -each of these models are responsible for implementing 5 functions: - -* `preprocess`: Run any preprocessing (e.g., scaling/shifting/reshaping) of - input values that is necessary prior to running the detector on an input - image. -* `predict`: Produce “raw” prediction tensors that can be passed to loss or - postprocess functions. -* `postprocess`: Convert predicted output tensors to final detections. -* `loss`: Compute scalar loss tensors with respect to provided groundtruth. -* `restore`: Load a checkpoint into the Tensorflow graph. - -Given a `DetectionModel` at training time, we pass each image batch through -the following sequence of functions to compute a loss which can be optimized via -SGD: - -``` -inputs (images tensor) -> preprocess -> predict -> loss -> outputs (loss tensor) -``` - -And at eval time, we pass each image batch through the following sequence of -functions to produce a set of detections: - -``` -inputs (images tensor) -> preprocess -> predict -> postprocess -> - outputs (boxes tensor, scores tensor, classes tensor, num_detections tensor) -``` - -Some conventions to be aware of: - -* `DetectionModel`s should make no assumptions about the input size or aspect - ratio --- they are responsible for doing any resize/reshaping necessary - (see docstring for the `preprocess` function). -* Output classes are always integers in the range `[0, num_classes)`. - Any mapping of these integers to semantic labels is to be handled outside - of this class. We never explicitly emit a “background class” --- thus 0 is - the first non-background class and any logic of predicting and removing - implicit background classes must be handled internally by the implementation. -* Detected boxes are to be interpreted as being in - `[y_min, x_min, y_max, x_max]` format and normalized relative to the - image window. -* We do not specifically assume any kind of probabilistic interpretation of the - scores --- the only important thing is their relative ordering. Thus - implementations of the postprocess function are free to output logits, - probabilities, calibrated probabilities, or anything else. - -## Defining a new Faster R-CNN or SSD Feature Extractor - -In most cases, you probably will not implement a `DetectionModel` from scratch ---- instead you might create a new feature extractor to be used by one of the -SSD or Faster R-CNN meta-architectures. (We think of meta-architectures as -classes that define entire families of models using the `DetectionModel` -abstraction). - -Note: For the following discussion to make sense, we recommend first becoming -familiar with the [Faster R-CNN](https://arxiv.org/abs/1506.01497) paper. - -Let’s now imagine that you have invented a brand new network architecture -(say, “InceptionV100”) for classification and want to see how InceptionV100 -would behave as a feature extractor for detection (say, with Faster R-CNN). -A similar procedure would hold for SSD models, but we’ll discuss Faster R-CNN. - -To use InceptionV100, we will have to define a new -`FasterRCNNFeatureExtractor` and pass it to our `FasterRCNNMetaArch` -constructor as input. See -`object_detection/meta_architectures/faster_rcnn_meta_arch.py` for definitions -of `FasterRCNNFeatureExtractor` and `FasterRCNNMetaArch`, respectively. -A `FasterRCNNFeatureExtractor` must define a few -functions: - -* `preprocess`: Run any preprocessing of input values that is necessary prior - to running the detector on an input image. -* `_extract_proposal_features`: Extract first stage Region Proposal Network - (RPN) features. -* `_extract_box_classifier_features`: Extract second stage Box Classifier - features. -* `restore_from_classification_checkpoint_fn`: Load a checkpoint into the - Tensorflow graph. - -See the `object_detection/models/faster_rcnn_resnet_v1_feature_extractor.py` -definition as one example. Some remarks: - -* We typically initialize the weights of this feature extractor - using those from the - [Slim Resnet-101 classification checkpoint](https://github.com/tensorflow/models/tree/master/research/slim#pre-trained-models), - and we know - that images were preprocessed when training this checkpoint - by subtracting a channel mean from each input - image. Thus, we implement the preprocess function to replicate the same - channel mean subtraction behavior. -* The “full” resnet classification network defined in slim is cut into two - parts --- all but the last “resnet block” is put into the - `_extract_proposal_features` function and the final block is separately - defined in the `_extract_box_classifier_features function`. In general, - some experimentation may be required to decide on an optimal layer at - which to “cut” your feature extractor into these two pieces for Faster R-CNN. - -## Register your model for configuration - -Assuming that your new feature extractor does not require nonstandard -configuration, you will want to ideally be able to simply change the -“feature_extractor.type” fields in your configuration protos to point to a -new feature extractor. In order for our API to know how to understand this -new type though, you will first have to register your new feature -extractor with the model builder (`object_detection/builders/model_builder.py`), -whose job is to create models from config protos.. - -Registration is simple --- just add a pointer to the new Feature Extractor -class that you have defined in one of the SSD or Faster R-CNN Feature -Extractor Class maps at the top of the -`object_detection/builders/model_builder.py` file. -We recommend adding a test in `object_detection/builders/model_builder_test.py` -to make sure that parsing your proto will work as expected. - -## Taking your new model for a spin - -After registration you are ready to go with your model! Some final tips: - -* To save time debugging, try running your configuration file locally first - (both training and evaluation). -* Do a sweep of learning rates to figure out which learning rate is best - for your model. -* A small but often important detail: you may find it necessary to disable - batchnorm training (that is, load the batch norm parameters from the - classification checkpoint, but do not update them during gradient descent). diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/detection_model_zoo.md b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/detection_model_zoo.md deleted file mode 100644 index 37cea8ad8..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/detection_model_zoo.md +++ /dev/null @@ -1,116 +0,0 @@ -# Tensorflow detection model zoo - -We provide a collection of detection models pre-trained on the [COCO -dataset](http://mscoco.org), the [Kitti dataset](http://www.cvlibs.net/datasets/kitti/), and the -[Open Images dataset](https://github.com/openimages/dataset). These models can -be useful for -out-of-the-box inference if you are interested in categories already in COCO -(e.g., humans, cars, etc) or in Open Images (e.g., -surfboard, jacuzzi, etc). They are also useful for initializing your models when -training on novel datasets. - -In the table below, we list each such pre-trained model including: - -* a model name that corresponds to a config file that was used to train this - model in the `samples/configs` directory, -* a download link to a tar.gz file containing the pre-trained model, -* model speed --- we report running time in ms per 600x600 image (including all - pre and post-processing), but please be - aware that these timings depend highly on one's specific hardware - configuration (these timings were performed using an Nvidia - GeForce GTX TITAN X card) and should be treated more as relative timings in - many cases. Also note that desktop GPU timing does not always reflect mobile - run time. For example Mobilenet V2 is faster on mobile devices than Mobilenet - V1, but is slightly slower on desktop GPU. -* detector performance on subset of the COCO validation set or Open Images test split as measured by the dataset-specific mAP measure. - Here, higher is better, and we only report bounding box mAP rounded to the - nearest integer. -* Output types (`Boxes`, and `Masks` if applicable ) - -You can un-tar each tar.gz file via, e.g.,: - -``` -tar -xzvf ssd_mobilenet_v1_coco.tar.gz -``` - -Inside the un-tar'ed directory, you will find: - -* a graph proto (`graph.pbtxt`) -* a checkpoint - (`model.ckpt.data-00000-of-00001`, `model.ckpt.index`, `model.ckpt.meta`) -* a frozen graph proto with weights baked into the graph as constants - (`frozen_inference_graph.pb`) to be used for out of the box inference - (try this out in the Jupyter notebook!) -* a config file (`pipeline.config`) which was used to generate the graph. These - directly correspond to a config file in the - [samples/configs](https://github.com/tensorflow/models/tree/master/research/object_detection/samples/configs)) directory but often with a modified score threshold. In the case - of the heavier Faster R-CNN models, we also provide a version of the model - that uses a highly reduced number of proposals for speed. - -Some remarks on frozen inference graphs: - -* If you try to evaluate the frozen graph, you may find performance numbers for - some of the models to be slightly lower than what we report in the below - tables. This is because we discard detections with scores below a - threshold (typically 0.3) when creating the frozen graph. This corresponds - effectively to picking a point on the precision recall curve of - a detector (and discarding the part past that point), which negatively impacts - standard mAP metrics. -* Our frozen inference graphs are generated using the - [v1.5.0](https://github.com/tensorflow/tensorflow/tree/v1.5.0) - release version of Tensorflow and we do not guarantee that these will work - with other versions; this being said, each frozen inference graph can be - regenerated using your current version of Tensorflow by re-running the - [exporter](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/exporting_models.md), - pointing it at the model directory as well as the config file inside of it. - - -## COCO-trained models {#coco-models} - -| Model name | Speed (ms) | COCO mAP[^1] | Outputs | -| ------------ | :--------------: | :--------------: | :-------------: | -| [ssd_mobilenet_v1_coco](http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_2017_11_17.tar.gz) | 30 | 21 | Boxes | -| [ssd_mobilenet_v2_coco](http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz) | 31 | 22 | Boxes | -| [ssdlite_mobilenet_v2_coco](http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz) | 27 | 22 | Boxes | -| [ssd_inception_v2_coco](http://download.tensorflow.org/models/object_detection/ssd_inception_v2_coco_2017_11_17.tar.gz) | 42 | 24 | Boxes | -| [faster_rcnn_inception_v2_coco](http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_v2_coco_2018_01_28.tar.gz) | 58 | 28 | Boxes | -| [faster_rcnn_resnet50_coco](http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet50_coco_2018_01_28.tar.gz) | 89 | 30 | Boxes | -| [faster_rcnn_resnet50_lowproposals_coco](http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet50_lowproposals_coco_2018_01_28.tar.gz) | 64 | | Boxes | -| [rfcn_resnet101_coco](http://download.tensorflow.org/models/object_detection/rfcn_resnet101_coco_2018_01_28.tar.gz) | 92 | 30 | Boxes | -| [faster_rcnn_resnet101_coco](http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet101_coco_2018_01_28.tar.gz) | 106 | 32 | Boxes | -| [faster_rcnn_resnet101_lowproposals_coco](http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet101_lowproposals_coco_2018_01_28.tar.gz) | 82 | | Boxes | -| [faster_rcnn_inception_resnet_v2_atrous_coco](http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz) | 620 | 37 | Boxes | -| [faster_rcnn_inception_resnet_v2_atrous_lowproposals_coco](http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_resnet_v2_atrous_lowproposals_coco_2018_01_28.tar.gz) | 241 | | Boxes | -| [faster_rcnn_nas](http://download.tensorflow.org/models/object_detection/faster_rcnn_nas_coco_2018_01_28.tar.gz) | 1833 | 43 | Boxes | -| [faster_rcnn_nas_lowproposals_coco](http://download.tensorflow.org/models/object_detection/faster_rcnn_nas_lowproposals_coco_2018_01_28.tar.gz) | 540 | | Boxes | -| [mask_rcnn_inception_resnet_v2_atrous_coco](http://download.tensorflow.org/models/object_detection/mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz) | 771 | 36 | Masks | -| [mask_rcnn_inception_v2_coco](http://download.tensorflow.org/models/object_detection/mask_rcnn_inception_v2_coco_2018_01_28.tar.gz) | 79 | 25 | Masks | -| [mask_rcnn_resnet101_atrous_coco](http://download.tensorflow.org/models/object_detection/mask_rcnn_resnet101_atrous_coco_2018_01_28.tar.gz) | 470 | 33 | Masks | -| [mask_rcnn_resnet50_atrous_coco](http://download.tensorflow.org/models/object_detection/mask_rcnn_resnet50_atrous_coco_2018_01_28.tar.gz) | 343 | 29 | Masks | - - - -## Kitti-trained models {#kitti-models} - -Model name | Speed (ms) | Pascal mAP@0.5 | Outputs ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---: | :-------------: | :-----: -[faster_rcnn_resnet101_kitti](http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet101_kitti_2018_01_28.tar.gz) | 79 | 87 | Boxes - -## Open Images-trained models {#open-images-models} - -Model name | Speed (ms) | Open Images mAP@0.5[^2] | Outputs ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---: | :-------------: | :-----: -[faster_rcnn_inception_resnet_v2_atrous_oid](http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_resnet_v2_atrous_oid_2018_01_28.tar.gz) | 727 | 37 | Boxes -[faster_rcnn_inception_resnet_v2_atrous_lowproposals_oid](http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_resnet_v2_atrous_lowproposals_oid_2018_01_28.tar.gz) | 347 | | Boxes - - -## AVA v2.1 trained models {#ava-models} - -Model name | Speed (ms) | Pascal mAP@0.5 | Outputs ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---: | :-------------: | :-----: -[faster_rcnn_resnet101_ava_v2.1](http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet101_ava_v2.1_2018_04_30.tar.gz) | 93 | 11 | Boxes - - -[^1]: See [MSCOCO evaluation protocol](http://cocodataset.org/#detections-eval). -[^2]: This is PASCAL mAP with a slightly different way of true positives computation: see [Open Images evaluation protocol](evaluation_protocols.md#open-images). - diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/evaluation_protocols.md b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/evaluation_protocols.md deleted file mode 100644 index ec960058b..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/evaluation_protocols.md +++ /dev/null @@ -1,129 +0,0 @@ -# Supported object detection evaluation protocols - -The Tensorflow Object Detection API currently supports three evaluation protocols, -that can be configured in `EvalConfig` by setting `metrics_set` to the -corresponding value. - -## PASCAL VOC 2010 detection metric - -`EvalConfig.metrics_set='pascal_voc_detection_metrics'` - -The commonly used mAP metric for evaluating the quality of object detectors, -computed according to the protocol of the PASCAL VOC Challenge 2010-2012. The -protocol is available -[here](http://host.robots.ox.ac.uk/pascal/VOC/voc2010/devkit_doc_08-May-2010.pdf). - -## Weighted PASCAL VOC detection metric - -`EvalConfig.metrics_set='weighted_pascal_voc_detection_metrics'` - -The weighted PASCAL metric computes the mean average precision as the average -precision when treating all classes as a single class. In comparison, -PASCAL metrics computes the mean average precision as the mean of the -per-class average precisions. - -For example, the test set consists of two classes, "cat" and "dog", and there -are ten times more boxes of "cat" than those of "dog". According to PASCAL VOC -2010 metric, performance on each of the two classes would contribute equally -towards the final mAP value, while for the Weighted PASCAL VOC metric the final -mAP value will be influenced by frequency of each class. - -## PASCAL VOC 2010 instance segmentation metric - -`EvalConfig.metrics_set='pascal_voc_instance_segmentation_metrics'` - -Similar to Pascal VOC 2010 detection metric, but computes the intersection over -union based on the object masks instead of object boxes. - -## Weighted PASCAL VOC instance segmentation metric - -`EvalConfig.metrics_set='weighted_pascal_voc_instance_segmentation_metrics'` - -Similar to the weighted pascal voc 2010 detection metric, but computes the -intersection over union based on the object masks instead of object boxes. - -## Open Images V2 detection metric - -`EvalConfig.metrics_set='open_images_V2_detection_metrics'` - -This metric is defined originally for evaluating detector performance on [Open -Images V2 dataset](https://github.com/openimages/dataset) and is fairly similar -to the PASCAL VOC 2010 metric mentioned above. It computes interpolated average -precision (AP) for each class and averages it among all classes (mAP). - -The difference to the PASCAL VOC 2010 metric is the following: Open Images -annotations contain `group-of` ground-truth boxes (see [Open Images data -description](https://github.com/openimages/dataset#annotations-human-bboxcsv)), -that are treated differently for the purpose of deciding whether detections are -"true positives", "ignored", "false positives". Here we define these three -cases: - -A detection is a "true positive" if there is a non-group-of ground-truth box, -such that: - -* The detection box and the ground-truth box are of the same class, and - intersection-over-union (IoU) between the detection box and the ground-truth - box is greater than the IoU threshold (default value 0.5). \ - Illustration of handling non-group-of boxes: \ - ![alt - groupof_case_eval](img/nongroupof_case_eval.png "illustration of handling non-group-of boxes: yellow box - ground truth bounding box; green box - true positive; red box - false positives.") - - * yellow box - ground-truth box; - * green box - true positive; - * red boxes - false positives. - -* This is the highest scoring detection for this ground truth box that - satisfies the criteria above. - -A detection is "ignored" if it is not a true positive, and there is a `group-of` -ground-truth box such that: - -* The detection box and the ground-truth box are of the same class, and the - area of intersection between the detection box and the ground-truth box - divided by the area of the detection is greater than 0.5. This is intended - to measure whether the detection box is approximately inside the group-of - ground-truth box. \ - Illustration of handling `group-of` boxes: \ - ![alt - groupof_case_eval](img/groupof_case_eval.png "illustration of handling group-of boxes: yellow box - ground truth bounding box; grey boxes - two detections of cars, that are ignored; red box - false positive.") - - * yellow box - ground-truth box; - * grey boxes - two detections on cars, that are ignored; - * red box - false positive. - -A detection is a "false positive" if it is neither a "true positive" nor -"ignored". - -Precision and recall are defined as: - -* Precision = number-of-true-positives/(number-of-true-positives + number-of-false-positives) -* Recall = number-of-true-positives/number-of-non-group-of-boxes - -Note that detections ignored as firing on a `group-of` ground-truth box do not -contribute to the number of true positives. - -The labels in Open Images are organized in a -[hierarchy](https://storage.googleapis.com/openimages/2017_07/bbox_labels_vis/bbox_labels_vis.html). -Ground-truth bounding-boxes are annotated with the most specific class available -in the hierarchy. For example, "car" has two children "limousine" and "van". Any -other kind of car is annotated as "car" (for example, a sedan). Given this -convention, the evaluation software treats all classes independently, ignoring -the hierarchy. To achieve high performance values, object detectors should -output bounding-boxes labelled in the same manner. - -## OID Challenge Object Detection Metric 2018 - -`EvalConfig.metrics_set='oid_challenge_object_detection_metrics'` - -The metric for the OID Challenge Object Detection Metric 2018, Object Detection -track. The description is provided on the [Open Images Challenge -website](https://storage.googleapis.com/openimages/web/challenge.html). - -## OID Challenge Visual Relationship Detection Metric 2018 - -The metric for the OID Challenge Visual Relationship Detection Metric 2018, Visual -Relationship Detection track. The description is provided on the [Open Images -Challenge -website](https://storage.googleapis.com/openimages/web/challenge.html). Note: -this is currently a stand-alone metric, that can be used only through the -`metrics/oid_vrd_challenge_evaluation.py` util. diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/exporting_models.md b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/exporting_models.md deleted file mode 100644 index d4735b978..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/exporting_models.md +++ /dev/null @@ -1,27 +0,0 @@ -# Exporting a trained model for inference - -After your model has been trained, you should export it to a Tensorflow -graph proto. A checkpoint will typically consist of three files: - -* model.ckpt-${CHECKPOINT_NUMBER}.data-00000-of-00001 -* model.ckpt-${CHECKPOINT_NUMBER}.index -* model.ckpt-${CHECKPOINT_NUMBER}.meta - -After you've identified a candidate checkpoint to export, run the following -command from tensorflow/models/research: - -``` bash -# From tensorflow/models/research/ -python object_detection/export_inference_graph.py \ - --input_type image_tensor \ - --pipeline_config_path ${PIPELINE_CONFIG_PATH} \ - --trained_checkpoint_prefix ${TRAIN_PATH} \ - --output_directory ${EXPORT_DIR} -``` - -Afterwards, you should see the directory ${EXPORT_DIR} containing the following: - -* output_inference_graph.pb, the frozen graph format of the exported model -* saved_model/, a directory containing the saved model format of the exported model -* model.ckpt.*, the model checkpoints used for exporting -* checkpoint, a file specifying to restore included checkpoint files diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/faq.md b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/faq.md deleted file mode 100644 index 2f4097f0d..000000000 --- a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/faq.md +++ /dev/null @@ -1,19 +0,0 @@ -# Frequently Asked Questions - -## Q: AttributeError: 'module' object has no attribute 'BackupHandler' -A: This BackupHandler (tf.contrib.slim.tfexample_decoder.BackupHandler) was -introduced in tensorflow 1.5.0 so runing with earlier versions may cause this -issue. It now has been replaced by -object_detection.data_decoders.tf_example_decoder.BackupHandler. Whoever sees -this issue should be able to resolve it by syncing your fork to HEAD. -Same for LookupTensor. - -## Q: AttributeError: 'module' object has no attribute 'LookupTensor' -A: Similar to BackupHandler, syncing your fork to HEAD should make it work. - -## Q: Why can't I get the inference time as reported in model zoo? -A: The inference time reported in model zoo is mean time of testing hundreds of -images with an internal machine. As mentioned in -[Tensorflow detection model zoo](detection_model_zoo.md), this speed depends -highly on one's specific hardware configuration and should be treated more as -relative timing. diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/dogs_detections_output.jpg b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/dogs_detections_output.jpg deleted file mode 100644 index 9e88a7010fa90f5c4a74f6caee78f5c975f77e40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 372894 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
    sjYXQID<)38 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νdgK;AU{OM9%y) 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�V`*B&}JIse0-GP_4pz`4?vD1^D3?m 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 diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/groupof_case_eval.png b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/groupof_case_eval.png deleted file mode 100644 index 5abc9b6984fb5816ca4f2e6f40e38ec6e6ea9cfc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 242500 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 pDvuR0c~Z)CG{$O>U~P2V;SLtQvV0tDj{F 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

    8m^u+ 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�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%0Dx%Y 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 diff --git a/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/kites_with_segment_overlay.png b/research/mlperf_object_detection/Mask_RCNN/object_detection/g3doc/img/kites_with_segment_overlay.png deleted file mode 100644 index a52e57de193e53edbb1a49643e8c77609abdc79d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7165291 zcmV)XK&`)tP)Lo7_9Z3z!kw1y%<9F2nt|NZl?h=@oCLH~+K@7;Z# zQo?^*Yx-A2davtb5&7%!6=RGsw$^H`z4s78O6mE0;`IhJIH*b;2~C$+NWv(cysGwuwk7C3K&g z$Kz3JJ&ptOQ%d{3r4KAf^<2tK&N-!23e&q!dR{E3r&br6^uBFd zAB49+TZ$^fA4~4N_a1X{_YH$|9sGo5C;7M5Qrh%IF?u}D(|x{e8ys0gAbDk#$(cP@ zM=Pbk-oThUe@ju%uJRF)kbFF0`)=Fj%7MvE3@%~5g{hU8oJC~ccM&;`!;ax!tG_Uu zRIIjktDLWV=A3J-;0J&Peqe8_eX8CkszjbXIvASlNBPIW6?=7p{jZ4pem+x5aCywH zwboi6kH_=*Y_0A4j>rWQ>LaL4er;K@*vn9Z`EN2NVF&7ElU|q|PJv(w2P;995TFe6 zD5Zo%alk)VEAGBI?~`R>40~|mDT!a{6F(Q@9U~+yHUy|Wyx(^s7B5)5gV7_gWtQ7%HaTwwFJWmB8HMUYpCJrBCwgJ@MAtRFKAA{zvWH6MccS7vDjl!^Iol*(-SFq^L+=Z| zWf#wFMq!_;IjM5tR)2qesi<*Gyz(YrLTr+OjbN3@hnc#XpT@_@clwk!GP@%CGCeZA z=#F8kH^+oE?z?^}#-yk0%je&eY&qwV#3sfMi;p%V0zYc)F8)jk`WUt*D}w#B)^h%X z8@7&SxP*G@I^D&$X@X9J-D>e@okcv{M*LOvsd5vuA8uC|T$D4z6IR!&9rh`I=JHwR z#~4qxFJaiWRxB~?c9Y4=tG|dBPg#A6P$f&

    >c9o0;s8#f#}V%PVTFI>!!>ORV-| zOEC2v^)Jx7x9Pbk>#tl|DZPW=3FfQkE3T2Ui(5UUs8R= z(H2(qxpGj*ns8e=m)E!hyK?f1rC-;3UxUjZf4tdOS7Pz*qCDC9!K99M%{Tn4aRhnG zd;TY~_-TpN?`^O%$*ont|EY1!{#RjeB_>Y^zF(B{Ui@XW=iIz{t@mmR5E&NE@{`_! z=8$6hmaN}J@&P6XRu8_9Yr^gSBC&k+4L_QYT(M7WKrQm@tA5|e$Bp|Tgi;T8eh~k@ ziQz`Sj~igaM*P70!wk=F=cP9(4nA!c;!S*HcEyO<8}1)*lc+2A-oN&p=*3^>tbcC4 zEQjoVgyMGb?+tsuhgU2=`FIZ^ul`%>8Ql6V`saeDsJ$ViqxTZHcC z1HXR#+O`dsgDSTeBkG`)^d5XZFS)jFm8z7)wm-J39fyeNml>&iYzynfe3 zIk0mjB7cT6r@3zxQwFlUksTa`c^e->wAPN}P;Xk#bvKViU9;lewmsZ?ZMF`xbN2is z-nIEaHdXWgpF34KVILGajf7+% zb~63sIGBqNQX^!$+1nmO1Z-`U!Brg+bu1J0KvtSAYESRx@i$6lN1NRNZrpQh=er zKTLtH00<>BOTLc%An>5Wwwa}!TSP21cY{hwODUEeSKtJ>lj@Gg$Iv=1Bz zgRGygrF{mJ)7h?;jTHvC&9Cw(6&Ta^PFE38O^p-o@j$`67xPMjAtcgmCg%ZHQT2O# zcz8dNu9lV+ArS%AVR5O4yoLR*OkAOJml-G?@@PpLLmqoLU$$Mz5yxNPfn|~Bc=dSe zRD|;&uR0@>dAS7vYeg_1Qn|_R+*b3#j8#7coV76VrhY;#iW3vF zJpZXDql7}}r=4rQ!+mCX+S#9B&L}xtr;~`wpQx71;@D^$COA$);%thGmQrdTD7WLy z)A8g};E6Qgfg82W!?jCJe;%a6c8$!pVmAwM{DjXVY72t#fsO6IY8oo1T9MX+xUnk# z7udzTy7C;&Ox7yj@Or}jy_e*{F3Hv(xBdrbhvDtlZnxKwDyWW)a$x#$e!fG?Uplzm zZmWqntML4q75fz?^!?ei@{|z`bI}52Q_kyUUas8+EyL5FZ}}G{!1Ju;eb|i&&)QNw zoM6XELPNx>!1GGiL9JZ1akjkC>&@@)Z*J#_5{bfrb=cmwDT2e~r;Zi*|?jahY z;)Ki%PQkVWCRcjEGx-SVB8#zIZS_N@-!*Pt+|1h_c^LZ5!$<5-_o;9XV(%ki8XV@v(_;N{A%%4Zdx9QJtTJUl)h^)Aege}S%hSuB4D9)kPhRBB4{L`0l>Vbat1HMhv_U=t zNIn3Xz~MD`Na~g6Ve;101tSpA{{R30|Nqoo+p^mr3o75!1F?{8DcVUH0 zBZzDs6+1YqfC_i9XbPA zv;TwSb>*)~yMbI%VH|iRBHOV`l^!6|b$$R>yql2ogp8%MjJK?cIXXqmCixWJM z_y0JaXi?SBQBd>0oaepM3T%@4q^W|*iGhpA)o0eTC?Om2Lo@Rr{Z1Q%((Kw z9i||`z4ZMv5)D93Rk9w(af6VlH44T`+YSFYjvqfuEW1d&V^->Nj=s}&n@=!ch4S## z|3%EzaYegAES9*FJABpt^sWUDr*@#KIEG0Kv-!e1Vb3G65Cu26!cZc!n*fK*=Rc@{ zcj?aI`F(+X?qCeV-q}Y9bFF_J>6g1mEJ*_MO%qpx1a~LSW(J^2DTUH{P#_f1{ zi%)&QZNdFm&ON^ta4%W?wd`|82>cODxb37P8iptG_#BBBiMHh9Ss5wB&!V2E5OF_l-pR@(>Mzts_ywVf-s?U|9zRbD zkGEyY{=^mV%$=_2X&JLq5-EF{KMCaBgbj>vr-|;i{SjPcKc(fcl-C&%DJ9GqJ?_hC zGs*L7;Pd1l5o>pPZKu=^I5eozfW|inzu7$Qsz1q zwz&R=zR%D1nb)8<*)g`0d~u4qfJozof2Z_5`}{@HcAHP?U{l{F4tRc{{p9W7%Mm%< zcjMF&Pchtv0i4AlY&PL^AVPZK&0RRh9e?e1{Lt6a=q)DBWMI!-c^9quHK9j8ZCuc} z1WOwajsiN3cM0_8jAx$b9ELlWYyX=E;ws{e+Ph_n?~S*}?Dw{x`pZn^j5H7P zAuWEwm1z{5*ifzf$ymQMp7iSD;+!+e&ODKzR$E|2IP~S^4I>tEfnc>D=ddSYxFHxT zrQ)b2r=s-_00960%w0=%VdlIHt=Kg@odMGpro9f)IiNeO=z*-tI}N z$$mFb_JQDaEnV;j!#lU7;F%tD5{~MSVt%Bvjj0Y2u^Nk%9z&$7jT`TT%9@U%4 z!(GOnoI8L)t^1clTw#F_#vGW=&w;(J-T!^|sUtunlfqXCW)(kJzEwb$&`U zn3(?a-awBkLPPB^Vp05)ddKyJyLJTSCP5@)I{~eyziNIy%u2-EEve(~E9+JqZ_7Fq9}h)3jz0|Ev79 zNYc)gl{%h?w~S*OO(+re2uii5J*KDlY!HsL?HSGQX3s*^RebL74J;d$oPQ2j?w!u^ zt9&L8F0Q1RmQlW%W!$hBCU5Js;z!sbiSvRFZZL8fz9$c6DGjcsb2IWA?d5;m7+)xR zaOp&w>7ic&IEABMGz9iE|G|?FI1SD35og@s1wCb?$J1Rcs0yVYMaq#K=Xq#TehRg) z&99TmGooCb{nVv@eRdOut71>cM&@T$6z1(6Cioi79fbU`T@8%<^?I8t_L>fzHGHV5 zBFCTOB71p={Kt)(-T?m42B3{Db{3L!R$IW~X(Zj2Q^|uEZu(U5RMmSP9=2lmoXD?m zfbBo$Hj(eWZ4^=sRoKpW#Bp0U;MoNTDz=-+Fe%U4! zzQa_(&c+0M?l+%JB8k zuSVS(_NE-Q&hk}b-nXuVw|Iw^obZvj@wkF5+ zVHvBj5ookXZv*mDbd!zFeUOws6)8KJ5?ggi&d}en3#hyjxGRSWMS9BqpC#u<4L;4( zF050jk(D2?QMkkO$VW-VwQAhot~bOthX%PzvH`nfX2qjb{`0?)#Ib)DUkpZ$>pc0! zM$D>d*_OD|^+vk5&~&?gww1t_>w0>bVv;Ac*ls_2Kmz5#?v{C@Q1jQ<*XvGsp6QaS zJh&&M^j2lWd^*fDMmYA2cRLkLp^}r*Bxp7*Wfh;Re*MqUk8#_eromozyo&^P7bv!t z_YPQn*sxn$t2LlIw*lyWkNIGp429p0fQzaRc1oV7@%YpYtlms!5`}ptIwlT7lsxP5 zbAhX(teEnn-;WEVJ#6uD`p@{Mai7P1)ADUi4=S&a?M;E7SSnSPjfJ@hIW zPwdF~sG4KF6^ob3ythE#Bp4^^S4{>S6tJ)a?v7eBfT+JP8`^7cdh>s>V>wP8=c z-*4iX!HTL`DH>HctVdPo!D^x$I<{LF? zh&cnF%$B^}`R316p8rXF#j(ZA?uu{_>Vy_rGOAT!Ddc+ne8$C(0m_FR>YbD&p1(Mz z2a+;G^vU$V!zMipbO<(>)whZ~cs_^f^)`W}kgs4%63n~1=2S97zevT9VOpMKW|dMp zW?l5Po9EHgZ+VvJkLv$^xblPs**SAm_(jz4(yrI0v6``2Y2WvK-(%OG9nXh+OwA+uE(y|9oQl9ROw&UJ9oc8Ot9<5vzoHKGlvb3MZN} zXO@$zf(PLtG5|0T-15dlEujjw-#;?PVi|b#cwo38gfLTnm?5UW-2xsZ?;@~wac$YG z6;aLp81{JULGVtN5E3dNE8&pIH8rzQFQbR|2UvR|I&dp4?iZE)sJXo;~$$ z$1VrFsUG3MU~~0Ay%}(5nw6aLus8~F{7l2+pH@!yMfJc~-m~h8XPUiU=3O8Dr+OjT z-!H2mLrC?nx+yF7xd^PE&2uQDy~8O`4nkOYRJ*D1OfazVEvb$pTn^h`c774?;qwrO zgBnGvP}T^@mp+=4i2U)X>>zh!zE@Dad8p@42JS1I*Bhhn_55IQZ(6=>Gc$cYI`ybb z*g_9t`EfFeoXKqTraBIu%pDz4?%68)0c?AEP|L={_2Vet@Y)}5N|BCZX3Ar{I+=Y( zS#qiZg<9n<%H*xrwrvwan;_GQY5{593@cEAT@t$358&}Al!}aAU4`@dP382#pQ8ls zG)d|l!aHA^L4Op19-F}V_E*Crf#?5HpoKa^Ic$O|hD1>oaf72UWuhU~{J|2$z!eb@WLyi;7?H~PqU3N7*y)8FYDz>2Z z?{Y^%5Tv-%>lEQXn6YBpHgCRr^GJB|KZ7EoRsdX&-?AUBe~+U5ZbjSTC!0Kz`H|sh zL8=pctiq^Wv-8M$4DOv@qkiv&?`^h2>`(UE-~PXhe`dxgl$`V9;$Jr!kR9-@=DzkS z3N#vTwhC+KV?P2uAAGBSy?iy$xFAQJ&d}VfzxjVLLuBF%&m;C5jJE&pd5iFT#lDmn zhw_a2Pdt=d@&pc?Pw4h&MPC_IAx1L(XSM8=Ld-Yp^Z0Y597u(GdG_b@V>F)4dw!qN z+o?NF3D;S;WS)3qYWX>bMR%ZX*tR^)4!Nch5Ql*B4|t;f0RRC1|HNI{cHY>La7=(7j;_I^@BSyG^ufYz0=bta{+x~;MYx8#pdf}2`1vaqu z+{AK&yMX&CrL@B>7AnVxgMi^PjC{bY1`=H>C?KpYyD^>O<88FeHe$#8VV!A2WW&9W zJo5T&oIp@gToWoIA+oZD$S);w8+jbVO;iK{zEr+(zn`$wPaKL!->8S*=`b5OLhr&x z!Bn8nrOU`bX`T`$6E}h>Qad$&%@}>$P~q!ur=TzD z$K5vRtgENO^K}V*LOLXL+iyH+U)&T+F3A;EFm=3P(P|++ZQi1kc(n|l`*P(P{iCBP z@T<)GDpYy9W_|m3h}clCb$%{;_7-g{7NV%2J~GIEHFa_p9JNp7pSOcj;h$xeCHytF zNcV!_i=wnc=N-7Kom0TfDHax3k(x5UE0c?!G_fiz}!f9|+(K-!LK{(YuS;bbFZ*Vg{8awbrla6Dgz0l^^si^NmEtUhVj!27qWA z6*Dp!HWc^k+Uft+Q~yHRVS0+fj5@Wn!#ehB78@}UV7G4M>MNQ$dqu?Xl|1zI=~SKT zi;Kq?reWz_Q-0R9x(p?+If@{&8g_DFYbczb!-b|0f!x^2Dta-hcQ2kHu=%?&dNK>J zhki_527~mOE!Z>t4Rg&2{)(rm=HKnluh&cEt-*mJZxFoiLz*;#C&Ly?CohnU?F7{F ztFlW(mL(XztEueUT;z~1pM$ZV`VgjKlKf1W^E?GoKxWAO-#U8@GcHe9BR1yQ+k`gH z-}PTAKg6#wKsFhE9l5im|4qstcuJqgt4Hl4N0fK9*2kR078qujPtNUd*snP4NKAcF zUPycxg12BhZ{_WHJdM*a^qKNt8{_p-it1Ly2)C5ak%VP(68J>?hk6Iwjm0VxOk#FX!8MwebD8?4(i-bB^RxPaX@NUW#h|ur@--y*O!@|GJArf zW8O-lVDDr6gF0=FGfkaPkJOUj5H8FMSp8E*Vn`!EE_zU51C7H0AEZBv zH_Xb5jFkB4hF~0y4lrRB!=KW#*!kvoj@Pv*eGcWP(*gCRKl~jxyMG7_A1b#Sd4v6S z!t%o7c@G%%q5Wj_?}7w>FC+>6?5F%<+@Rl)D$xeben@?H5pS#j&7;h8h@#ElbrO%o za&-+!57=oLS0{%$yJVRTL{d%1e%Vi$#p+{EzRW=UuSF@xN+}?7{u!|id76w1U$66p zFB-$JcFeMS0bupLeOR95C@!9)<05pX>kBT0@;!Wl3C6%viR25KdYNHEK6 zs=XheHFV94p8o&<0RR8gUD1N9APB{p|NrCkKCqoVfuOd{>|LIkh7?f`h-AwN?r>5$ zbx(R5oL`1h4&?Kx_s{KoH!;i&JD!<`{CH{-zalanLxZ)$fE@zNz;f=lF|?V{vr67( zn13e=HxNH$)(c~qTFrb){-D^t?>AmsHxB5q(-C*u$OEXgmi?mta*dBLOy}BwgU*S? zwN`ad7$CTO;J#cTd)Qtk1KHdo26N@wryLY0bcUkd)VFC@ci_2c{Bzr^(_mWajVl0( zv1>I3Q7Fj|4b0_d$>pxii1ZNgo2Fr4L<_vAe8>;BT+Updxhuf^Sm<;jIZc`vF z6b1qo%Q4XnR!A4e-c6=oj3j@Wbk9Z=j_cyWyZ(;(*VwOp-;);$b>gVq=agk7Hq2&i4o#_S`MHXHuQ!(s1f0n)|xrg3Lv>! z1x!PscY>34%?NBRAR%Ama^fvPI1K#4fRJ5|67gXHInj`J>&<=LUum>8%M2zbFBxpG zzwkWyXQCf3zj>s&4V#&bPmrIdeqy$^e1dFL4#vEhr)<7r}GiQ_Oo?7xZ!i^|;;m~-Y zk)(#f`+gVhpe;|mc=;@u^_sZmV5~;tP%n7J{k1RfX2}yj>N9rVj0ZrFL8M3k)+a1! zp|}LQ5DD>&_MDP|M{mF#Q>v>o*UnIoqdN(Lgo&`g6|5Bof$OIE)z)8Mlb@U-95-YuI`~ z#e9{_la83C`OT{dxCNnINc{ppS3ewO(N)8pHUfO3^O8(rQYf!!K-+Hjeh8^LJsuBL z1~?+tH(3{XpjZ(2DftPf`~9AX(1|qVyeieAPY}laTYUJhTpsVxGgJdJ(1!ms@f1(4 zpR6#f|G7w<|JQ^?ooP!?HG_dS=3q%&aSMp7chM)@)C~E9LJ?xCk(&OnA)AJ*gKyg} zW!i?rh_e3#YA>BWEFuJDA zaORybFAJ99ny$c4S-aoAV|N(v{JFNvFM7gd^d&jx>;*&RU#&0?Qz6H?C%cg)a zFE}3psp7_VZ{>YG9GE(Bj@J+VH8O|)k#$nMm;c@q$^uH|=j-bWvK3MQ{aH%e>tDa% z#PtME+Y});Zo+PL1l6OS${iJsm0O^0ljkV?HVD(IoLqN(+WSCaJhSie^4b$HPdl!a z@zfh2z8E%56S~F0l3YK~nW|^S;D)C^x7!W&$cBTJR}~L>a4-7}1 zi^pYIuGecmdbxmAoZU{_Y!S4GjDA?mTObM(~VAY{{3#@UxF-bPIBj}ecGLl| z=i&|TMxH&sD6#e>tVKMV$xmdS9G;k}>$NgLDC?KD7(GmBL~cl)<}i-qy|ZAhmpmK= zw$BmlZlf#Z3503R!#DaOeDAE;i$;_Xe!&#E8* zn6}V-oWJUj`|skXm#X$FBFj?8jot?Rur9VxUzBt9-a(eA@{H}p&j7rg%*2^lc#}?I z?Bd{jLs}02>7^G6+~pJNvUigQJceR0$pNB($Q{>rR_B4?U|m@gdBA?x*lo2dA+>jH1ztk-)q z)=eH&<={#qw(Wr9npXmDQH3AJF?Zr#UX`cXHj&3bkQ(bphCpb0cDk>yp8bP1ri1)| zM{Skx@?5Wzhv&U7>KOWXH1zgQdPxhQIjFVs&U0-a*rZpq9oauDiS3IIn$v>amR*7E zee0J^()>8ee(+QEDlU+q95zY)hCUi+Q1mMl@4?8Hy?QD(-Xp!C0cE>fE-LCxXTqfg zoBM=d7)%bs;Q0p+PX^;xkm8DJ*2|Ij>-AIK^g!>&b%{dt0G!(6hEbT(Krq<$eg6Oe z0RR7_U0rkQC=3N0JK4W`cV>Tjrw%sU2Zd81={U_SPmb$?5c-yY{NJB{-+VErrb>Ac z5J;!LHlDt?ON&k^?7;W8+b!oTKTQHdiy`u!fJeySJmZ2SMmH!)fkqrr#h;z%Niol| ztRbANt?SQO<6ytuyWqs&E$4i+cxOyWSs$`hMxiY=yfQO@7@pq;pr>9)0{d2$9u-V4 z>rH=&XYsW>{al>nO6HZ|@L)mvNGN(d_w&#b#5CbJ4f1}$!|u#u1b{@icAJgF2e&tV z(l$0W82HP)gBC;7apjPi*QYw~R$@Lyv-07#NPS@&$MLS~x-84r*B3C51|PN7g#Pnf z0Cyp|@+h{;YX4kQH$obC(3|Oh-*+G|sieaFerKrAUK2WG9|KVy9wR^HC+ay2A2E6` z3u=b*?}fB5*))7V;LXc{P;Ot#fv}(OJ)^^Vo?w=wrGzT*(!tY8uGV7XvUcG>dbxq0 zO+kfq4CS67Y#s0o^(k|JKXqvHY$AC1hHhn06rN_4+5xLd&`o}(S@>)C`@Bh7BYzoJ zxatY!Iq8@td!vNkv-vXo!1s_T;F*2T2!_EawwiQ^+bY*}g#t2ysHw`8#MLVr)3c0j zODWIi^Ei%WS?>3{nC!Jy5dxl`^_w))tyymQ<|KGXqX5+Oe-6I3`j_tj4(ZAem6v-4 zp4MVVWm(?vsWx0MR)_tGy=QdA?5FFWgrTqA`+4XI9NZSose_hwr$^c@dCDOlbK#bSDT6oiQSb3aeBM4 z&jsADi;@c98oma2Z7!gBtAPGz6L|vZ(T7*HZCePBY#mI)(G&K^wk0o@7@wB;Mi-?Q zNMX~UaLY%J$8j9Evv@}(zZYtIn;P%oY6ebx_54q#iLVtPSTv&;xKp+2#j z=~>hIICu;M_KHpnIyC)2-Wq<{hl!#ggz@J40aU=Vp?}jZuIvokUTYaivh)kR!1Rb9 zM7v;;F!<+w_wuuky|TU^RBra(#m@Bpi1yc#GMgv)KKo&CCeIgwH@03#AsKk`IIsXc_gCJbz;jP(pTlvv0Y-DZ z^z(Q;k|GAYXRRzLw4-v1Hzo;@czJ?&h10+BxJF#OwSQ=QKpp-9D$QzxifL?JbX~88 zpY?O0@51+)#LtCayxf2uH}X720&k{}E)CMcdi|1~xxA%uelH(7ub*IaekXDj5lirk zIXU>Z{7CbUF~9e56Jwc!%oq8N5D(06dMke{oLr8Da+@7Za~xNPymptjl0ziC{q{U) z0bD#Uq92)_0v$6w;=vE!f^Mzd#p7%tKeBNbVsEc2i^Ih8dXo4~e4Sr`Q&7!=um(quE$j1CTBHz+r0dYLV%|~9?+e-?uQ~zw?b$%hMDxiz}LP)n1 zKSa`VITOB4r^>?u+I)GEak#$BzrKhINjyqho(TT?b{nZ=$)rdb&*SmH!KR+C!}oPK zYkt<@_nFYGoGn|%70UkXOaFaX=k_H063V5VGmD3_cvnY2UTGE_yyg30ej=?y3%}<0 zXZ*|PL^Hm&BA7i)?G^%Oj_OtVsAKW^u8h1Avu7Cmrq%P51gIc9PewL-|F7Ll>o5+Ve@*3CjfypbR0L-}lBt#fI`X@ekKA*zx zlDrn4(nhSI2OuGnIEm#u=4i0^*oW)R{OgPSNE=m}62lbbD0xQtFC7?Rd1utc8G5*= z;}sHmKA)u&NfYn;ej|Ab*8Tzj0RR8oUCEZ?APj^)%>RFG4(>1qh3c||gdleM&D5b^ z2V)S6Ru*TiE1u$N4ESeYf52!?)_5Vf(%8_)P>Dfv9ESuTO4zh=mXAZgoI)qWuM8_~ zt<|nwz%U>s`n0_&%Aq5l$3Z}bvd z$=H~JM>Sk{n9jN(d*<0K&N=NsjJ1sKS3fCUy4n+mQ+TR$0XJR6v0!h3ZPU12EL9ub z`-@hCr-GtTZ|evG5DHV#r|Jb?Pm7H+V1}&n7uSx)KK%f6Oi!Kx*)l*%DW%e)ixQ-_ zVpt11oFJGLhn0JlJ!5@}jUY&TUp_O`7aN2gv9nPx_ysBam!DejIP!p^Azt$pR`Yvc z)06*tQ)smoHEB_Zif(|F_^k|9<%9U!wL4u?e#eFz)==IMUpN&#JLjtM1Bo=`Q{0Gy zbQS3Qzroh2H#Fc!W=v)!me0@g5g^vuo}5%uj(KE5k5qCj1Ab>3xF0--vxkZ>XM&qT zga8#$+SB`%<{_U}x`7xed;K}gS$kZ#oK;mZVjur=R1yBm27lRp%ZLv9RNZVLd6L(A zWbk-A5KNR9mTV~WOkb={)w8KKw7XjOO7K(Z$|2y+$j`hEdIuP579&C}Z13W0WX^z; zRr)hIJwB4fo=Uq>Ih=PNJpT0-swG0Iq;6}=pJ*2>DPm=#?kREjDW&r`cd{*0NlVx{ zt9G52|4%<4#F4vLi3EBCT?9U53tYW5ET@_e=CuA%1v_07^AKvkN9EZ07 zMMc0+8n4%|*7i4!yo@dg>eo_nb2Zc@@Z`oS>;YyeZS{s%wZK_Mx|?zLY?KyRdA?n5 z?U97N*F9DHee{ujZ`-+K zT|RnAgNJU{-(MI3rnIi7!wpUM7VC-F@?XJ|hsfgWZD^E}hWb$N2w zD?ge3&*AHQ6c$S-$=7d^Z};^r&a|VVjH0pRj2gxnR5pcnjur2< z2y6PKM~OXI>dB40x#V3?<*h$T|KQp(eCqs32b&A21MeWsklI?SHgpniEdlO4Ctf%S z1N}AB0$0@wWGtc&n2xJ@Tm?~42%6&=TKp7lk?jF&4KEamc{3==uov!#On@t@%n9&2 z2p-a7n}02~?TxFJEY%{2BnGyk-T0o|-?%Ly1%Ckm0RR8oUE7i)Aqd4zP0jy*Zz{SE z#xq9{TJ6qm&GL}yB(@^TMMOLgFjXcXlT}Se#RfJvRvRaR$D!DD1*{8C^N%uuDB`PzWd<+UOqfq zMnl|5Q4>CWe}CsNQ^+J_%CdtUg}~!{w5#7z%in-Z)t0Ffos3ifX~xVl!!JYmY2~3h z*aRMl9fj(_B8&$c=ujcZ0Idq22Dp3p#CY0v6`iXtOrtuth2APC5r;8?7*B26!;^dU z1RDV3>*-U-9DYkKZ+HWc870#(V&(1Ppc$l9P($Ml0Sg~4ll#mWm|DTc;jp~dFHa6I zPx0rBY@7rp4u0VPcWE4*TRP_$XNFbzz#&i&fE-`QO&7B=hk8Ory)<_~(W^gxYbX_O z0k0~iCrTC*R>IW&zd`9KC5I~*O}TwOiDA2SZ7%-o1rJVP|PY%;S<-%_V9MJ zoP<|=#$8ajA)^Ld`SDFktAGG{F~P^f^4Na`s<69;NFN zDZQVOOYLP z`u(|k74`5dk3#M<>M2;2+x8qzeRw{fN}UNg2U717-#DG_yYmuKAaLKx z8C1f*pY{%D?BVapvF-JKy6o2-0`nJ4rs7+1-nc`X3-wxjefOeCIN6=0@_Z8xOQ)HJ zhD~#$rEQFfkq zI~Y7ah2YgeZ3u8@v`cTzUI$NZtPYvQC&thl7p9m}Mgjga_{8m=;>oXU&_@{?OzmF* zo?KP)ze3QjyX3=zZp?-@;hUO11fD7n^sL&dlMDTY>cm*o8vvBDNG7CX#vWMJj~|6o z7rnBt0y&V3XGw`r)!(5#$rg*So29(}wGAzSHziQtq&)mI_;{{$+}r2!%JY2YhgJLE zv!hO5RP^`!NFE(lMVOu z`GNhVmLG?5W?28}@4pm|b~j+6==PlRslQ0kQ;Fy+M(;=U8t+G7!Uy_D9Q|?^c=PtI z{fJdK-7l+Oe};aml_3KT0R=Lpxx{XQQZA*Bd$H`y__HROhojv@m&h%N3qQrk2WA9? zkKDm8ft=?YJqb6vlKNx6SpXL8$?{kD#on-YuQXsYhDVCcj0*S4d7k+^7XM0>cy#c9 z2L+yg#Pun;TKc7pY7XU5d1~=gd=Fcii;bQHWk&%4U@pdA%^@PSo9u>CB8Wq(WW@NZ zaM9k_*pd^o>}4EaC*bmdA;0q_w~8h~i_%Y_4Z8gS00960v|U?rq%aJWXDfUE3-7QW z4xM)EVZ;!9qzGeVS&x=%45S;}*%E8iE$8Xi0JzyL*dD)883>61J}381z^AwYCPCtn{S%azM0-2%-~)1IE*x-qft{2rfJF-y_ap(ggLXX6mF|1o zyn5gLS9i=C?F^dpJmbE(^_PsmM+9Tg7c96~UZjq6XajF1Z$Y1`B{_|C7J6Nt5lt_P zp$%8adO6Ky){qbS;^SKWOh4hj9-xZo_U7;vgWysNe*L}nQ5F`NJlXk-GQ2&aLUTKc zjDI12Mu=9)eYVE3Bo13O$v)3H(dSbiWm}hPk>6O!uql!Nx4m5ob%h5KZmhI|k8hv3 zVqsqv0Drf3ZxQRqXst)ADT#m&3f$}B18-yj_Hr+rg0TZ0XWr*0DRIWsNmJvV&r=x=Z~azae_rxBUm7hD;c*gOiz8)tVr4zg zl83v~xINpNQ88@q-*`9aFTH7iUAoX`E3QMe@UpZ}lFNIGCHDDsu zMG^1U{rQUgp`5nPt;VAZDA;KGeV@P#Ux3Zzlqle!^A?m*Zy}f6&v%!#_teF)BbwzM zXUQQBDN=>D3+pIP@<<5|Qg2xoR(u>`G5!13h7Rsf8o$@7Xpb!yDT|ka6~N6Hn)?0v zE(-idr)++E}-GX+v3t2a? zGZzmGUBW=HiTVl$J1 z|L;*I56<&~=W!gb^Z7&E#~EckFY;&JwH+o$gfYCIY&fJ+?|28PbBQ|$zP!J%m$`R6?|53mC;~}KXp7_Cx1W4o_oDq zL0!C>`T=ee;Kc3!{fq7U_4Nh#g(LBJ;hF5H){kq=cfX9!UCQdKx_#kqZoJ8c-F0>G zN84vdby~bQuC4qskk2XYH*5cBzc=b+kd(@5uX6sL&5N^sz5cm&1?Pg#jXKa@a>MR< zzx(=)4=#2+@)ZWw&o&;ZyC>`Cust`q^p@JU$%pH6u1o9owr(f$ z>wB4*aPV5cR50jqj+Xpm3@l|p2Hx;$5pJ*~TzGhWX8mFwA$a>I$C*OUKKIpL$C4M# ztTaT6knw$0{0Qaw>zhP-8Ffb|lS-VF`(o(&Dcs9ws|O+Y?YzGU$B_LMMgcpQ2&Mz$ zI7_(i_j~T)zqqcK0%eNu2ct6&+q8x4yfR_i#$9Qktm;Vm{0RR8wUE7x1APfZ8`TzfI zQo9d?$si#a2qb&jdD!Eyz6cN_A#N8txNDb1%<&aJg_;6|3H)rATNo9qj9~D1^ypGl zR<*gD8_U=eexgCPw3f!Ngc3vj>R^f@2;2QsJPT)0FA{yRU)J(7Jc`n@9Z`OCK z>AaFpq#yYN_EdCO|5SaCP-BszZG-serIJ{s^eYxitVA|7KcxB<0f^LViscMTKfe}Y z9=8Tp!uVD1=X6#E*h@AQ(H;wl6pFo!{____`B>H(1}!}D&b8=(u$zZx zPm0%tDnCqeX;5Ei6n^NYm$!vMymSjiF;(26mvhwc8%xBBC~h#6du=Xrj1FmoIh zuZB`{@ZZ(tkMSTJ{r8!EXm8wjHMk4RDUUz(cJ0gAYaiFaj=PS;RYbc3to&+!Qt-@? zv2W7aYKzS-9I2N#FkXY(<~B)3o~k}u@3H#Vy>WZI zXNsSr{b&Dv-QN)kMuq=c_b4u^JZ!z+PygSrn%~yhH4FhKg->d;@4IiO*723Cx8H%) z^k!vTaBmA02h~lpf((&PNETvmd6OE@#Wpm-ox7PKZ>X9E3xdH*pqdpe#p2r(H|E}P z`YH7MMS6y8TI^?vtElg{7o7Ml?9?nc_G@W;MnnwoMNwjn?c#k{<={XYO-n zv*zbm&?hZaGk#g=mVY}}{-5J-R2zkE=Il@6257sJg-AQ)GiUb7`4<2H|NqQg*>dC{ z3q@fJ|yv4=Klkh0xK$T+U8#_gz5ziUJX^w3&-=9aPPuL*>jUroCud zt5ae?V;RB>loLH{|9Dg5LI z84sTUu9x)~{{FgCm)*p*pYkbbe6cmlm_SPOtmH}LRD43bH37m_P)!JFMW0G4(-z_A!1rw*&)yLwJU9@G;5^@nI#dRer~>9$T2LfkE6i z7oI%)-WLyAc*Kui^T$B=+SJ0j3M*E62wSn+UuusBCOe_4Ha@ZUbAnXZQE*+?=jW&F z_tMt@*p$YIVY|%GSV(z{EBO_lb@K3HZiZgr%cy=-5-v$SfHz zvxY`5Aez)N^iALBq*~* z2ga1NC&txzSIMofgz-4G#iT??veF+2OHVyd6f|s^Hbm57N0}kwCI9fgiacd6=|+pDBbazGwi zLS%T!XIH8=j~J9Oj!|X}!&MajcR^yV2SuC{*>B-gV1gB8JmA*osEb0LU&jD7k5|`p z7s{^w@g?>fMz97L@nxLt9&$%Z?`uDpk89Om+LmA8$)?@UmI@n0Wh5!oMkBoOUgZ)> zPCn}j{gB|C_s9xdz9+BHWPMkvs)ncjTRd}YSVC?FR?8f>Nwy=r zOSq&N0TWtke@;p&gn*1A$)jgtvu_SX#!+ zyQ_TW%%&g_`S|#d{&|W_r?KRb0!tY(AggwvJ%|2ygHiw2vwSW-K&bd;8w+%k?b#CX z#x>NQ3`!gNHkvJK+U<6`-EK(O$$Bm67ppvc3hrEr_yYsUKh*~bWo|pEc;n*gHR~7t zp640qMH%-o=gOG3C%>=gG)LRGH_!0|pSO}7KIvn`o+zdUT-;L*x|CEm5nG18wu{s}zDW6J%l z6DQ0lpesRGq%uj@F`@P2^$EN0+IRI6*Wfu|Q^Bu`oHO{K<~3%jc1hts3u^wN z>Ti?J(o^TMO}vC4c+Kr>+9=_aS8t$`B9OcMt1fdXI^*p2sl>hBgT!OdzB*nJ%S-_8?w>7+P~G`Zoniyi07kj z=rwke%XrvM)E@O+91Kv@dt)g6V=P*+qTr4%8kBKUpW>LECs`#m#K-oSgAAR`D&VH!5FA$eujgTK<`@d) z*m)1x9rqZu6H$p2^_ zX?5NpX{V6v$p|2?)6;p3Nq$E0bu|AkqZU?(M-c$)E6wz;m+kaAc6f-oxQeRSX(vv7gn)Et9HEYFe$VLwT>Tb@J2*_jJE{v zQLW)U`x3#+df0k=|lrkL(L%}_(-z14MH*L9ue-C-Kz2#>28Hq3!V=-K$!hASK1^Jx>JS z0H-;|80UFrBB35l8}LRgWzW?kBBTQ|`_>skxb~h>}DKr&=Jy$ku*-=7P1|QuKLi|T1HDnKm4ff*4 zL?43SC@w8i^2rFTj3psMN!B!~8UlaKq`v(FIY3ubC?`hXW-XZjEXyJ?{n#$rZ zdkxvg$(V2EDQt`z@Avyx))W_c^m~59#Icaed&@SKJ$~{OmD`zaHx1f3GT|&G7J=-) z-Xn|;gY*`0qnVX^ENaDVZi;_kVVVJfVL^zW1$lYJ$P10Hn;M{+x({<;UJySxU2}eh z5Y87aVgO(wgeW+>EZ>A2oEqBgc3VjUJyO%SrBL5%1ViA!taTpb71pbXvaUUQS3Y~| zA!%Id^~=Fby10M5csSM5H)_gXd1X(b2D0j53UE{BISWV&I9;J`NTYKbM^;9wJDgJ9<;!2f+R;Z z(sr~jKoDq%xq0!q(SOS*+~7~ZV~MW=MhZ8dW$Rz9jlo}M=x$9;>|^@#j%yQ`ym`d3 zEC}0#_LVOsMrc0>z^Es{2c9j@7H?>tG&!OWvM-NAg?Thb$nv#WZ-2qA|MN~(wfuqv z`v~Z^$8w#jShMR7(=-LKaf=G5m4TlAXfxe#F}#c-!;_;|KlM|6@xK>GRo^l#^Ry21 zoKY}Sy!pteb+%Cko}DKKTJJLa@y6?||96m-ji0NdNZ(4yh%stdl+}kU4zpW4((nIX zbW38Q^tG_vlU;c0*YIsPx6K7Bn5Z6nefX$7z5Uk`+(!ul5fS_XBT}JXh9mF?;sYBE z{X8Er)0}wt4o5=|wrsGfwyx{r@sJ`uoHQBu5%5j_^uENXp*2RW7R~7&#!sy+{w~xK z;>)ieDZJ0cQN$<%^!!&=f>*%4=Uxp-SC>{l{-)DGU<>kFASs@8@)PsF+;Z4fU6y6x zJgXSv!2Q|h^9kig&Rf{;FEE~{e*|J6X#^kWhGt$Nvh#{p&Xa6vCpE)#9T+lYvt@2q z=lgxrF_b?500960tX;Uc8g1sSJ* z{`y<=+c^NJEX%rWTPfx7c;uY-eRu7$?|W`{g_>C@#re{2s-6pLAU86OuJ;=4L>-~P;wy(MWl+yjSf>s+u}K|ZtptX zmSyqibNIX;1kS~#OLIAC%>T=kq4CA%B0;bm#|fh=1*@4nIg zjKZ0r9WEm8?1}UhkWM*ME1ykrmWW9Ze|EgSm5rsI%dOKk-?ffwn zuyC8Lwp)-hT{t@P=j?c(l>QYR*otrEH{9RZ>cgT2dCB6y!-PBnPKW0e|J;Zm;Iyi5 za4&sw62`q6SbPdSwQU=lTbS6|0<5XG4;3GBVh~ptmz+1CWa=cHBW^b7ZcE>JSzTg_`~gPV5ojf+ix>0@b)q84WGhF5}f0< zeT<(f{_yM*8rT?Mrye+VBTI()d|6(4wvWfIjAp2-gh7T?@F{Z6 z_xs&F&3)ftAI^F|#FMxCHSY`NR$Eqmt|?%oaZGBZk0>DpT4={_7LY0eon_8N2P=wh(9Xoyk-FEdEdu<6n1i+sDYp7{ZDci z+sQ@r53(>GT6?kKq>STAe)|sF6})8;7sA2;DIWehN*OG0uOnVM@?lEu%dhKNO7UZ$ z$K&z!^%c@V39`cHY$fyy)cK(Do0R-QuR$aWC=$~-?k5Ys0P@aAn{zJZ07CMKhT;>} zr(BWt_~zvYW@ z6(x779Tvh62QKA^D09U?%O!@M);;fge;n zXL*PJLs2-U^kAy7Jzq+!udASg;x~yW((i~L&pF27L)!zuXZB}d8L*z>FIU&zpSs`G zg#wo^9_7hn2|hGln}_><62A)9s~7|4EWi{0x$j%pj}nV-;m#X27@vL7 z1qId-{Mkx(PO*KJQgY`v#DS;a2UQdutOXbgeD(2Z{e$Bqx^?B%}ezd-e zOQ!Qa*2rv@uzz%-m{NF7beeZJ+X}h`6_0ui*1TonH$( z$MbJlFL*m%{5Fbjmr@>&M;Q0MnxCNJ!^1@nuO%!?I3Jadl*r86_nj4SitVm9c$kKG zPISI=!k_;G00960>|INi+#n2;9WVO+$L$4VLAz22Nq|jf{PLnzj|YQ5r4IAcMbf#XGuKC=vt>L|)TuSJ|Q> z;7;Kk^ZXWgR=qGOaKIj)rhS+tZ>(D8W14L}D32JCt>RSW0bv0hZ3R(FKq{h;Qv~Ip zR66$)lwJf0U_Q7aw4cdCSC_FtBzS&AXmEh@3*!UX;dLN(3M$DDaK*{fm=C=;6MQnY z&KlNOEp6Iaw3^WTnJsli*2 z^2S-Uf^kc=`pZ>)nO!*W{1i4mf|)|UXaXr`G>Fw_kDtJwDhD*eC!R=sFD$%y7mb6o zof84Z`KRxWeaj?e=0U|{{6rj7V18Fd9_v#9!&AM6a3Rfj_p|y9Ju>4=4~Klf)#PE2 z7TU2pbU9v9Hixy|EdPGL0mTv?>;oH}xw*K%W`Uq<#XjuyjiIt`{-rcX{b-;6+cfU% z{B^J@u_3*oOLbb8^8_1Bxbpcq&RH$!>f>e2`dRYE|38^DDCM?H5QksmM9nEUtc8zm z+350*y!p%1e3Kafk3@ay zNzmUV`jzUfJe;F3^+L@%&qORPjdp1cx$0h~p4vmyMc zyw7qwKRd7V2piORN5XL&@A`{6ipJYwK4C(o9&OY%GX7J@|DKNUjB+G+4x+NB1>TCK z%l1=z`z)5L4R{C&t9Y0d0j)pH2|kc!{ie6hjCCGg=)xx#+wXLE7ZW)B7)B)SjUH6&Ns<$fibEJ@bjsNiG;UV_dew>x6irsbT|PoE(?3)&hn0gD4iHkdXF$XHp zmMubPKxDrJNAICLD8W0e{WF9zkYYL3)gwae#Fo!0e?HC~Ym_0&BynSd7I7!zBIZv} zjyHRDCV$oAS&8zw&3s$x1V!Ezb&P4wY$pEHaL4!jb+S>3RygTQ(G+9)4(*MD_L$+D z!-iYAiXKpebsy(`<7d5qPOqO8+u-7Fo9{H~DEI1}2Qw9q;DdIG5^DHi)+58f6kCzB z@=7M;lDAHQK828E^}2*E593TEpw{cjw_*(1ayljyGd%mV%{gSoE|djldER14J`_4C zq4ID|4+u_1QkI5o3+@l~1&X~2Zw0t7$uVh%c-WsY%AB3=0pqUhF7H)Lb}~E`K*_yf zVf$bgoX|2H^bN3tQHO&`ym zsV6HY<0mQS7MrEraq|tV0{UUGC@#H1gUA1@*-=X(|CJI-=qRO6@1n0W zJQni&X4|<9if=&=FRaQLbIcFMla!~S)mHXS^}Mm6Ucw{S?R0ojzSRTjB7nDkc|&f= z2GH9xP3y{4ue~;Ncu&vfa}P6?V_-HrFW4~-A<1(*5mt#|EZNEL0XJNIP{&`d)%?@{ zFo!&O$fG8_ZrzoWubEC>BkqKO$78YH*l#lrK4Vry4xAS5pX|CcUZn-!l%DG#ep_l? zF>(1N`MC-^z8L)(lB72&wg>TcC^5AsKkJ1Wg&Ii5{7~!S9cOtSd3sq|4USs8?-XAl zD8CqLogyQ>>G_#!9D=={QeQ6w-^HXA6enT*gc*D|W5JShPB+Cf+y$Nv+)D@#Q7S{( z8zdq+?xp~l{Pv7sqld1X50)yd=Ad(j?$R>1K4pGjuCU)kzQ->526%Efus4)YeU6L6 zY`kp*Px-!^*Z8s16%LV z-ky{vGk)nw%oxDisNeMvmVi-a{{WAg7tat79}`fFKc|qh5kGN%dUVbJ>v7czZzuk{ z5cvHrTGTW3T04QaU{=-?i)(bXihD#cZ*)C7&GQfM#T|*UMuzc4^9ogkOGzepS(sKmP#$0RR8gUE6ZyC=3K=lK=nS-4inp#7d)9 z3vfJBHF`)nK3E7LwZz5dmny-{;}Gbu01*~{Qv99avgqvjEJK0B8oRBvIAN-lri#8k zo98z=SJ*AFP7UN4Y7tWgO8`yNv^z6B5J|-u_WQa9m%8 zwu77t50UhDL1Aaz+nA-~ae=VHWU&*YKk!Jsi9D{-dTYRZ97mruKCUAR zT5J8Sn6P|kCkA(Jn95Ap5f+I76Zu$2m?R2MTq?t>%Z{N^X^v)$54&A6jmv!T2q|uT zAn|&=oJyaq-Nns>|Dt~E-)`h~^Mtn{6F%nYVeKp3>KwsvBQMW!O_g%BL15r z^tiyXv9b;+iY*E z`>Bm1UMu4gCngsz4F}%e-{0Qex|YuCEw#_jPj_<57P$l%jpSQAg>Rz0s5f&2yDnrN zXxLNb6oLh27?!V)dv~u)Hn^K+(EBXn*!?_Su>0igTH%A-6onfKv#MuySjNs>mlN-= z=UpEkA11&Fp9xvnILo+~$Z1;2^?ASvawf)&epKY}0sSJp|EKA%RpcnlE~Yri9Mpnb zGH-+Ns9c8e|9I4Lxy~|D^5^)&c}3XLgumN}U$0YHcjM+$rmOUy*UPQmwKwV4TU>7N zPw`FhVf>VQh~d{G>P7vLe=bZJ+vVa~*c>H)9smQaMS!b@;RS7M3mNlVyx)y?>2rGWl1q_9UHqI)b#`8SOux2+IoEF%)gYby( zUZD3AKD+H@Te=ryZNe5mRe-C>|*6ase5@9EDij&P}hK=7Yo%mN>Y*ARG*~zT-YVo=?+fU>vitwTsz#ywI!#-pH!ap`H)>a+1=p2 z(%!c4?)R?VEY>twmvOygHs4^?uZ;T{@^zfBEhWNvOf&FtH*_+|Z{$B=JbfyTE8@JD zf30GjD0xuvPwrdaF~d5J#mYF3!Kp&k8{An=4&~hHbz%kPOt7QP#*+QU++R8L<@$GU zfl13E)+Ox?MXEI6@RJw4*6s5*00030|Lk2|lcXRFL~H;555Ain?jdJa+aVDcX3MGC zeo_k&L&z5a!evjg!h`z*ZN+n2xx$<(Z+S3-iX0K<5L2e9gM9(q$_47j@~^ck>LLg| z3w6>^J)Q;aNtAGdj8#zh>+5UVHrp{5y#PJ&e13B(`G(B$=P5%4^t{Y}#`5JJI&Ur{ z%Ekvb_~NVMkd%VQpTEN4UZwS5J4c1K6+xnRVATr6wTQ;M2ad3`TjcqzB6X$QL2v?A zAh7|oT{uo_(3H<}x_JnELMTfx$QdiJAHa*ypnU5Q8m4EJEV4+dWoa++gx_kCO9bp? zBIBD7(V>%!z-arU@|O6Bue0ybEI+rBRp$FAm{|;E)PTL`q3Mu@nAc-qrQ@yYo^dBO zJdYg#pT~Y_b~{=RTkL$x1Efh?m2WPfX}7l2N~R$zt<95q_;a|pF+eXYb~~vFzC5W;n`Schr6z5kJi7yNGY0{ds(eF>J`=4_uNpj@MsOzZFgvCfSb2 z_T$?T$CqO|Kqf%*)lg{jVKhSSa9D&RGTJYyr;6fqpyr-PnTp zmq;H)Ck#h^{imQF6P<|Cu(P=lN-7UWHWvC!@YEI)Q{{D%ai6fTHD%DNJdDKAd=Kz7ft!R1vAc(e2esQWDooA z-g6%Ia}mXv5z-X;M|vS*tH^J%7r8g>3F5%0|G!vX_|J>rGkNMc&!ow#K7J@;%1aoA zoOId~lq)ScpU3A%(eIzKy!D^Ek6m;(L~=OKYr-uT;|}5pDPPHt=`Zm7kX6tFVX)5e z(uAkR4OtW$yw=$*Xbs>BR?5k!TqRFN6U}q{ygZTk!*Z`yeuo1ZFIswdG5M~S^BA^b z5`TX`+yu9~!d?gFx>P=rP;m>~n00960++EFjoG=U&Te9!}x=C8xgM&IAX#^&0 z4%HzaON=ZFX(Su}6g#-{04sU^HZH8eo4ve`rwIPZ1SS%iFeO4y{|D;PpWU`bb@hv1 z;}Jqo{ty0ihO-6~lbA17u%kS|V#?>_+zZx*DA`~uh_8Wc*y*zk1Mv-Chik(>x3_Z> zFPz-?>H*Ujs!8)C)nUC+35A4yfv+zr*3AYVAxrj>QAo#v*4p#=bmhA~TWjn3oN5>L zLfeTIb?T^eHHYcd6SWm7e^;*_VZ_V(2fVxFLEOOWPWMhpIU`TMCcB;D<3qRT+C}>4 z_J$+=sPGNWcybA&JIu<76(OrFtc|875T0OQrszYiZ6oFo)p#56VV0B?VO*%u<{B06 zeSw*dz9D5D-_KJFC7u853S-m>Ui2KxW8WdHQLI5rM)7JU2DlM9q@>~qS`=Q)+9$>u zj7Ra=gJ>e8qHsyAP})FElAlsB1bIwI?8qMYepcp!tENeUY5T16glJSsq_?-X4z`ZE zoqAq@=~;v|;!gsfiL(}Pl~6Qoozlage_h@(JuCb1=!3P~7@B43tK*afGj98iBY}sM zlaeC5PmpD0|0O02{pb7p`?{_@OJDZwd)IaS`1nvF)uKiLyvAWUlfX9 zujNenv@GvZ+&(`)9VEMv+ipLqUWI$LwCD2#17xth=k=YF6G#%jpjVdOe>MGNT}Y^5 z@AVX+Ax<=m`3X9piVHaI5u+YzqaM32@F&eHn##BYf3nyCQf8>|({~WlCRFqHeZ)Ja9@reay@$hF{)kEiD zbrCsj>|{|x=mVi0_0tvM65qvV%fSal@(VwMk)(a>r-vQD?-4B`Pu?`1U#sYvY?eVi z#iQa`x?c2-aTjDu@z8x7WqUjxe*mcIZ%P}iphi$4lRE<)v+W|mu9?;bXUrOIZx4BO z^t*Up(DWc9!)f6!=DnQEM{Q%mo}cI7teh z{l9JuUM$5o({ULK^b73b#fw|$)p1kXMm2%#u6oJATWiX%JG2u#w!NPo@9Vgb%hMM` zd9irmE0+7$v@nCs^%4^lOTE9wO?UHMtt!?6g8= z{RK}t?SwNA(T{B0b{1b~A)Cgfd>qxEB2?MJj=f8{+@cUEji;~nBa|G+{jfk9TZyja z8!=Bn8^*W^2^f#-KE~ZJ>q=wHbrVXfn+DHmM7#7Vq2&SkQ zNwpW_9ewj^GkMn`owU!t00030|Lk4Ma^xTk1WzXa|GTNg!yXuS8i|&{_H1^mqC?6_ zY%D)Iduv+#{4C8|GuLs#-1J0=Zvv&X27FYA}@dGEge% zBGj@h2<*6zgK}a*@*ESKOv-ImuytM6b>$3psqvr1%&GBIERA!@HtgwZ2%_RgVw?7y zowg*|Sk3yL4Oc1>K zSpUM|hk2^d3v;3&y6V-ab26sHm z$8v5PZu^1!lmu~OnTbE|_d9SE>j#Iu^1Q_Hp%>M^uhsHL4I9Vp-X0D}*KU1WUG;f;>wob~>FLeb=xo}PHzAEwt+X+Q z_nlc8v|BZP`9X?_CAY`JM(*beRbTGGMD2gz%ZH^D&Tm~=+l+tV7nnA|dxKrhQ=0JO z%mT*>xlp>*K?`)KZJ;z?;7JMMH~2V?PY3*~gu#lh4Mn0Uu38V89ak!;yYqQF%hF~( zR{b*AUyOe3v3a;=0W-!tm?y`5P{3SVB7P}+7tM+oFPwyhR|p$zI;307M~stCd!RVV zceLkazLQH<>lD8d3sBnNm1;XV&%CYQvAc1}h8L1J60YY5zEfQ=wy62ubo;k5_ZJcd zZKc1WSKP*s61OV|Nrb=U323g3>1XA5B>lDwUY_v9#n7F0%35RY3J_r z|a?3%$*D93k_G; z3zz9jUolJ#eZ>eNAUw3L>*MiQ*Y)G$g9F@XA-|%ckVN^O=(xTA^me=5?`=b}(uui% z{vmzTvmf{Q@xWEd*BI=!mt4x*ErlwGm9f)pEU1iL>!Kbz&RIsyHhbbxJS-6YaE9~TOcTqwd4>DU`)`D=ZGrr^j)kDmuc z_d<{f0lM(`hw%VxgDUZ&PfQ1^0AG0R^!TCBuWWSKpfYdcOH(1!oeVe@9bRpI&uWE| z<1jYue7=~Qh&g#Oy5{P|?f4wvq;p8^tN?*R&lk;B688tL=$ECGWmyyq$S}}+{Z4|r z(0T*<)#O8u=Z%cOz_TN{^@{Vpi`5kHzYzI*m2^6_?w@?cMZJ*ls`~OP96!@*41VQi z4=PJXPS?PGBVTy@;LdN(jCtrnbnLi3ke~yoiV3Vvwcq2z{=b@jnyJmqmyvqhw1({H zqc_e5Hs5wIC0wtR%sQJu;I-eQCgqdbP6@dXfpSsi;KxbE+pmmmHoy>_ul*S>PNGzwQbI&DrIb>7 z^&1OyLk@8g_EK0br{bnPD%)~cs=N^OV{3bQVSA*>SMwV-?Rp&X@NiCjYTSB$_3gIX zNaIl*tXcMxXbNBr2>Y^j-%|&A=cYct3x0@@roU0<*JZDk=HQQmgqf|`U%hxn1oP2D9zTSx2SDxqeIGCK=H+m{5Oy{eImYkYg0RJH4%dme>1;PI*BTG! zo&A@3tUUMZXVtuEd1uArXAUl*SlJS(J00)4vg}uv);`6FF8ou1(X)2b8FDYq%=_>B ztH*~iw&S16vPjFH)RWzXkfR?pZcxWRZ@(>KoYB(=PmEG=dZn1EKkI*h~`1Z=FA zCb*X>`>2#6lZm!moBVE|8ciJ6%}yoe``Qoh^VPU`qsrU9eBXXNWPFOV|NpFA-E#9N3^TKR-V)#^>|N*D1VFN5-u_Ib!?Q z3{BU^EdW5@d`G3%(;W|%ADks+@Q|%ges++*>Jy5pPkrz=k#ddr&gS zkSGAl2V3$>nWcGPa-C9oy+F zZwjzz&)G<5&~}=lyuP1vcIo5d7*AZL$wA(n^Kl%d6vT(Jf}%-<88~;##9<v zNZ*5IGT z0_{W4&%!Do&+m)M(hdr*0+KrwZ_#=IjUU>FV32p^5%K4?`Eemhe42T|8g%?6kn=n_ zFTg*@wvFoYUBEoO7nrjV2vL<7B?i=ZhMQp94L(gZGMEO+-3s(SiO#<3WWf4cLw5BnY7W$FHzkIR`#~*Uet)1@kVVujzv0M(HmQsi! z2Q4+z_TJGKJ0r$t7azh{5u-OFvNu4y2+;xY8{+dz`LehjFX{oN_4OOV|NZ91*WP_Q z88z02v%WZiT=u9G=xA2z{(2b(o9Q{p z>Aie6)JK4Sw#|NZihp8$fSSs`yWDv5xjsd0-~IS-1;a%2M{(u^G&A$hEJvgqUX4G< zzmN{icxL~I)Tg%Reo$O1f|53>`zSGY#?;kZbeB z9(k;T_)JiR6UJ|HpO+KC_00vypmjlU45XJ49Z!bctwlPfOM|^eSysb;;g}>v%Me^`xF)8G~FW!s#k@xC+7JBd9hVUHuv#23{ zemoxMc}fa9jyUH5>is1CBX{`czW@LL|Nq=w-PYnD41~Hz-~W9*vKMUUnFG(PD5ISnr6XCmg6O8 z?`x5ryzY=`kcxy$yG%_7=r%&? zM#uca9CRyi5-RD}aYa-4H}%|a?1&>QCz_B|(EZ^B;NsFnENpv3qpNA2&nIIsnw*Z&bI#k~MID~d08bnTJH>uQGUJ~#^OL%wRspdxha1aavuTf9 z6LK~!X7mCAKf`~=&wBD$!+-Pn=oF07#n3RiZQoe=I$oz^8fu-u?EvrdJt#Tf=$1+T zU=Ts)jh+}|@u=iHo{ft=@Irfm+9THRTqKuQ_y$1*f1(C*KSj6sJeFra$UMa1kA(?= z6k0iB^KW_;1O2Xe?c}DTdUH)`Hnx_t`kf=oaz2%OU}7BNW4f#ORQgk>V~)hBl#&Kd zLh_kOeWL70uqxFnkEBHxOCo|_>uFNfkQq#uC(uTkMocw-PH2WopySPpI=m9 zyNhpJxlYas6cwd)#($26>1n7{e5NA0s!HugHRfISdtu9P=F7RAi&TY{AC=pwU&>)$s6TTsP+g+A_i3Ujr1I78YENhI`XZbz>{V#y(g0R_6QSgdf`Trb zUOMV9-eU*yvhUPU`Hy0?*=JTm^NNiKI26az8#Tf^pz??N<54&4Zu=|i_1jJKMpPac z(7i6dRpe6Z#M~0^9T}Vv&XE}B7xSW+ZgEFNE`j^~UUuNxe^o#K@px2(RZB~&iJe@3 z>2#RWq5$ctT6LJ)ww-RVFch1X^{*s3>3e#<3g-GY{S&0(#p%DyhgDF!Vdc0+6D-Z( z=%UItE@;wQRcGMy3a|Sl4FmoFdoQ|s6E3BUubQd4X*Bbdcmx{N{|Po4HuI%G;e8+r z@FcN+=4$v@W5Lv4O}S+{AQDd?=e(cX$1QY&p|g&=&On+BOn61_=l={=9o!)BaDYIP z^D+0;PskjAh2g7uN{Lj~O(FH=VGB0iOfZn%<8xl!A7jJ8ljL4#2M?orZ72NUe+ipd z#|(at)xAWT&?$eTPMyUp_~b%zPo;XuE`!s2Th&K5;l~0$U<@$O&kwl7BG$83(OtD$ zNyQ73T;azGkBaZV0RRC1|HNI(lH(u@6yB}M|9@{LW)EySjZiDbCK(;3JPE-<=!Fns z?%sLV7kA1QqR`&C^*-ENxq>5WH2Bh=dpM%n6fKh9u$Pk~nLwxxa!~JuDMD8#5JNzd zBO3d@mp@&A18?CF41^Y)M96npfV1cw0hWQckeKaoYQ~^RzQE>m0sebDRK%V)zpLS} z>SS2B`ogOnDN4V;IDTk@shFMXD|BX@X9I$>^n@$G2(VXi9r)FFc8OvRnGjE83^ZrG z{fiWEyC#pEl54|cvHJqH;gdHCm&+>7S3b)zGt+Gg;p|F=+Q5lj`Tk&HyhSd_KrTQ=$Qa_ScarbeA{riKdZyyx149-x=IMe)R-Dh z?d^hUh8xM=V$wjy-##4RRw9gzJ?rViiI0wpK8h!*0@waDp!7dw9I_NzSe3}wT?9 z{j4=Q>p!@8taPTG37&YBtNbywe_H$f6xZJRD|c|g;0S8=6;q%e=XH!8)N=n*;S>5} zTYtK8x#k&%wsx?$+pU$jYvt#gzs=QHoL;ghQHG&hUblwZ1PZi$_xRga9I#dX#=`aW zuYih!B||vpCp&wQHwzz@0B1fh_p0IYRuOJ~NNzYe0l%{DP=3O`zs{Xb;=@*^^9sWCm#o~c;y-C6T_!Sc4%<8T1J81uV#|uTPQkf-4QH1V##4IRSrB}v z=EeGrQGCT}2gu}t`33oPvwzM`naIZoK~=(bQQULLoP&_giXV6@lONoTg?NxRDb3zU zyxMYwei~DN*?WwSt+G?R{$(!WeJ+L*3GOzd4_Cpg{#gZzZ`tDTgF>kc`6^p_K%IZ+ zq}a)FPJFNyW4@5z-a;rBA)Xekk5I_QdOap@UK;Ge_?3Nya~kl*?v?$lr2p{qS#6)# z3ulgxbdF(Su>Sx60RR8YT~V9kAP7|V_W%Fi-P`6KY^NhQ1XH`;@sy?p5n;fnQ7&+o zN6EDNQDp|EIaffocRUtfa!c+mcasjuKNYf^0*(AjsK`ghGi}cQWnhA4YNFex^)|8W zDNj&7p1n^aQNUo(=tlDebAp>m}q*8qR&a=JY0gdv2X6zxDs0I^E z3DwSR@%0q&LAphD?$)ms!U#qxMNL0bYLr}cXL=LDVQF&2WS_(VK>KnpKGdx!R^ zl#Z(=0A16YBBdV{cbd3=&|>IHpLg;~Ky`II2_)kYcNxYLw2v{_Wl!{WvZ^0e`)&M` z?36G*L>cd)88T||^9R19f85_cB|fB#>r#9$Dn@}ee$2)P8c>WR*T_d7Bfq)mU(71> z>bZ8#UAv4+(=a-)+&j8!W>Q+?Le4NihTFTn(d zIv%Ec&^v+S?_VR*?S6vX^UIfIrc6Ty*-qU}g)LRyOa$UOj*ol&D?_LFY%Va58$3JZ z^CBHHDnb4!>ScMr>o(> zGA6Dyu@Uhn_kN5s3KQRXATZ5;6q)(a%v0W-mA@=OR;{)CV%%i$zP`TjvCr08e~s|@ z`T6tx&5iXAp47R@$6nm%{;bZ8TaPgtue9g~pYQb~`zt+uXBGMOF2|{*(z$$$rP^h0 ze4=2b7o@uu3K)n(MGEJ29=K=R3YGF^&P;sg09R}6_sR%*r4*G1?m`C@kKSQ#{{yM6 z@#DML63{Ml5kGaB{!MFV(^V(BuM&%W5Gl*5ZmexGG%LTZ`BWahko?#EG^p2Oi1CZ# z>^-@TBWv=Q4T0B!MG4*yFUDEME6Ag}eb58PU&Wv8st}%^%47Jeyh|eGt^txDy^(lc zo?FCmB+f&O-PYMb)~JCVed?{X50qh2?lL2y`8M)6@@*B2;S*;6Js_<}EzbHQauE(Eu z+q1{>GPBZ5KQ6`1*sk(=;Q1YJZmsP)*(TP1;1|=9p7Sb>Df}@^wwp~5FQ)TZ+i@&O zr*X~b8Ba|UfGHo7?ew4j00030|Lk4SmZKmH1*`M_zuR*}_aWQcYeE=6v~zanK219o zH9&F`Na(5HZXc@vufoK(3E)cD811=sK(0kJS->cV`*9HGm1S2=V+nucK_b=MV_BC#?%DKwxdQM zZs+wED(r&kB7v&oy&!Y8pxDET%d*CZaUJEA%vWx6Y@$W0ol^bs?rTS$Y5&;#;&G+s zMLm#tESO%W)Ok&nJpl`zUp9bp9?HRp{w~HcxUkb<-Z`(9Qd*WpX63rBI8oiZuQZO$ z(;(&L$~X1)%L5db(qpZBvQXhK`#loLSmVVQ!*Lx{wV#<^jT!K=z=oySK*tL-wIlEh z%}yb|aDi5|Jo!`nWE4C*+uhF1z+mPXI!)8EEGZ>9F<>IJPFOF)zC5n%cyJRl-e>O~ z_&F1vkkdTjsC-8C<0zz*LSMyQc!Om?WPCIUB(r!!;9BVuOmly%G2n0?17LXcHG6-f*)RTW<|tgOwHvc zC^?7Rbhg;5mnuP@_G1R@sFSrup`7?(g(L69|K+9J>#!_KJf=O!cy8s}f@mrNj8%Y^ zfBvEm>}_>B=>supqoMkh(kJzL#>3 z#YOi;%Q!3x`wUcqIv%g=Pr=5iVO+2;_Tui|V=zORj@+Ps~6Ooq39 zIuXUnb_X8#?}>s=A%Ir-D|t4tvO6(RMbC@uQP!^<)%f%Ils~xRcwb}IAN0E8yx$7_ zv(b?P-v%wM-Bf-eRN1HEUH=;jaj?R#>Una9y|`3|h~LW5Lis510gHK_w{4TC3oPuq zu4Cga_xm00dLONuuwB04d3H*S=jG-O+;4`w_|K^J`}Q6EtFU$?tGEa<4SNwY5yX8cOq8ydZ7L;9{=BuyHbBF>irilZsX~(vL3MG-wt@Iv9AEH zv*63vesV&&eT&xF?a3J__qY;T+Pg2SK79NG00960%w1iR+b{@3Y4863|LrB}gB!A1 zSYmX(neveFI5H9l7W83DZg5u<9Axgu9behOFo^@*be0VXCl~M+WjpxPUDZ`I@sBs- z6X{(a&(i?lj5%Yy(FgXXT`1rYLLDu{ZKHU)Ry`wz45PdkhOri;%6ex~Y_5l5dvygY z#`0CAA_cK5;dcEO(w(OX>&LiB4(FTjO_#5)FW-dZf8Fo*LtH|i4eILIiJVcDSLV?T zBouzmv~Z6Iuibah9!$%dhDrZSFLFTU=P5;9x?0!b3IIath)(aZ>F7ngGg%Uuj0-GuS6!) zHgr!k8~O{S#tm4JkiTQv?RGmR8gAjsH*@tnG@CvBpdbYwvc`zLC&@K~`-jHhFO&Iw z~Dh{gnVgVVhB^8O#m9T33VipRn@NGU%S3tYnkmXR6f9&nJiAfjX zjEb|}4L4V9&}ql7Y@P)z$L(D09wt6S_ywsms~Ra-sn(j#&!d+WmQS_gwbH&L+gNia zC0ExJAJ0=n4yf^K3n6c;`wJ0H$qO)5*t0{W&+|m#9%E?QkA=OBHTl77%M8OGJkxSz zS6$pzG(%c){Q3#?$aCmC>Z-VA8vl#9;KqjCit*jcV3L53*NsVP6nU(T*BhiB`^FgE zJT`6%KDg0gXfLZq$Lj`J-qF&3;nA_XYd(Y_3POkg|{MIh+_s;O%!{x=tmr)&hL#2BE`sV zC9YmYQUsAtcKHxKITvTbnH~v{`v87e7ygd-#ezK=A6HuXEWM5o22r< zx?U=?AueLe@*8IS2CN^WDW>N7l0wZ7$b6e81hAd9THsFiHsi0#$MB{%>KH|U8qGEZvuKH_b`&K^`wq6&)GrHPFtFw2*ZG(KwR^wDpC`PK4U43r* zDc5^qy^msg&PV3Yz4jnCSNO(mEsBq+T(Nw5pIoEH$=huKffSjM)HM?(L?bw=%AId0>jG+tngVV3uchiT-7%AD&s?hMXg1KyS)lJjq& z<$Hv23KjCr^&smb(jG~iTzk;MxQTwfH>ufbLuWTni;>i}vI0!cq6JbEv+%8=xjVjA zgl$01(XMKLQP!gHu**l0#CZT-#Gk7+_$r!m9!Z8{#fQRN4HSi4p&lHT)y`Ib7I%JM z2nB`drtMc%r@mt_J|b1u@A4s%#K(UE2@CsA*Rw8k`4+v6YpF@2?G;S0z*rOVzW@LL z|Nqoo*^=WR3>0>4{{Mp$dmo5<8eIW`r)v5shYdpLLR^z4xLbni&>H7`qJro1`FK1K zVc=A`h*IlNm4*~TLf&*o_Cz5GlmqK`U2eVVUF&y00u%r2(INV_a1QKX(3Ab3)9syr zH6Iqym}lR9PN=GY+$z7Di#4$pdW)NEk;G9$mEsU(taz)<-%V^2dA+&D)(JLg&Gkq9lHde=Ax7B}a!!5;4pGE# zX4>oF#3{D76Q&FnyIc$F-~GGquAM2yYtQj*ReUnKP#*S^S1#7L4sy~pHBe68 zgHd}UevTrFLnP?O2!$Xf-f)U)B}Y0sYlxmvFc~&<;lGNvTb`eH{n|I7NM!%{cid2< z;*b)LPuYH2X(&SmJU6&ejx$N?MA1JBpWzg{aS7i6h7*&;*Xox zlGQHBqPir|a1y{PCNl9ag?4I5>;4u35;Et%Rv{U;{t58#M<_^peOlnI{K6{v9A#ZJ zK04#P(2$*pP^VG0YoGktG3(|c%*)M@^)>G9-@6g>LSnMF%yAcNQoNWC?{-pC^kwjFF$>uQ+t`0iM=(zTlZ`&ra zxPO0n+!5tTUavLz>QU4kWh!KvD5nJZ;n!ec;rQ#!)-$k;&08_LK7`BRC&Rd_>&VUZ zi0t0SxCq?HMb343YN5Z1kR|9B+gdA+S39ZLEPEBx;#u# zQ_4pONhbu93GP884o>so6|{|&!+Yws`?L`*U~z^J=1F`4Z%@n`=t}t0vE|e`mp!j1 z^4%oR2~x=wTx(|l<9Md>#l{WswxSWRQ%&@Yx3d5Bq!u2`VA4IsAII_F7r_=EDC8Ax z`_2RgxK`Xx*-DB0I9-YX$CWN4+4=BJl&mqRPESnBVNM7Z*iq%R%0p{c)x6wg8;bP| zbfPo?a85rNxpL3*;as33VS)>G496Em0uQTtpw&^}M1hxGi{HUId8EP z_z<7$-1hX=!QHiD)KSze&<|hTAY0IHD={PfGB<6%T5}6<(-JC-akObqKu;DpL>hd^ zpQ)kv1&n1`5GnR?jmA|& zyB|J&3xyv=QQ->@&8rSb4@;T z9KyDvrXDEajY5YUoXu5AUdd@&w-_m>=A8aKpLUeP$T9z>z0opMf;C9YKxbsBQ%BqzjtiJ37EP=hQU+D*A2xS55nNP3fgU#D(hh zj3V3<#M<)0F0aC?e!}qw=mWa3hm=0#8=ASGrbgj}S>UvwHxwaJTmX`RGs{aX$3M=7 zWpozsyt&4OO?>jF71zs|ynR?66n=QUUVw1pes#q>&ua)t_i`9!G{36dyKsWqKV?6f z>x3uBy34BZ!zmT{2?^=KQAOtd3bibc|O3v>hKMrf;|wa;l{0;cJr&9eQ#drdTG*3-xk#fJ|>$h4sQ8bHV=KJm2te*@IQ7^M z9c9%C?sv8_Wd2u?b;BNCD(W`~7;0GQ0<~)^@%Hsw?8${ynd|vDQs;|O#sA0S0f5W> z>7-LWN53r2F9Tp!bX-tFQ2$p>b0=r=jupEahg6J@-I(BR*|tu?)kD0!F|Mff*#AXx zA5$M3in9QZqXvKa0$-!Vpg9@RpT2b$)%!2XKZ^cTy&hw0i`G>)KEMiCtF3Q8%c;Nk ze`^z`_JVnMI;}Y_{R;p9|NpdI+m7TY4CR(e_h>$LSK3b>jk-b-_QB0513siO((sf{ zr-(7W9Bf1UfB*bzJ{qG4IT_K{lO%Lu zuGXl|;HvuvLI6SS%wvTYd|cnPGGeK5eY*a1z?4!-NeVuU{@Ew9uUf|+Bos9oE2X4h z1Cew3Nw3m2=iKM#ClEGjOwaRlXYuVf?!|Hb{{73>;~OzRd4|XX`6L$6mm@a`R86YM zAMm7;A0OF?P&?_zrt_|1vjW7&AnS%VLc3eb14f`a~k9<+d#d!vzusV?XA72rBduakpFZ#Q+4` z7{KV601@*(1A;l{bzPTbInVR?e2N8I*Ofhg*Qbst4cOQiUh+-m4dl z^Q8&CBs-Fl44qigoz$bEUvevd?)xr^Ba)2iLrs{L{}H$Su^ouZ0#%ZJM9qKx_+iQw zlb?{K-~_}}rF3F=)rVg0aiO%jtPop_q*S9gC=fdG9m&bx>%lOIMuLc@?u_!o2DQK*fG zj6A>ZyZFK5I3yVfbvEC7IbU5nrfZu~{;{xxH+0A?Ag~+3vpXce7 zC)M;vBIgu$5xe?$Jft$ds6FV+=*bVENATv8=ht=p`uZxRJRXlwHz&vsOKm_tr4$y} zy^C9zok=Olc*T5)w8$jNo(-w|6S%c)TU67e<&)VfMpz_z4JX*$VdG*2%5WT-hEmG9 zt|oq96Ly!+L2ba0SA4IYs-4leNKd*pETt4yU?g^1#715Rtu&v<#t(Qdc`v?U;#*u= ziXCT|Z$yt6-e&gdLGUwZEA6_8={4Q3 zR1s7sR{|AKT#gTC z2IGGzMYc7Dy00vybQ}j=M-co&p$pgR5g+E9KR!N+<$uX=-J(udhqP#U?)aRq><^?! z$b)0jgZ19C4GByy^uTpjm;R!cHy%IH?f?#AGVkVn`aF?;7C#hZINC$j|7pdq!i<}? zzhipDTJa?BpiTi0PKtwDVl?G}#f?L|MH4uL%{!YH>c_7(WWLECCU0!MD4%cUiNI&q z+HHvyJLj;zaO$A`LCW2dy{9u1)CR!AK1JwKge+7#9#c`eP(C6#x|h7 z6VKPI+v>VT|5w}9(Z1;pHQ&rQ16%)M#p+sdT4FQsj_grBopZ-=U>lDh+v7N5wBrev ziqJKI`sTQNZBE6VCVPiW9N2xZ4#V^Bi%cZzsvibO-mm=8?!V(<5lz=#L~d zDe(tfuj?uk-y9c{ zTZV@z9^m;16W@CEaYZe+f)9ahaLwY?$6?1UJ*OWbZsZPPj5rZ|^zY_-DbC^X3dSFO zfj?8C`6el3*ZGAQV_^jfq_HjJ+iu5gsJ|d_bzhBe7cZjtgvHb9lKHz^@5Q_``*YWC z;^&<`)EoG<+_HXl67OR8jp0ewm{#BQJ80c|S)pyX!h6gPFgpA9GQThlt&jeZq6`h_boPqr7qjy@XUSpQ7=iizB-u0(}yM`9T|M8T-R?%)1Z(fmk2-+e=pV3|C%{m&WH}1Vtn@*T88yRH`5p zN&}LVBZue&2x#U($A;Bf|6B`T$`FVF1xg(FGAK^<(}58~%TNzL0}&TMANf}Zm{flX zZ94#Wj%(u-#80x&=ktj~?tM^R(@vQS7x)g+y9lBU;_6pcqXi;4N4pTGkUM0xb$=L5 zHhSLee-|Y3gRz9>x2^Y{NA^TGr7oafA5QUceIjsp>Ms&b43sB4F8!NfWj`QdL$@3W zt;-dklzC9Fbm^8`WndB&$+1$RqZu>~&vQT#cv zz{&YG;^dw}XOGc4X)%wbk@Fyqy`zN$fpzf{%LcAV1x;#yU>OTfD4&Cc(OvOI^egK) z5{0d`ak67SZqP3b`k%9bY^eAUDSU(v=ms;DdokEIMUYW~M-MCgsr~SatjEh`+idScdXsQ-{&=^UC6)>>?`~oWOf!xT=uzqss#iD8DY>Q*9;sy52 z-t4SL>6ixUZ+ZhKUB?exOi#jL)TgH+=>-#gd$n_%O#dey5{ z``(JgB7knZF>bG?n}cZd8@Kervk zerEH3ca|Ha;7Y1D(o0@ne|=y-ND;XJ3zG9 z9&AZwk&h^sH|9Tw9#oJ!#TCwu*AnKf?XT`vr`q6<9j1w~CF8#J?1Ynl{L$S zqK~7Q@KpJu^;M+a%dmspcx&I=#S=vQpq;BJoem_8{kX&~a3)~4;*OG0!Chx4H0@C> z;j`lE-lhO77&tId5d|u+P3HdKHR2vm4=gt}RJI(;bp1S=^F~aqQf-f|MLj)tp4VYvQ&)c&r zc%P8MC1t0$JNOR1@~;Ul;W1~A7|BuE!cOPOeg0JTG56p24&yoV%qQn;c1f^iKl4%)wGt+*y~&JzJo z#1A7T##?q;Tni}q9Nl)f+~06iC;qrQTpz`2MWgKug{riNj52I)*av`M?>f^1>*<|Z zV8Q;9;k+F66K7mNz1)S7+Ts9kh=gyKV%iL zO=0)x!WKczR%p!ye@$RWtvw%Kuk=g=(RKPLC;kbFx|s2J5pRWB3sPC47r4`i%hY(JEr ztXb{qdxX10S=N$6iF(oX!}Il&QHqM}njP0gubY?%`Ev+gZqFY&oKf}t7J?KxnQ?N< zH&qGAc;{8l6-m7yCA#BZDZR!jq4Q(s_>8n|<><}3CJ9PPIH-~le*v_MJ zerH|j4zZuc7npD4#{3J)*!6$dSo6yMC+v0at96CxrM12^$-l$4y1s=(DOM(ztqjc{5}&7WnE4~@}T{?ew?aNY;d6slQ;?U2q8&Bl>);AkGW0idpdVJArm1eAzpN*Sju`Fr>K~rUu%VR=P=Ga_PnDZeljEg{GB0|H$k1}Fuj$$0S}#WxH&Ys* zf(q<`ao^?%?d3r5zadB@CV>t989vGl?|M8QDu00ue_4K*=!|(I0~qp*S)vg#P6p^n zIK3A)PkYXp{m0j_T=R!6c7WkC`msFs=`(1@w>34=_T#fVDLM>TJTVI#b>2R{4@_SM zp`1xZNQBTtYjQ2-1+5o1%NKM{*2s!NU>&@|yEFUo#t5`zx%7a|R|8AOiQ~_S7F-?A z;s(3k_VOJPPw}~<7aT?J>rXM7(RsUlGi2+8Y<;yEhqV`@-yNqg#-n~(R(jWDhsAn3 zw!GJ4`r3Q{{{F^|?{5ZlC|xgTtrapMWb!N!UeI%Y3(SVCQ?3U0UXNpg^?(M)_H^tf zF0p)s$gfWClaitQB1`xQ;*SnP0I?5&3vL7@x~VHeZhgM>%$= zYup$sabU?exZ}bAphFOCgM1TQ) z0Tiutzh4?}4}!*L%|(>6Kw+%yO5&2%rArAIT?E4k_}>}+4xLypM$z~yu(p`(m&q-r zW4J{%wbe+;G0u% z9T*Q7h?}V`Il+`P(3(4tc}jVVnhgpK=VkJp)>kF)QbwOu3k~(?XV^7EoZF}-+6Z%gZ&2p0RR8& zUE6l!APj^w+5i9GT=v2BWGo>WfgJbrbRK#f?^?ki#7IIU?F4rpLVfwZxQGJj8LnFx)MBF}@98DfLG)e=q9*(4RB1IRo}@OQ<%7K^EbnDo!OuD~yr3@fMIn);|NZkK+Mcs2s-5qBJRUgXWKoR! z{r=C`fR%;o^@_@~(xJCLoN*Kv1MSo|QJ;#hgO%Ut44q zLTDnT?=+v9)SN6d?F=t!&`%WpmLu2ST+FxAvcp2)Qx!mCJ@S=-=Mgl=c?4%K38DpQ zJe5uy9r5~TRo(j~5b@FCS3g(hTF?eF7Z6+5wEe)zlud}_94>ZGsuQ@Zhqma}qQ&laRRJAmawP^<>b9(f?XU&z=UoecZ1-!ed2aa z%<%c9)X$Un>h8D;JD_7X->ZN-YW@BE+@4r0JW!T{4u^uR2K!QLwR-buoQNFdR~U5h z(Rx8k{!%bpRNRA=hb7=hf){zCPOe(SRqzxx?h9TQO-N+H8W(dtrQaJx%Ln>@3}XE% ztprawzS9O^@xxqby?SjUNLVF(IeNYO!vap)v9d)wiv7((_8}@K${(WgE&HF9u;jCO zDxJ`C^s21=*0Op@_zz{mlCX7}ktTTNdt#2Z>L8EL;seoF-sO#<_G^2Xi+LXFNM>#W z{kg1uka#b+`TVcN<{>3%UAB1Cxk&LZit@*`yR@r^ratfSb|D{eS~0|9yldWH&P6}p zh^}|SeioWIOmW|{>|nwpUJ%^X*=W_|;kVljwcLwtEH3}oS57?PXjHWY>U-g^c=Fya zJd2AH!7e1O*^CGRDR>}%452C%TYm(dXW-;*b%@{>V4ff1tX2qI zcO%8N(3tl8wK3z+NnaJ~VR3bS*}5LFktpAa8$?yE8Luujf6IM~D6}4m`h1LLR{kQ2 zX#e~BH2NV5Cva^YlyeqD|BNj@3=4kqS)!K)EldVJXndrFp_h)qAtp5KD71X?Rxv1MMQb3k|YDD!R3LNZ< z#MyUpYRl!`esnzEsJCK@#iDfZMp3YY3qM{V=GR#5N(k1zh5rBm0RR8gUE7x1APfYO z|Nr0Qw9p4O${=ZE9^`cV~_o+8x`s`DhC+>@1 z;Zk>l1CK?p^9<<<$AQ$ZDTBAcVLj-p;<~+eW)F0N%!^gYzWxnjT!~XC{)0e{@Fa?u zeut|s^LpxWpC8t)^4|h3COSoa9 zhCsi;Q*L=|RCb(SMTnne&A?F6<*eTYIEH1^g;Ng!Xk|iiRXgdC%6J%VAJ(I2zC4Pe z#-GY}f}*ID&I4(IRQf3WD`KQt6eDr<-d=|pOO%=Pcswf5{eGVpEbmHFexN7}%f7l1eyPBf zr~Iq@>!&D-O9PNokge7#FJcX#^7?LF@o;I7c%_N-5>nMwaDTEGwgEenCq*E6_1dlrQTSY+Gxc+oxMUtkGxCAGo5 z7zwDRcU*W!&QbsYd5kf@J~5&pR!ffpW-#zcPlNKZdqc=_Ud>3^Qeami4fIO8p-?og zf=-M}_F9Tz*s4c)9iuFC$M(kbqEuYgnZzAbXYKwD<>uCda#Q71=#)Dt%Mbo_%ct-Y zqr*;%S$S3v$YNK3$@pSM%%{2z^vmKJlMgG8j<&RZ-S~xdnU(kL$IK;8$}Y5{9~Il{ zOg--XtbBF|H5>5b`e}^As)kzAU(`H7iY1H%mSHB(=kqBK;^eKwufr%d31>4b6k7*m z<0D1`hPM`rKBwpNIaS%4|08fgNe{4C5Px(3E zP{MKqVgb#0c#02jEVt2F`jP{%1R{+mk`S< zVt$ZctNkR_88_7`?*z)Tb030y zame=9C8qZnZ&kH%p2pfumH%!iW_juSx2^|R4>jifAPc4Pfy#I6A&{r5$KE@B98y+$ zyJ@kmUk2FZU*+f05jW#fC0V~@Z8YvL>d{uR$v=C9#RWTlnLqyk00960%w5TLW9p;8En#m4E;Agd;Knpn+DLgb>c} z!^N1Uo>^82UQJ>xmozDdv%IPRFPAF&3)G);<*)tv!nk6&k$_!E?ZWO;C}&Ut&6ijO zuWMhN5?^Q+_Y*WUGvoYn^F1~X@c>+BN0EB3+EL}dOBGeQ@OwtBzj52Q@+Zl=a#vvz z0o0`05ntWI67f!b&itBwvROG+Z}JI$7&9gD{>cMOj3+KwH^LLUh)_-;7|G#gQ(8H2 z(}?>55A<_J#ofR6$@Nko5HN;Mm<#Fa?f*kt_*8zF7mjm-TC2}C*r5(t4#__Aj0nZAL4Hs}vQXP-1Y!2uN5;XO5)l00}b)Wy5pdPH% z_!=wxFr-O2!#}{Ox`N!#U)3#>$w<{qW+Wt|@?_$LgY4*RQRW?e<}?sEr{|3jjtz)N z`6ZmRROiNF>qnhFH1V(6C6r6p*`Q+X2&CtZ)3Dx2Y`$C;OHHA5CmYWqJB`H#u!s7a zQN(K{3WX1M@uT#L3ql{~{eBN`R&nO0NX0c1@=@tA{>fqVwfj80d6MH5mBwCc!BbqZ zdLf_Y`;C5M=&N11N)MaqU-`x!4y@;S+OME@$CYz3T=6^doDm>fD^CqLCHdiG9W}8J z-yT*J9#~cB4sKlHe^n1v`k@}iIefK+B8_Rs3gRYmep}&?nGL8jq;S;J3rUA`zg?VD za&2 zrH&vN-!mG+uR-!Z3d7JQ8&Hm2AjF0*8cCm;LXYAT04sKH< z`wO8x?z+n7DnE+e?{`{D6Y{Bf2?;AXuja4D4OXch>_r2)mmfz33jeTP&6wWPOse<_QcDhRyl^rQGz^yRj4=?c3)RWbvDKEMM#|WFP z%59gQ#QHb%{gY#~eIc)jD|V4;7a%wH7yc8nx~VF4KB=s{HwjHwq`IuY9Sg~vmB4D8YYp;g z`QZq-+#HHz^+fOhxIjn0w5A4>QGz3lVgvjCLor=aZ8kgfb@igpcPtwm8u$BM@h|;` z-D|dVOGT*&@w6{O{NDtWgb*Z#sUK`j_XFEEGdw2k^<>G2j^b6Hir3ia=tJn*dygF- zT^xO|x@!bVSjzt?`sLJ~sNMp&oNC1L98{E-7x!WbnBU*xDmdD#PoFFkvR)Z&f0XJ4 z?#czRzkQP|ekw2l(@u$*6DzDe)%8PW*`qe;~` zD}5T#Hs6vuR4yEsJnV5C3bcGI4i<@FVFJ6WujKt%6yfYBP`HS!c-K^%dPWL85k62Q z$tMW84A&L#ZJM)NPK;MwR>z$4Q;#DXCE6U>Ls2eQ8b?x!EfbtA{^GHMuPXSn_!t)i z^Mw?Y}RoC$!0>!l|f<7U#dGBaeTCd z5)%7o%{n_=R{G!igq8Oww#L4fI|q2aFs|c?Lq%NVs;Hn-v?Wy0OEI2892Ido{inL$ z9~bbJWeHFUGk@KDbCfK6xI7`Q`Y^#%tgJrA+w3t@kE72MjB!~)_VZ-f&z71rqm&_n z-@xZ&zBwBAzv4Ig<4%)2ZTRhCYA%Fe#pP85r^on5;Rn93aHHTKmuBS7@j^O|J{Suj zZUlq>!o_(_9%-76-EBQ2%&hwK&4Hq4gn`E ztG=ywVE&=ban#g{WuI0*TlaZG!}R(3_XntsOLae#9$rYr1}DB^>2cq8Og&so7vFBT zzpvMlnFWeP!NytIn4>vlEPPTKk31_}PF7s7>K6V100960tXzeNfpELK`R3;mIe5U?Ftb5`x6P|NKjT6WolkxnGdPH(mfYug`i0wUD(iN9!}_ z@#CpiJ@)eG$KwZ(G+rTQ#igGu0Qh41r}1RNn|)!}pu&UfUZkn8J8ij6_Z$a)BgMY& z=pXxTP|jJhF!CX8`JJm3b(jH}20gm))b=laVIONuUUh+>27IL)j2^9Zcu3psuM6RS z4Xax~=5ZMPpfHZ5BnxiL>#hY-BhDD3=CkGxN-m^c2LoQsUKfNp&isrqwySC{3k9j< zM~d`JL35jOe791;JR)vVH|r8cPy#Rn zPt#OQ6-=nW2uPGPSFX%NH2rQOeHSw*&&*GK>%XGP&juxLwfgo%1A;pK^o%P%4ES!_rkxl3 zlqn2-F9*4~t@ePSwWec_TY39jPTbEI0jeukg~+Gu!MM0cT>R_x3L!k7&y4tE(wy6x6_-w2>p!CG@^F%;Lc0j z2jof|%Iozq>npy7$wR4C#;LU)$05NzHUR#kXEd0%a(F7ds`Uaj1o~U8-;FWH zN3~W_VX;(?$3uiXPuo=T{OodK{6*pT#HHWZ{97>)UO9gJ@Z(eFPyhM(Gv~bTJM5vD zBNPG}Vi*o&>zlf6&hiF7uA_!Ju9UW!Ze#LEOLi}U&)Zvnfee$vMP|OI`lYF=Hb*%< z{`%4ig+BK*=ABq)9MsW08^^a|uf*fX6yR0e{*CA(n^(HSb*2FT7?gGO!l0n|oOAwp z9IiiQ?@j%lHdsH?!L&%$aUqIsf0jUBG!#O?;9ySL17-^=1kh7YOVB=QeSW#+}?EfkwSi81D!FT!u5P{xete}(17lHdxc zOzSxo6g1CxW@bKc)a>7j+NhZO&yDR9vH2F_e<@xi>#i+%?07iFi2l|uGdrO0i4?Cx zG4_)Y(AvhL+82FiUUf@G_zG=il@4530 z-C5t6kJk2NrU!S9;L?`sx)?s!0tWeStsTd)=7VXQ>ZwPQ{6LuU`Gx0;T)f9{DL|Le zM-XP^UxltlFxGAMJFcCyquUtwE$Cr!!B_ONg0O9S#~tuEGCq)1P>IZ47^y zo;H<$9r*UE_Sv+g(m3G*J6tDQCx0?O%f?ykkGPGkZ%`R{CRdsj%&*TUw&e|*>9Tc`%x^L~(7bp@aE=?-Fuv8_ zRCjcaH$5Bu`kbE3_kG;{)Zo2 z_v1%cJ_gJ^p2uEI8%IK|9Qx04NNB5*Iw3(bxD0pM4x@rt203?ZyI-K7j*VGh!LTyy zOIyCR-i}wr26}YlP_yd9IGD$pe8wqkf{oL8G$kLWNKkdvZrHDMxV_Yzz_;%TXr@$e z6Dc)w;-vlW_vz>72f2{4X240kxA3D#jf(?D*34B_&q-|EjIJO%W zXud;tY27&WIc%l+d_Hk#dOqTtol#o=nyKE-?#|M4#PEWg>QIm+Y<-aJy*}Zl)xiH* zEjv`aH_uZJ`SD7-Gw!o^Ly-ex_^JdOx+!b)Cm-8Dk&xpnYf4l-*Re2L(kMkc-M!$T zW>_AO-Rfvm`^bo#F?Oeg(Wuq)e&-QhdvG3$g~{D_W`fH3YEcLC#>w?Got;dqh|f;8 z8Wp?dP$0x7s_D{GTv%V0C+*Eq_`1>l@=Jb{uk;A^=h^r+-wHq_INz_1*cS_`cIRRPrvo|d2^H6 zsU$;3x-go`)!@bK7V3oM3kbJb6dkc(K7wmqn;P7D5UMgO2jDKQBpsW^62Z>>cquMN zfmDYxp-bgGOfK0EbaJN_Xl)X-BS4JTGI3EuuJ22PKss@lk?t(>IZJ8-E8<`w_B*9z z{`ueoBbAdctWNTili8MXvTRoVrY*^H^1BrpS^X*6c^o&SaY(s?XINF(6{z)*DnH#Z z%@1Sd<@)z}<8`sAy*`fDXxvreCuFQcow#v}ySO%o=TT;~!`G4PCbQJqrt`yA>)XgQ zTFU5?v?}ZYp-G(3?Mq9cA22&rhoB=oZM`gLGXJgOB&k-9m!A>!gpzma=M2rYyM{~q zJhXC9t*G(EJmS=nUt~3LHqb2dBSP4Y&1bBZyWSvpN`roe4FSJ&$~#|VXSS*SJ1fty ze9n0n3GZdOIl{Owp3ga#6BCfFt4#F@J5_q?2xSxwQ5zZ*seGc&GsfdP+b+oIt&+oR zo^&>D%v%j|oy1S|ddErTqcrYI!6zR4!kUGx}$MrN)em1q1kI#tqB z`<7Kb{dq80cMP+Kg;mE+@s&S>wYj7}D)|#Zpas=ZkEs3OZxZ)6#2boAUXQ(2p??4X z0RR8gUD1*wD+tw|yZ`^WQ#H4u``~!y2p(FylSwTPDbwjFA|MLlNq~DMXkS%e0rSo9 zFLk0?KqW}M!<7QQbKfAS6z`r!6D_92#G2P&+!dz=cgsKtkq+Jj+6FPU6l>pw1RWI4 zQ*JP_!T;sx1Sa@}0C(;PJ{3MpKrSe?hrSzDd_0P&|6L1)Z~Vv0l`x2ZJ|-twD;)@7 zl@~Y4!^dN4+C_N^*f`@A*D+>rWPW%TV0quZLZIRWz?A=A4byQkYLJIGyKIXfIO`4L z4CB4FN|`(s^&aaY2vpJzvlZQV2X^(uH&Sr}_7-H7)7O3&s9RkCveoX!Q27lCmzL-8%H*p8`o6NPq=NKIl`JSW8 z<9|6^-e9#mzqiZ;?bd>nQoFw6IF8THPi9dF^{&cQa-`l@dM3`$Uc z5$@9g0(#7KsWF2~-*ehugUNTHkBC`61_yHd2%26@iL*E^0sPRA#3#E6I@1YK4`p0a zqwgFK$9n0b+e?YK*XXMOD@TVE%A;Z-tWQx-={K!y5zTW{3I%_6{j2;qstGkNfgP^E zbgH@oRIDgY_jMNmTPw^G+;pK#Yyp3&`jwnM9{;DAUP5j@qnCJo8SIcvPn0MmMQ{bJ7wEZ&`W z0E>2l@!3_nMdYBHrb@s0=feDwMoLy%fAQx{SnRI?Jzq#Y+%86d2P!``0m`#L`8}T! z78XM+kBjrmLH@y?hdrxKC07?~p`hJGV6(Q8VV}ULEV=7996DX4xjnah*Y7zzyEDmi8JxR8XtI>dfX>i$`ez!oTa z^1h-mBd>v>kJ`6UU0_AWn-zZn00960%w5}(+aL^ucr*L|U%S(tiRlB)*@F%empE

    )t8e!!1P+23$6a0XP!VCGjXuqQ=})8l{HyfL=e|b$fP|@KIsdi5 z097}VS6k?^W4!H;V+zUVnPM^^4YWNuARPgQTYI7#JMImKc$NIWzP{kCK0ZEbK}jhk zF347WTOHTCWyVXW#4@c=^91o?@kv`*QmaDe^R!gJ*>2dH_j|_Tc({Q?=D@`h%5%?O z&EQ$3KMtJp*R?}!e1Csqdp82a{eH)Zi3V2Z#eCv6(YHiq@SAWj??{av4v9x-GfK-Z z-*n~2C8o&A&OZ5))GZx06E zTUcj;XFM}P31~J2D`^z(coeT~`ooj+uLmFrq@oSkb{SVit;>!O{>JJ?lGki``wK#C z8IwsfG=6#c2~UmDQVy(1e2bcZ#^^3ndv+K2fkZaw4a!sn__Zf$vzS5iXqHGVSGi-H z&5StyKjtp*t7bOQ=IenTuJUCpv`CdnHxSH&H(#ru{vuqYyqzhcbfs3)+a{IVFnBNeO?Yx`XF}705>Et)3f&p9l7Dh1P{m$1cnes>4avRW6}(6+AuX%?vYkbQS%O zOqLuh=)XWuJ=>yU%ei(6s!=`se4R-h(vzR*Q)=A^^Qekp0zqm867;_cFa%FcpcUR< zIQtM8bzN%XjX*QR8{HVvc`O!^u=w4N=OsfYb<|>b? zz-o|0&r>Uh*pF$v)Af8Nn6Gd{$1UR1&R0E9r`P4nFvuQ>=P|~g#9lo7 zuY+n=ZQSW7P}aAr0ty&3#F)P@(X0B|9WnXOcg6}#V?G{vz;v?Jd)HsV&rryR7`^Sv zfhkF?6;F;E-*P?=hB)aEmg6`ca?)Wu?p5Hi9K<7*6=Zmpoz>2ms@%rfCLy7Y|9{AhT%cBs{OncRz59v>2 z!p4ifk`i2~Dy#3^)Ydjqj-kCT;d$MDSK(ic%cGl=jQ<_lMTH;^PQuY{ATji?$ByZN zS3!qA?`@a;Op^nbHZ#`|J@DptRd3%HUoh}0swMmZzbx3Hd{*Hq|F%jGR}LiN?%k&C z@mt?Z)?IMvnM57O@yl6n_vpO!4pho>2fDG|az#q*2|EqKvHB}6xL5DN6vigA5iiss zY{xIpKd78NIzK-@IkUy4(BA+60RR8&UD1-;APmG#rvLxHjZGhv?5!mW5D>ea=|0>z z86OZKq_q&To8T_#r05&-S0-fW0ON?BxLxSLG^Srg>#Q7GD4Oa;U3lR9)YL2o)pDVi z{aD#6ePn3!nKU}w*o8Qh9sW#`QVJJvXz+#MKuyF z!c%ziNwlfP$3?t$tj~M@(Z&# zSu719;1=ND3smNxgGyO0uPl#mbP&h=Sk76dxLgTu0A2xxvpTQW zYumP8PQp!;S9rWS(-E2xe(M1`0Hxye{iv0&@a8Mp4yy_-I!K!3Cjw4P2MX=*TtHl6 zc6ia<_yi&F^eWm8D(m1E@ljjrjAm8bnTv5=E#5~ZAQoI<`T6L2AVIK^KdjChMWRa& zd;q=oQ6rn+_+}1dnG>0{-^C(Q?f$ons9uftE5t@spnN``n-j41;xP6^3hVPM`Lv_( zTxkbTRiW|m+c@M1rMKf5_poZ5ipY5YV`OKV8!F=}yOAjZna*6Zx__2KTzcdGEs6t~cCI$MvKiaJ}NSw4@C>f#zG>!A)#^M&Z!^2tyaqn&ep zd=6--`vnVa`IPn9i<6hf-)D+VqZcQM@-A!8zhfKzwBYUJr`h_ zUdA$%t!q>ostgMABEbIF_&P1)lqaYgrtpNH{lwz|jGynF`R$wccD?oXNxlD?6*tD& zSKfsmp?o1UlD7hU1q;uYGL`R-jywx-E#^hmzpINVy!iaR6|BeS(Q7BVU&c?wiR65Z zeA;<}CLJ~to8hDyhZ|MCGZ#`E1Y!y)2 zOz!|;H+R}^JNP+~`6}!lkEC1crXaNMrs9ei_P684^%+ZW* zL*7A=kGoxV9bG0LtUEO?>w3bIQ_XA4n%}$h^V^se1^s)V_B+y58D-_Xtai-ZxD4s7 zT}u2A!MCX}8vDn*ZHtMKc90@Zo_+b@9;Wcdd@SoA=JXE$00960#9iBR+#n1EZzuo% zx1DA(&SRxY7K`6!@zaAz|la_(y zPZ*CWMY|kGtmQ!PYnyTV{vTirsSi{Q$;@(6%Z4{lSo_nIrE2iYgt2a*W{=Ae7vRMrmpHkDHLEY zrc-8I*NpJcQ~jpeu|a+TAKLUuas?ORUO3S|tN&O5>(D}%RiF)aR_9nwV6F4|tBKg$ zg6sD#`A>y=Qg+Gr|DpNm`zzs}1G%{EWbqIDv;Taf9c1;#$H&+sSkIFYOE}Ga!;XmX zI7`O%n|H=x0Y4CTYMO6a9Vit|I8raK+iw;E{-^Ycf_{e;pm7SOIkX<`GFSP=Jw8~! z*p#YCy>tMI2!mK0kdM%|u7dY-;r2`AElG;V>0OeBbm3^+!5Q5-KoG4!~T6%qRB$v0pW(f&ErDzkO4lY1ooc z_xYA^w69eAN?tec>|)5~g1aXS#e{a(S{oa@w%QKvhKAm0e&jt_11HyYS3{(sNXALd=Ec-FA8dA2O>aW0UPj zejc?qa4fZ!URrB4*@4nM#i9=1Hx{6-3qPzjoFPRn4m(cf2Gscwpmq4R)_0$OetsV3 zX*U&y3`*`Q|3_^^SE=w(_SnxS=-4S4*qPr}e)wHb#Rud_7mB`}^ZW;#AkbPnME%3t zOI_yA>JV^25iudw8S=^=4>50y7)~l7s#h46;!m8BSe>@X_xW>Ud`-CZIZxiSJ0&}8 z0XrqR+yErJ!GYE;ALI#qBHq~z3}v>91~}7yUHj_Gz`@0HWgtPHcj?_`n)1)8YchoL z)LW@nq*}x!uCMXjq6hj#giV>phsR~nx1D@!2dEtv4g9I}Q@MI&r&+(G;!&1fGL|PT z;&~PnK1y#7QcG{7P&U*l=JN`+A)ud$P(8DVzT7Es+gkU*^}SuExa-cUQ)XiP^#WGY zTuO4@3H^!Hp`{u0&o?maBL74cvcJl2EA`U(z_tJ1*WODSt#IV|uL`Mliim?jzrt@{ z&kx`eoNL90s^55n(dyZhtzGhSeeTkm6@Au^DSiF{mz4sw?)lxIWL=W`2inPG3d9&A zuq^w{v#R!h2=s_FUcsjN2UL+onm+;)3XNgr)?^uzXw!a1E`{F9}xdn z;(K7%ZoZ*l%!}gE*m(CZ00030|I}UEcH~S*)=;UU^QHkM^PkuNP+q<# z;6^Efmh3>v8DapQ;Rr!eAp`|2R}85B;;4XPW0fEfR(JOE6hH2(mXo&C0msO)yb}^w z&G1~uS66hZwaU?4`2f|_NR>1cW8JSpBrN=(2JBt&#@=xp>{$N`_=*e?8GD*LKvv)0 z(-%7~%1^}@sf3t9$ppphnH4%ws-{3sl%KbI7;Xh5?>SdzDYRFM0jW=odmc!VY1F?< z{N{LQry3Mr9*53YWN#PDZSg8G!a>@jrDyqRvpCZx|-0^Km1C*=&MnY^i zU??Jya!=9OHf~%&Ap9+U#m5`^x4o^NJQ3YAwo1%DR8C@b?Kcu}RwB|aQ6|?|lu>Qv z_>(MwcoS_NtrzasyH z>tw0&iU1+RSBVpJfPEd;BK&1dR;`!OiMo-`Rf-x?oXoIv z3;)M>M>S-)u{3k}QI#h%@v?IFA?kR)5x@I0=u`(a*A7SV6RsZyvz_ZETmD93WZxcQ zUJb#dA9Njir=QLSqXT9XWJjcY4>2wue^tCtRWa8WsfRa^>M5(P(nHoaIXlY<5LSV? z`G>A(K0Z2j={szv24vDjMbvqC$W5;kL0- zJhyX21}t;@uIMJM0Pmn$%0O8c5m6ey-O(T6&QpnxD)8EH{wP8ZxxaqqY-*taP6 zDBQ=1>vuoj=o$+d3=GM&g66^fSZi4I6n4IiGlj&LpB+#o5(*ER4QruT(v&>kg>#%p}U$aB=Wb z)G}wLILME`*aTPE0(<*n&3IxG?8NmFtMxDSH=+bDqVk0z-g5erd#(Q-Mf;v_BRd~m zoDJnXMvQ?G@RtCf${%>q4zT8<5{7Ah-l+dZ+SqrqHsnTs(xqf-+%kVR=u_>Ar$0O+ zX7J(?2PX+{cvB94SzKp@@y{i0MhB7~o{N5_+`3-=l%D)HDNRd6`oDA>K)@@SH?*54 z(6c6gPtr7=>5{@hxeB1UdK>QF1#x~`!_QAf;=LgkD3>UbrwYBYgS|?we4@Bb)C4Yc zQ1yG*A#@oezy}-L(Si7% z8*RkQqQpr8W+2ho6~Y2mhC&~j*pJ$$7-?Q;ZH``iu> zIhFL5koM>R1)&9Oh=hsG8NjXfX+P)O-AFX>-ah^jjn1LCLjJ=3d$7nQRMoUZ1ue|f ze~rEE><#h}Aoy^8tAFz44l4K;m`OA;I?yXLn6>Nc>x(s^$8o=uJRM$l#pg6OW_^&) z#zUx`o)pk32euHuF!yON)c`|r!6uM4f1o8=!?VF`Rr5{2XaQRI z1T3)~dGAAvxnjf`$Z`|@1o7AJk6{S?pSC;858#K`eLmDUB+2$DbeN?iMCZt^NBh0s z?;(T`LZYiEmu1##ZvK*qCM$np zt&j4}yZZf!p;d_y5gMNm-MX$RrEE%xRx6x$-K}K%;@Tm|wCr)I;V!?2{m$0^cUr4p zpvn&(W_`;})zLaAHXG5ywD6dyzi>cwRh%%G;I;Ij?FRIG`H}%+B)lw(BOB>q$;^|4 z;Hv9Kd)-leDBP_0XQ%r;BsN~HPArE8K5@1A#m(Q0h*C;-s`~((yYWwW3nmW*f-Hn5 za9;W^=Y+m$mlxDswX}}s6MykIcNUWK<13Rv7Yo~r;JAP#>=wgv+kS+h%x4Q*T+%j z{KGUIiWjj%`1!>fb}`5R9}wD=;f(hWZGqj6etFbgfGqs^N9ZcVdkCQ|0d90J4BnZR z_9*q^1S`LXn@2^RWt5YuyA~^m^I|!Vi!4884LQd6cs!8R&lQ$@G0+({E+?z*`DSZv zgG~K`c&>32swWI7b)9QkE9UYxAEBYT8v_8u7w^55f4FLB7H)*yUFETd=>7e6>Q5W| zUr5Mg>ODVhWSwQ<$+PwD4NNhsK7o!C`m)frzM?=0!v=wdrZ zUN;#2wykD*-O-*kt+$q)rv3XGyNX8Eb#=9TPSsK-RLhDNLHU8vind@(BNJ{P0HZMk z-dTtL@(%z2|NpFA+qSGI4CEsAnO~iGn9rZ3pv*(I>6oNI&pJH0-8M!@DwPm1{`=40 z)Qg1IINX8HJzq*8=1o7OqLY+T+bc`Pl?sC}Of6XQL2D=foOAIktzE!7Uxu{tTBlbA zaJCAr&zz{0Wgp@Cq!$OA_MC zaQ^z0GMM$(hm}nJFx@L7`M)^^_k7HLf*#3_^i3w(Zub>Ckw|^($Bh|(y9J+ML-OP+ zf%3C4Z3sV$L%{B)pQ=~#pJIz&=^^;M%xK8zK=)P8%NuYi8PGWMLST%Mu;XVT87~;P z`pp03=k51GA2kkBxK!6mIb|tNGOviJM6GJb{jxOHUKAYBeSbS4D4{RhE%Ax`(B46l zDkKlqb#)UiXn_sl`LeK6kn~+essfk3d+W-dKztsKgVi@=7u&X#Qt0W(c`wUSO8IZw z+U)uDY}D<_{~C@ zaJT>*Q!hx^@mKx}?fk8TA*?vh^HYl3e-u^M?B5x0t(|sJj~hfDxm^8QdE9Y8jcc_P zbhLX}n6+zdU-zBE825-^#c!*JOn&B9-wk1PK; zVQQNVjK>rup)VSxTN02Demi~ga9-+_#ij}pT7O#Cm0n;Yv*kr8$&)pXf%$5P7XdjD zFJ;6~IDFnIU%38+{#R^CBJl_58GGUuzESf8fJ<-fLh7M>7E}m@{4&y$ob$GAz4uZI(Yc)S=kwY3-PMz6|Ih8+ z&hLQt9>>9nM9!S#oCApC_`Vv4|C}9-FHrKJhQ=p}0xw>Wrr8b%f)ml+#kNoD|+OjN!_B60mX!7<29@M|ofdt|EP~^XtmPh3uSAiXxw8`3A=?s{eck7CwI*-+WZMRvB7r z?Dus)IlDNIdmjs08=#tDCoWk#G8mGNBFH-bl*u{UG;x_Z{){EN*@sZ)LI!KLkNs= z$e$wiiSi8Vy1H=z(sLX(_&AC9!wGs~UaD~qJ=ZKw(dYZOg$F$F6kk@6I72nr6pWK2 zi(&%{dp!^z>IrHQT%SN5wTd0)l2|uP_dE=(`L@FO$aJlx^{70_GWyVYv-EylRa){j)n;JyQ%?8aY+x1hWw>ObOmkYyu{ zrTgyt&YnF88c#3uTK@=n_*O9hCRObNW*_nN*@tLkaqVo@Nrh{=t_(NqyY(9Madi*gSDymNha!n_RgfQ}Vgoi94 z>FxQTzC!b7FrH8Nvux9RqdMPOTh}$ERBJs&u@>@=$8k^`9mPWD&#gWGUO}EAi3m>O zfaP_h@W&-UFrXAX+@p;`*mW|TBL2+ymb|>W9S6=oAe^!D;_}r7>PgVXOx!FF>|Q<% zGh)BNco5`~qA28GNpSUc zNFKzm9`Y^)hWsbL&|=ZjZGUS0ed)}^m$qMk57W91+t}9!k?+F!89485evFkN z-q!(b|Yqrn8m8Zd4L{%t;ius|733_J9iq zdpOcq@!#mxMcg-NVV1RUX>b+B z*XueZI`cb~s{jqF>j=Rm8Q0^|QsxuLSURI%_ms+wZmh|*pgQ)~%()xp`?c#hZP(*u zc+OcO3N#TRGEcqCjCx$FY{tUcsHy3SC=!M^@OE`CgVu^S-Zoct%$ z-n);uiFh?t1I$S(MMckF7c`9nn@>%snUpTD0XDGs?~+M_(b>FtSw!y-P31mIw8z$) zyAh6~W8cENC(P1BqWo@}_B>1Q=ksxA6+N)uY?9oMFXFG_h!-E;gmb3JSRy_cdu(o6 z2l;1K2%{+_{?#IyG5=HjKh>*dgAUuAh(}&ABjoq{Z4SU5)91TM?JK=}R_RHfuKPpP zPtHGwBP#at-|5I4XTYkxSH!A)J)_?%p^EpRoDydoViG1{VAT6r24JIN6ei@=v6tbe z#^r9MaG(3IZQJYh6Iy<9t+qGWddJdiqx2_6n@BgSR-?6lK`O3=o4t396M*(>oE&3J z$yZRdioE^=?Rm35p%O}NJ|RYZKnNk<>oIsvIz6s$(GnaODVt#q8orBCYU%K+2n`HB zLYaqj_PQiwO2H%^-w3*ookvGXbQssSggSYrChl#Dj#T7_!S*4R@;~3A&UlTT;(RU9 zrQ>F>H-+5}!@FlMSIIz)0dG_RV!lm`{qRkY+t47+AM`xq9aeGEJL11)7k8g4c}dkd zsA(RYyXi=jj)ioz?!I~tm%m+TM|D_oyIiH;mmq0O@&$LLREZ;$AT;G{5*z) zIsXu7lGP8WKt`X{lqx@FJn@KK_x1L=eN7OL>sCSc(Z!zQEH$hECms7`Me0bAansoo zg%SrJhg|6&oYp<)w@>Y8Kg*BBV{&zsSFiU?eYw8?00960)Lq?rAwFH_tU*_ z!yJJ_G%-z=tLaRNif{mb$R9tvYk(L!k_)WZMs=&5u))g?bf~7G)`3E5T(S*sJtKuH z;H4C%iJ_L%S~p?>jK8Vu^6CHaaJ!CxXZrQ(e>-WRb=*l$=cq(CRJLvV{{B>~+>Wh_ zAMl;|0deU=_8;g^Q??eA<2^7Tn8o^!MQBF4t(z#Q{5!AQj~zxNVjDb3=RUs)tH)WD8-tJKQ)|4#^p;T;E2dc4U`*4@50*cI~evRJWL$`Q_~lfiNY!N^v$O=4W=VJNa846@ zSBVXdS6z?lgFqZUZWnq-0@0?{$|~kwpe6EWelR~?j8RAXuhWVbgQSU!!M)cH_!@sl zaqoBuT1&e`q}JNX`@Pc7%S95R=4-ZME2GnVYMjs7IOisz zg<_Ww2jm7+>eT2zmQoNLjGoAu{!igQa>$?GkBa6SR6xN>QA_;J@1b(k>XW{5=j_l{ z=}AJNJ}?|$?XrFv&X;F)hr%m6R5(kXkAL8AcJ(&0@B3_baoq_&v(;o zG(Uae996dt7WN12(F9Z>l%YzDw5!pMsxhK{!sjMcw^rYOrzO&u&(tBwY+Ku#ccE;e4fhYQJ#0Y7<$~eBonjB<{t}K3}f={!!8{ zet0XzFg``x+Jb(m?~D>x7D~qa;~ir1d3s$-hhXN55x%@vZmjdn(rKK(4d+K8J|qu^ zesdPym|f5Xormegls_bP&Y=)NpW4N^KCu4aOevj~1@U=Ah_}f6317+1fncOvffyfC zi%R7%TWKCSjLZw&r=Bd!!u&F`$J%d>$g%&W67y^ggpTybe`e=Ev>}6g>^xGQzx(G4 z)Ez@<42U)uS14!WY9&3_C#gJ*^cEUU;$KX_pbXusp8o-asfH5zYBu zw!fo1u|F5=YnD87qshOYa4LmUfkbi4om z#qmDakP#drHr-yHa?%7*U_eXs2an>_UAlt?Sf7W08=!Dduwr7l-fYua%tY1f>bcQ- zcW~#t{2I3P#aB5U;e&y{Qzz*!<8S0CE)m@NO@H{ zQe+G1OawBaXr2}V2@b;L!e9eOm~ zEPcVW^lrr%W!uG`UWR$5<#yzgzT5s|mct)CZrtVa#{5j!XxI7=eGv1QJbRx?n()l* zv%rU{syewb^Ew0hv1n|AZF1h1^ODabp6~rOY5pzdn3KeCuPqq)II^J1TgU{mQ#Ky= z5hoGh&65?9L$%m)q*7V@493UnvDR987VvC5tSw^Ng9CnZYmntxs412zgCh4dq)9%7h zF!8>^N9UDjfx*0z(Oq`Jh~Z&@)@N{l$%$Bv`8KsH!e2j-*kBu);3#dHSBH6ppVzYj z6h@kR7-OC(a5v*@Mrk--VCpmN`g|s~A_UKN?QtV+m*r89$EH&N9BOk^w_XJ6Z-M-t zj68-3{u+ZG^_MbO-z%kT_!xR#~ti~f0|yP233&}H5@ zNeoYD*4sD5ehH;N=4}l70OY_VtR)iXYuiUVyvkDaz-iszrVkzQ=J^e zg+w}@f3`b-Zw1X;wPOG?;Nvfb#NuYQ)6_4%>pkl!_eBfA%zml1!2RN33GJ_9@ zHp1%%x=3*=A*@NS4m9ZkCHMgiJF+0pf}g%gCN3KV`4&y2C_s2qUoqo+UWD-xyZ;)E z9*%9d0n4jD9%XEo-SF)e4H&ue#>e%1O5X$|8PpI zb$!NuW_FlH?XYK99;F|sOW)sMeDvLR2kS%T{cAq|yzINb4wz)M`00rdg1LZqEbuXJ zy;K>t8{EeWWR7~@wrwZty)167&3^|Od&p-de|QZz;c$r$28UU@frJW!#U0Nz#LOX| zY~3%b)4)1*9PNMXUE6NMFbKtI)&2kPR#CeL7IXrE7{^JPYUg1}tIoIBaKISf6`@2X z;q@(OXqg|gCZZv^#N>po$anspV+go;d=4H>LFv+aGWdsEE>mn9a46eK#tmy| zx8U|;;Ycp+{AA!Dw9SXb47&nbuUvg7J^dp$$=U;XrTU2DP(y8FV3_YJJ6Xlz0J=a$ zzj{=MyxW%QS(!qPLA^ZZt2xP$lY8rhdc^v7JLC#NnpOm}yPITQE3SF_kIm)dGne}meU{*s69kSE*6Kh}d5XgzMMdJ)Rr zQS|RDSbgVak~p+o8rymDdpa^LAKO%UyuR$b#f%7SJT4yau7t@@Q?*0Wk8f3oc?kih}#B6xAv5`CUt+Z!rz zkMi>inwkGu7|y#H@*f1gAQYsYbUl4)W&O7zURH(78?tN3rm$LcRKe2}oon_3c*xod zmYrgI)Zd_yp8WYVLz3ee$^@Du%rH;ZE9^o7IFx?ug%d@Y%zT3Q4e!Tl&=?1-_kcfB z-ae|A55C^ay)RcUr%L%=WaAv-ec|o)vdUau$(QQ+yzO1zT$w=}NLkvy^UA^GL0Cdt ztLop2YoE4NY|HU^vSI?tJm-gEd^_qPsCUtxT8#_ZiSc?o;aqBM$J4T-c;05==@)b! z(!}~+{tY%#$cOvuFnSX?e4F1a+uy(+q6&`~^{|SJCh9uLy@~x^2%J zPvtUK$=-^e7O%rPG&nJUBLp(I#UC1gMi|GSj6c(-x-WxC_PjjqfBM7P``vFRy0Jbk z!dy8a5q_CJ`?L@PvcNFx+;Tylg|<{!*to!l1znoiAUHGKwF42i+D>(tfgd^&QC<1T z1#a}Qh1o;#T5Tb9c^t*|agoW*{Y9~9QXe+hFx0y!4t&`V|NQ)*(a91x!;Q0u=|df< z|0}?mz<#A&Wz18%`e`TLT>yKn)S*1`U)wZWZ`nP|fqLx3^ewPQkzX~zJ}>A`@opbn zyMe&9N6~XRc2z>$i~C`odK2&{SLNUDE@p+^>cER~&d5Jwt!?~DV1a&i`7Dg1{b3z% zkVWR_qRKoetFZ>+mbb@&SnuKOLD*>Ggz8f_D7izelC@hv;L6qnwd zE)iTsM-b>Ii)t8ISW_>tqJUe2FEF4}n{Mbq6e$f^l*E zNR~f~b3R4PCk_}}N?Dat__zJrQx!H-+S-}^GyIQlKtT_y-rS>RsTPYS`LF}Aj2PZ3 z`z?~Ef;X~(gUMET9xS#CkqTu)1#r=Is27&ZvEJ5nnzWDR_4@7dIm`pQ^1JUbevm(< zr3hug{GGM8HGKp9qr1i>Bm}@zzKan>gJk}Bp+Dte_-zuMvh^w?k!O{M2mMTmleYJO zkBcXaP&4}*%rL)R@9lOg`|01_SN$@n<%<}!o+pXnUY1WVUe@UxisTj(NEA6gc>L08 zet+1;3+6?g`fv{sS9c1WKZ1V&u=2+%%s=-|b2kybNa!E2AC%QRA$R;C^67%v^&`Jt zvwjr&({~eFf9%b{3#2d!V8aIHAI};x)<4XYf&_hvf5*MLhmL)IR7$zuZf96Av*UOcy?X;|Hf|{ZS?J=aE8%|4)rZ44O_5!{ zjV~f|6WJ0 z@q7sNb2Ia)C#-n$VvBnX;u%}sl2tIPpKjHYMEhrNBl_Pmr{}KfTGyPF(|vC@!it=3 zje)=L{ZVqhnI+lRr-t&I%wG_cq%FaE(AO8;$K|#+#((Tvl*j7Nh1nOOtlv@69;#MW z^WGixD*aT0lH$`J+yE&k@5-afR5(%^vThexmf5;zM2@7l&~N^`w7v z^JCk%A5uik`q@MK#R3ZIF{}R{00960)Lq@0+#m?WN&5Z|yq(YsJM;uOL`|~Ua?x)# zO%N3iApWdvH72Y}TgJ2_f`DQ?ojtC8C+>A?zZ#w6peHmaorrfuv`>2Yw{ArJcUfLv zUthYP3tQLqt($&s@+zg6Vx2L%NY-l#uCS`w1f2D6U4wh~+K!$L2@`laO|{&5di@Jd z?qS6rE^zPk>cXYBxsq!W^9UI4(if21HWG!bRU)dXw?4O5ffFb0Q7%Bv0TWpHloPJt=>3#wWZ3;qDSgzZs zX9~H&1#RuP!0PmJYofL@Fx8pJ|CUfs`^mx zb$N9hf4IR(u_oSy_VJK9@x0nil*;v5Cm%*QWCX?wF02MD>tQc+*rV<@eRO)syYd>|mmY2tnqG{JO}`#{`w2oqdi%dq)#{ zs`aqj^2rUC8kgOC(+-n!j*sIo!H~XB5*zEfR>SQaxd}S-8wI*=G(L6sBS$LQ>Inju z?9I9%%oZ(o_)#=!@3cAKK#xMjoW9xaTt#f2=PGv>H`!Y&r{6MUr+oERReD?y% zLvkj@8WZz|CaOYyL~17zwgpJ`I2q=n8K3w2U6YvBjMw%rix-&Ri+Mx)N${`mQYgvxlF}Joh~S|o1@)D z$Hhba&hYsuJ!I<~Xr73(n$w3?9@$$u1AO*L=+85}4H0He)LeeuCuIr*+GrW`IPL{o zg{S2l>KE!i43_R>cIFIUGecZA`QXO04K4@6Ptd-1f~Nx$YYMgw#Bnn{Ve66DxM1&N zmC#Q}s=(?M`m4;(JnYA|J)LuM?Ra7K1((X$;60T5JpSBGh*UU6c>dkTUmtB5tFMy$ zjvYLN5;`Z={kVieHIox4_x^2qnh)|Gzt{ zRnG&Jvkd_y#!iQ)85;uYX zI6dqW4bd-ZfFhMr@+*RcLv5MguyJ|F@1qm9F~czAoQHXs=b4|HD-`^1^rQz1etv$C z7$NEPeC3?Sag;p#`FwJfBs9N8r_)eUz23zLwgGd1nNLTq$T2kd?-_$awL-k_PV|7H zA?y%4c7Rp)Z}j-I50PnavSs0LlKa-t(z}l6s>VGEtaqsFINN>nTk^1Mkl^FXi~T~2 zMNiSNzSin=I3C5DR6X}RAF%LEz*2D#1zvuU0AuL4qY2toi=L{g>cMToQ$=?%I&^3| z9|l!t4vim%;q`hga1QsnRfMbK*DXzw0Smm+@G&^#jQBy(3#ti8^CJ5CqWKejkY4Q0G-d@T%M+0tO-m2F%kp1N%%kG7UMC^S9{$uKc5wCa( z=W%ea3;%HB7K4+*l%2O5Qm`XPTvJLnZ5TB3-|~Z2{v}5!(YE(?(Us`=X`kN-=X;@O z0PV{hy=K99JRZ{E-e6C9(b+tYXja<{=8Z-$JdPv#aWvP>yIEQ>r4UT}w_+L^+-aX@ zk?V!!)8Pp|xl5p5Vj?u1@)W<`jiJHzcL#S_kxXAQz80*w>u$U!>kQ4{=TqmQZ=7=- z5Id4l(1`?x=H~|Y1zzkSqGee){y)rTlQO3#Ew-P*Rq5nHqD06XGv{#(;r%P1^UC-0 z2K|MuSGUQ@Nobzdq7#!ZOrxU9%_1$k@)8$W_96NpR($R^MpWr6=4^{UB@az<#0iHS za3T*GT>|=wc9$0ai!K~7%SA&Baw&vYH;nSdBA%(*%q~#1fp{f^5px-;%FlkK&`KBg z{w*75`L*Z9u)SeU>)7tvlgN1jRrg@&lB?&}D&U~&fgJ>LR z=Og8jv}~EbB&8D07j~648!o!Qitv9M!mf8opeVCpvyO1XUvxBaXy|&`b1PqvUyHc6 ziZ|^KsA53JbOvwQGO{ku6$QawJg>Y8h{X^V1BplpN*TBzc!xS$b9VRd1x(XKs*=C1 ztE0WxpCsPoRwBucpXH#UwnaI-3*{L#B`VL~rWaq>;7+wZ2Xld3k-M&>*1B7Ddj@U5 zE&EfYu%lsd`atUYcka8;Nb{9==KQ*tCZ!XLEPcd!vi8e|{{4(4OtpN<>I1Rt9)@j% zd6Td&?FQ{+ihUf?x8x(^o!#nz7i_fwFS1glnCvOT89Ke1CidzyC0BZo%>!t5s zPh!+^NPB_5u3rs+Vs^*;_kpDs(Rr};NEjYmiwDqz5@hj(p|ftR^#h0Vam|fG{%Ec` z_1h>tRJGd%UZ2Qf&VtD}`1U&Ro_=BbKL7v#|NpFA$(G|N5CkE~?l*rsbC^$Ww}fC0 zS)_v`1KIBlCs{=y$R%=Ni~s)fx7&~$Q-_mS^7A~q9RM0^?E9_>U%iL7ltPcTCMD-X z=2s+gkV%(P%CBF4sWW6EoDm&jjA5ApB_rHeQVhD#b6wZi)=Mpmzwq&@ouVQeG-H)> zuI+>yC6vu9Uu5U#dUMjM`L2;dgmPWWg8XGyjc9AeA*1>LSDj)vFc*XWzO1R%D!i_c zyTLP-0%Z2h0FlmacT${90K4OItq!B}MNaysa@95x=}6~^xo;N+#adjt)jlckrf2fy zne|_LjvSGn0tGS_d5|}5J30SsoCr- zN=ZIFnaHI22q##C35-BHOFQ^PP(tx@J}y%j9S|7t=eBJw-(@x;G|yh289pp+VUwot zqVeQDD|nW90RFN7<958JNQQm1N31`r9riD}+T(5M`aG|pn~qUOt@5ltWm-ro;2ClO zbb(Ezo#(l(s~)nb`{mYkJ&q%^70JhO2(q#9-o7{EI*tRKoY0oSe7^C|;QwHc{QfX| z%I(Pe+#RhM`^6BUhY@s|l}$&^!LzeU2czBW#ApRc?9W7rKKIwL|FP{S49zMbk|W(B zlmK>zZRBJA&%Wr^uM_{oZNKzE%R4#Pv@C*uJ|Pa%U%?-B9cxLYB%A?($MEm6n-&pyb-yYo3Kvqz!NcP)4EQ&-Uv5-#VszLlzh1K z!T&;X#k7rnLalY%Hq1xGmfd1`Ep$=vL2sZn?*p@U#hiCBQ5#pCI_7V~=)T zo7l}JpP~1unEon08~<%`u!4>vps0|ziPbj?$KTr2pU^C$Uf1>h@tsPdEffy^#cNXT^Uu>LT9!3pU2!1R=x{rA43 z(7-{o$&Is^eUURIMGLgGz~hlpvKueN`1U8UY>$U4{}h)9-PY#tM~J(x>tcQ#);Dy( zuul8`I*!_xzS-}7Sw9k-k6(^!S^T_HNQC}Z=W!`J7#?aXrk{+z5&~2w9{KK| zKvweLhlpCSg`sMWwLdbn7nzUHagF$_O^ND-seID@xAhDro?`T5h3UJI6MbOvA7iI< zw{|L}O}mZp!vA%nCZmEIzoY+Z`Z>XWH@;(h{Fc89@ldooqg>$w=$GF<8D{mPxtD%Ll1>$QfhkQQKwRcS3wEv;c zH@;pk7YEMsR068KK=PJ8pU>huW=|O&Qv6}_Wl$eg?>_(l0RR8gUE6NtAPj}5yZ`^W zl|~Btz;O29TY!*`dLF7wN{nNSZ5%Gs+kQh=M9+tRVtqP}!<(o*ML*~K{r!#W+9b7D zZ2;z^UYxrRW6U#$rv$|codT2kK!MB5I{3I=tu8RoBD~WCXIRuh;8nV_m-R-V1!PP7ln|(Y6$QuD^JFVa-a6KP6l& z9Ps7DAOSC+;ha=z?U-{GTi6QmUIOw*pr8{vQ>cSUmcKa~S+?7rKiZ{5oI!vO(v5Oi zBl35JatG|xYOzZ>u+d=Cfv;kqpIWwJ@y&bG4`A;g?CYyu2g*Ea|2;hIPqqG(mbHwF zC9*AhS(*YSBCt_SR@f#S!5!z7Qo{DepkJ(`mQA_E1>W+fpJzL+Yk^N#V2qK1Y{)nu zPZlF<0vd%ahG)!2=<5P(1n{?gPH4j!`rPZ$G4BU)<{Gj!9=W8+a)9)N&JR0HvsCv8uJcFpPu=y1xTsBHCpu(8rMa2%f8 za?k2`PyYzUjlbzQe*W#2<3kU1!A7D$Jz4QHfC9;i0Ro1(@PZ37>F0h2ToFSKk{v0p zYxnF}_WVvCsR}wA_o7BK9+<^JCnm!|1o8Hu^gOxg01WX!{TVFaOuZbqO~>E&q|G%s z>VOH=FRqE`o0odxwU?VXp4@TV^EooU$Unxo(K!1Fi|DiB!R>zMX^1!qYmK~j2zry*uf6v2T89Tdu*OO02?(0` z$%R&UTK_$M&UW@%A{T%uQznz*UpmInPwDbOVK@|BDYiAi+IVg8f|vc2kr_eh6Cl47 zUVkb5aJXJ@TZ={qokH5Bbz>ZV`iT+xS^yujQS!Y^eX?G&imJ(HKR-1dKf)pjn%@1Y z=vv{u4N5#wUr44|Vpqu1>5sYmOaLS4}#eo!`}kO;UjzJbQTbQ#~+ORYX>o zY;#_sy9o1X+vB%OI!9241oXP)rv*v9O@ORTm>^D;imny+oU%oJF-PkESee=K* z4LK56md~uJ2ubqvS={Gj+7uf)w(<0T78sYM76YG4CnhB&0mQwvKb9V|^B)kF)b4z? z4U&R|Sa+EJe{+gT2($S-zxgRV6tbGSF^=)ty^=Y1pMXV4{nX$%S5!SdzF2@D7>{?j zf3c57XT-l^Iq*hx(9&T3Qowv5|6Q;{7aP~J1sL2w>#>Jhmd@oAgzrb&|-L`7Q= zjF;p5u&@IrOQoeyik01Z6kaQ^9p;OF00030|ID4+lH?!=hSBMH|M%VMiF;wmd;u|< zxLwP|R61h}BK#onusoXL$`#%ecvkPUmKxw4UP|fb=QIIP-@;e(;x^D5GC(uaqOKF| zdU5`wU`r{l*LSz_!NmQ@d3SL=d1ute!3@E!OPm(Ni%1TU+{_5-SDvd4*aT`^-rb%0Gf5FHeI?OzKXoUn z_xoK>crfm#lu}c#Ot7+-{qR7i&da%XYNA$}k}Ll1as#?>s{TypRj|_Q_buKa{)tFOpd7b{L~sIDgVkuR(HVv7BXJ%UM1x`o|g$Q(f_hogxmS7 zy(+^9hrQb>Ey$c{h(OO14#FnU zJTawOgL+A2@25eN8GBxi7b3Zt`;|D?T!srx53EY%BP`FLV!)narnEtyaTZi0vrtN$ za!%?=6u(8~Bm9iwgvjs6*&Jj7AG&^UOeSC!z`J0zWI2z;vM@FU zsfS^H5<5<@zf@z%9-Xy9#29Z4JnB;ss|Pj+AaQo`=l#xe(!5Q<*%<7NE+hg(eq7DGr-& zpsRMl39laQqw*S@Xnc}`lL`jJSLpS-og9+eNrq!$%Yjhj!yO%P#5PzoLsHFRa;zwVxFba4%g+modtOw23O)bg0%Xb{RqYdGp&f4 zHWNRX__=oX(RTDm=UsJ<<9NL~6P`XmG;o^yF1ju1G8ZRP!o1-3(1*089u9MsOvw{N zDdRFCJE9C#KI-~w12xs(eQD0oc%k!IDy8%XCx;94e^rtP7F}?DLR8D89E_K#naP5+ zOf329URy(=?_b)dI>CJ)Ou0LbGaPPF?@H`DwmtHvs}qQKQ6!(+qVPDgio;R-u*7H1 zoz3QQ+bGaKdpXXH-rkKCo>Nq9q$d$I3vcgG?QT)L+;{#KwX#TgNJ(Y7XSeN|HNI%mg67{6wFNj{|~pBgP)b6w6K_d zty4lU5n4)OG5lTSNfnF%NqwyK+aEVN>;@j3WVxHw1C3m?O4?s#$tK^D8e$Ysu?5l! zqS6IBYkhv^7JvmLLmkmXSvT0plhWaaD*2f;iHINNSqom77!kLcIvw_hn(4?5a_PS3*BaM}!_5Jcx%&_XL3=c>P?p z+@%7VWY<6c2)NWSi+2Jjaf?#bc673!o!cmkz>EAxdOzjAns~MTCbdEVK;f%u@fYDYvHboD3PNRRe!a9e$l;?XIx62=lMw*=oxpO8_m z#(o`NA$M1>E6|p)gVNA7PBGJ$QGcmqkCUIq2l5V;zg-B?9--;lukKTX6=zLU043<= zGAp+VmnEU^Z2Tj}7o{jaiMkxgA4_nYyt)vA;Rf4ZYD9VsqQB#b*ZLROBlXkTpJC?G zDxOG>%!K($GqYfBe{Idko@exnE_03YYB6$fyNp?c0Io)1I_Gnqa(|CVIUho3elna3 zK{-DWd~v^eGuB5UJkdOv0$FZXR=;=FU7vH8ujjJhQxkAQn3|+eZohPbQKn^1Hmg`$0S$ zlOXOy?a+hD`DHdt#oK6JAdezBkUJ!PI^aJTPp!5S5!S~ptj6)!-q;=nDqdCn;(TLL zEh@(>==slMXp_e^@dPV=zW2%=AS88Px6?T{NXfYk+%}fc2t-)!MxMejVNhM3#oB5k7caQ&DTgs*QI7w$#i)RQmYje#mV~@>206k7r&W0{;g9 z0RR8gU0t)IAPfaNo%a9#+D=#NK2Xmd5`qEodN&VuELSn|k(>k)#+-*0w)~^4@X|Nm zV)H^;$X$e~WSVXe#Jph?J9Wh8b@_P;^r47kKRPK&?U0XeEv;6EBjezE>yllw*8v4Q zq}jlBvGfyb-$GC^y3{QTb`FuVF5ZAc;2nqgC zIph+nfZg|M`S5r=mSvge8L4rw|E!5mYoi__N{7g8t&c`gs+n7r!zBE26&WD#V4_xr zV{YIvuuIpBYSIbRJ)f=U^?D&Z6q|%9fk2l0zg%EC$q;?w?&y1B4^C6BGJngiW`Z-Gpy|5 z+fTLYEfS&z>zcuBIU*2|he3xFEdr+`=ac@$c=iPTwaz;&pDj7|$>r)ly_5SHabYb) zS?|4;taj7oyi?Fqa}g&eyO`hAZQWQ48|i|Z_xrC#yQYJmVtL~%z?xw{UZ}U8_v@s~;dD(S4TYjxkIBnGUuOuMgy<%{4Y3r)gT2az;HE zdgA_8oS9CTWba(0OoWUN;p_mzaDe;_bnhUBEC1L0{ZMi;<{Yj(Ay*Ss>>9p5#`tHD zpGsux;*nguA33@4)aJ2l>m99a0kb(82kUW`pGV*>)M=H6Qmb~*JkROC1S}U$)x-yw zp$82~OU|4As76zzu1Bov-v^ zO~fU_D#xtEEO@`)AzuyocAT;P6{u&KXKS3d;#dvLz9pW|_L26q$2_hqTp^%}Ols=m z$C5LxpXtXBX29FDAHc>JmYrKCZC{M)N2}(#oR385XZ-{l-3}?7lIr>>myUw1S!=LXI(G zsVNvy1Ir!U*sx2w*?}HW!c+S%00030|GZtncI+SsMLTEy|9iWLZ{dVqflJid$6`*B zQbmLd8l%fQxaUZreWqryy3jnFTdem^QP`w@y}IC-wKqv{eM^&G#BvOLo8V^#HX0p0 zgw4p0B4NF#OzbIqL##T)9K~S7DaSL}p#i`$T_7K)hguAfBL8ujUF2m#*vMahkgI+de`?OOw%Y zyZ{Z(dJBVr$uRVGJIW@6#`8b@<+@LM)GesX)>;9E14%gzzIy7-+(^WkDH^j$px(Hx z`DOTk7S-Hq&Uw1rCW6;^zKp@`)d?L;XfPhF%E`z_xBdh@%jk{CX;jhfZEJ=5wI>WW z6&AJ2_^nI5H%@!BpGne%qyom46tar{jQ$!Q)LKlVE)r)^Dgo!Zh*T9$#xQv~lV?f( z3wB(?C*cAqtfdR4ZC_3FaWYp0&;`U^Z;4-r`bQ1dTFt|GLVv;AjdEgtuhkdc#qMzj zuRRzdE#V2nbAj$alUT(8Upu^&um9%$NKlA*^ zz)%ILFKDRli*xileBF{%=dUvq1=S({HGc1|C3Ju9f~mnL)JWW{u+wLOZ^=&0c%fj| zxF_6FIZSUlhwx}=XNgwC?bCS8V?6Tsyb*<06;eok$Y@ob@9%HzsRG9ewec;c7H))@ zksqf55ipkshn9$A=2{tY92VzyjPS3B&t4d0^KnPWM4lH+i&ch=Fs*dKC$$Ke#(LY+ zNRa7`J;zY%72?SV6E;~pI?;y7k<{KU*jXG&OE%)Mb|v|P#|KG1xJtXpu{gU|cuk#ff`_Yhdw9{D{U z7Fc|SGuz5(^21zO)}f&!D7LZfNn&v=uUCAeyW_0f;p1kb^JXEP!mIcD4MP3wSoHe) z1tQ_|)%P!*LXGWpG!ylg<>*FZ2ITufYEP_x8`uxtCVr&9STbe^*hbz=HeRrTb?Vq9 z-u?+uQ`bZVTAeJwYOoO`>OtJp!KeAKvpz~#$DO3LfnRRy7Dg-OUv6(oMx>-1rtPE` zx&}1rnY_aM5(ZS6(C6sd)PLD?19TquhI|Yn5&kCn3C9ECU@%gUv7|8H?10Iujj8g66?f8C5#30NT=?e}l=d9jJlt1HN{SzZbYpqu1FQ+7p z$z%KH`p~#OkEc1q4B^gVI5xyi(c5H@=q;_?^X(FyqZcW1q7!nV5jJ zv-OZ+y-V^_eljhBvOoh51nRE)x;FOg4~hMa==b zpN{e*)QQe))U(QyR~^X>JZpKTZ?fie#iH=A+V-n9lPf7Big2lv*MYCB=dHDm{@+38 zCP=`P+amw^v!67k43hgcP6{#Q~R| z&nM>pXEqW=lq@i?h?GjJ7)@SuU`32a@*?Z_V8WeB7b zdED*ebPiYTDhRlB$8}T=13oMcjAMa6diU|M65tks4kYEz;(t=km*T_bU3F&zqj;c= zxXQieQl)^7{d%3y-IdnWIP&PqP1&6*U?}R>_rs_n|0JSF{=CZ&BYHt@Tmt7zHuTjN zJKiJM5vZ)=8$@!PVZ^6fel)}YChAibT+8mCRC*OBD#y)_`jJmCEu_y;`Q60MRF1W$ z5w6;b6elPI8pS{5oqpGN%&B_Q@+sTZNeP8!V@WggXu5xbw3J&nL z{uhYdbTS7cHmmMzIg#8rmrcWOqsSgbfjstI8CY&~Epk@NYENAumd~d->4EViSs<~# z!9qhK9AkY34|(Act{yUA3%5A7(aE)JcY08cf+J3_vXxbP4Y^@08T|4J{HOS-=OY zZ!Y1+E#|z^WKG4&tsD-kh-ht`DvIPhi$9UQh!~6f#v1gO-Ri+&WHxe9u-H}X-6geO zr;Lj6Q+DS%G4hCPWrCLbQ7)dBG1}=4ZH$F2C|~u08Y5QDd0cBs4zqumqC_!xse+k_ z@V1PTmvTbe?eo!-D$a~d(G!`u*FAI~xQfe-(TZxEnO{3DYOrqg9kaVTh^6QHKd zo%SQDCnd*jXi#0ojz^zA;DF!RV8$Z5j|F)4>!xaCVgtl}OQ8t!wr#C7K4^?dfmrcW zn)6%Wud4rYzeJqNC+=O8bR_@B<536(|5vvpy$I(mEzj=q<|oXc`zpPcB}mm;dpsU) z94P`K>qx&6v0n-X3JGTc=%)M!yM7^=tyVGIFy;HGe?6nr{;LU!7kOwGX?CMwS(>M) z=T#f7IPI3_wQ`_-%;XvyFcXFFzX$QdVn9_n{OkuN^Sjpk`GSHSFc9hgY^!;FSmj!yz`7J}H( zeCjR{Mf}&$KR2Z_syeSe{YT07~SrQ&sdFUzskqAtJWHlK&m`6kl>9Ux$^KPJ@$fJ*XTyOkgOMM zaK@$G}00960)LqebtRM^os=NLFzwMq?`jBPr z5D0>c?QI@aF1SBp4_k0?7;~Mw<)CBiPVRYCnk@I!^g?j|6 z=}oxkab$hUuE3e3`*>pgVc=Wo5v3@-A67>R{OjxM#OMw=H`#%N#(Sz`d9!H*_{s#!rS0XifENi+>A$IOhWzKNp~{(*1syHsG9-H4odi zNwm(YudCtzXiUMx|EU3mvi*eoJ}!925v9amA&6IS#-&uDhCRhAE>AcZB8Ua80=C21 z{)xqZqyM5YGxPma;!k|zT&j`*mM6FNJ*}bTk$=2?_IGxB;rxjS{Q(c||y1 zoI488=MxEsY*gj2)0zjir;$dvp2C-9L5;?9br-IFzfmZTCP%+``FpgJ(1~t)2w5fW zF=Cf^64F`}P*z_Ao9kPnRV7nyIqpGmKXY{E3F^dB2#O*4 z>g+MlL`P21?RHZwR<5ywnvzfHv$=%x7U$|BQqZuUEF4o|K4sR2zShYGiZ1^Pf2p)P zs6U8#Tg(&Wq1BDd^T*`en9p^jm0?n@p!Nw;?sCg>f1k# zYt!j|3bJ0m2u?wk|Bqcr6$3J81)#+uKA`%=i8<*iF+QmHNtMsPLgGhZdF`PeW#ND? zCbS?cM_Py}q34z-^nm1~6c(@OR~F2da&GITpRR8I)_0V{Ec^pZs!Wy^q`X-^VEwG} z$wp8pgdih#VGlp6_QL1kQ)Qk1Lt=O6k9K6md5Np+0pfxK?5>8xo)QWfY)4&sIr`k? zE=NPu>$)NYnnB7?sYVeo<#>S^Y1Qp{9B$9JV6pRs!cQ=6owT+Zc<3nSKzg6Vh3@xz z_2I|k5fb6W7~^`oi7*}QZqOKaH*miC{QG#@R&TXqdhfS=UzUZvFJGJIJ#>()dG_{r zZI=Jm|02V(%l&7GhoGOj*8-%j@Zfafc|-ODW|38qL+jQFAtB${5f`%rILj2`WI30& z+tKe=CDU11ewRnGY*lT1F#RsPo3)%t^LH4g#XM^2#`U6#R*a!ISseKJ`RTovooj@i z&*$^`T+?_5wXUi|CecRy^O8xvUoB{&qsDcCa4dWJW1&JtbAj;?XGV)V?9R4buKV-W z>(+S6@{7u%r#tzocPq!$qL||9{PS>Lm~o6zi>LL6m}fL_B>%Zms+s_UpRo@@0!r+X zPf~fY>+@Xb^G*HgIL<#qoC00960tex4GoH*ySatX$pUfRLRx0ifRJ89M(=$4A z_z;%r4gJS)*iSTuFXWR1Kovy*yVI4Q?}3+vm3G~c9^#lMR9U%s-Mm8fY^Yy@4I!kIL~p2d%k_pB;*Wm#)yd}p@}|wL<1$U9 z`FN0O>2`dYTKSxK$!b7TO3Sk7_%h$0eF}+|(G;#(Iw>F`kV9!JHL*?Oll`JF2FbG& zdRkKDf!w>{RwUZ_Y9Xm#m+OaObjq|Yv6@b&rJw36;v0RU)ZWl(wFLDi`rQdvb&v=T z=j%}omA9uS{(oIBqQ8|}tFc3a4;|hRdnErww_z!T^daHW0q9A*zchg-`&ZPI3Zb*( zBNjxi64e#|1fyfE)8Y6jj%`b)CcxZ&x4aETZ;1T2{dL_%tH&5s zEW7l_ityb&qWyT19M%E7T#;TS{+or?jUcn=@?l-q*u$S8{M3MoqEl~T9-u%ooC<(N z8s&BSd3O2Z0+*H{UAsSly&!zD*Bg%AD`;I@2YpaFoBpZWU#6zVQ_Xhn>yu?!#F;8r zkI(VPk$pp_YY7T^q>$b5u#|#Us$O}kOCt~$69B9qy73UJ=dA$0UVnAzRDP{GbhIj0HGtBir@ozho>k7>J|chrX(N3|@~_SHcLTP(rT+eR(1)aF z4(LCDT~m2W^@@aCzsU4xzQiBGb@mmOIkCFrf?bzo$vMB@Zz|YQPs+&;@p&+XZrXu1 z(apT{Kz=lSN{lg>GjA5!soch^t)v7G$ur^h3^>Q)eGmJ1zaNa8-1z&y>SyZj-b?-ksR*%CR-|R=$zD_3 z=IQ==dd!08C;SsCesJ=0udfukq?80FNMYg)J>T;|FL&1%;4lot2OEO6o&w>2Y6aq5 z1UIOZi|E976c9%1n64dcx2|5wCc$Zq_#fb?7N_NU;HqtV{ZdN2#%-n=pLBGpIkPQP z=-A@zZ|HZj*QKB2lc3RSp1b}?sCvwfF9$hdbtr6##{!sQj?>5M^woBMHs+Oni33Rg zY~n~K_|fw?cJ*zdxD&?}^A!SVx}4UcyY93uYR5~xgkCxjQT9(m z&%dVe$u1Po^XR9KV6k&;M_tA}<4B)y;!Zof zn)0v|HzvOzgTMBAy|!)B@Q6f2Z@#ecbiF3fKe#Tp`!|3*cYn_{d6&#p_q4y(b)Dx~ z?x&YJt7)3%d49j&iXU{pN6t49?jpWXQ~T)bIIa7ybyi;ALO#oWvDVrV^1m=oM_>MY zC|86_$xk79Ao-z2`|-xUcX3XJyv%E!35SFy`M9UJT?e$p6h5Fx>yl0ACYZ7!qLcJb zsfRNi3Q7>)Cb^=vpJzA!i1{z0uPpxwe?HyU6ko~(>Z~&GA3QmvCm&>&yLo)tr&=Ep z3~n!fa&Q9tN)unb`bSUY9QUab?0`+TKjF#Al+f4*y1<3gp#D(OI^j?6t>#rAz zk(_)*W!;a~Ro8N|`}cOq2+e%|0{{U3|I}UEvfCgGgd{Wl|L;BHxDS-=S~mnCNxKi3 z6OMxf2;GqF2Rv`=$r1{d=nh~LQYh(@G+u|SSIE8{ zr+NwkbITLXE+ce@*R8i+O=D^mGYkyCkJ7xaz8XyQ56f*{;8F4B%>!PkEF5u<7LOM# z0avKBF7)P+<2dSFhUIGl#!rDY*%N3EC=5muo_35UhJ1zzEOTOOFYMz~DfDS(IK%bw z{>w95au3olS9#XQnw3uvp8kyG&E$vYu;yNT`MO$T4a3y6-r(Ri4^HG-nWxy`7R2A?R?uU(wYLxsmi^Xi*-;+R)aGmgD?eT>PQv4y1t$n< zuQX~2){{_H_kvCBqHSONl(;l?MIH!dsUB%s?~0CnW?is~HD+3Z`pk z&RZi4964}1 zYo54&_G#f!n7uJM{V#LV&GK_noo4r-b6jGhrvcX`7Pej zhN<4~wWl%p1Ul)y8a;wE-M8um2RX=g6$f+ z1ZETmxqaOa0rR@W?BAW|N$RuLqkvDSm#SXs6??f!IUmaZaV@NbobQSkX7?k0C0ckk zSgwX$3He7pmMfngk4M>baOLI01(xNU?`AKQ@A}su^y;&}T=c62#*5o?-pIpfAjd{7M3f|-wx=C-r66#mQpAyG;(~z z)kK3rxtX8TIt7N5hj7F0yIhvLqAnx_cMHe=|+P z(Ej3PP8P^hmBV5!Hp+?MGnU)tN5PJ_6UHFVvlrT3T=R1@ymO@+J;5>4zo+Me5j7o- zpt$x5m5krTezo8&7V=pH^DGz>MD>5gBGzlbqWh1zS{~7C=P@ldB4$t{7D&s+P_E2& zuTH@0Gq7vsnsTWn>!pCzDR}y4jYQtl!*(lb> zY9`~a4Bb_hHy|%R$#q#^0265LQ~n$p>jh43)`LwK7DYU0NtjWSPgDQ!o9=)z@3(m1 zQr$Ybd#$MVCBCApOziS!X5pQi%u+Y4L%j4~gyxFfu-Y@vD7?;(!aKk4&yQC4AFhs& zpY5xFEuah2+vjY3h?uc&nS+n*yII8Ndc`?+7-D(6jV=d(%ckGNZvX%Q|Nqoo*>dC{ z3>41s|DT)MY?*x^?leLz8xNDp>S4;`@n8X>bpYZOuCHC*F%wD;b|12YwH;T5f=%D} zmFlYSdLcPSuIO-cl{p`uOHT8VZ_w=&KW=_$HB9W8%eyd8Ga&d*JrQ1!wq#sL^UZ-kkU>MJ;K zrQaDgM|1y5nWt5FDkZpzegwm9A$wc(UTEiEvcTQ04Y83N4!G@DpjkX;dBY&uwymA2 z;TX6v5ZsI-%Ny&Ca?CpX5gQc{3uB#s1S zNNEt@hO^IS84erD-DJ@(1~r|z88B}20ItJ@vk zxkxe`L#{WQ!;$9D&~^=Q?NjqakcOJ+ndbn zQYngR{Zyi>Lh@eKdQNZRf_FXfMV^7iv2+7no1NLL&}L_1ofcZ4UAr}T1E1fi2XWNE z=jZ49`+JG}tXb)D|KhKqesOvq)p@o8QsplPE{DVFF=eMEfD-DX22Ds5$6u%T#Q18W z#hb6#sKZNHMRqEc&c;QtxpTw~6>4Yq>e4T550%;}LDjN#QEPoa78bkbl^t>eB^6%9 z<*TDe=O<$0AM^0Rw?D<DBmV-{5kFb_48A4GE^MT>Y9GI4rN*^m{>M1d*ND*beIeeec$#WwWY&je zg_*VRdDnfY7sm~3fEWI?8FH0QqG0VAzSQ~!Vf-YUg?2=qw{=I!pZbX-pBo)!Qs*P9 z_oxhE8Axe3PG_~9npd)3Tv5Ink`m{&pI(mL+89ZNAAUZ4~$>%qYF+&^17ZQOP#jf3|$J4=ngH%yUkFRDGM+_jLez{1mL)-~b@r2J2e@^Em9d4-j zkD~23TcgnG_T2dbd;Gad2dRFSN4+niweu!Gr?p0iW&YiC`-kJy>4iesRi?(Zn!ivd zeZ9QgbahRP{WAC+Q~axTZa3VorsIV7D#f4Id0s+eyZtK4{Wb0{w($~ru)h0nvLcR5 zoGmJ(e*gdg|NpdI-FoaG2-Ix9zW@7nPdpcH=r}MK(}atDZfX!w2KG=3uCT$hN@Lm9m!t;9?Iq z_)d`&vRYqk7i?&i->zaOpz*Kd_JY|^17s%jQ^|k6-4&~T8%__G?MhZ_%>v3f{tm5K z#>q`Dz$$L6lETkveP`5t4YL zo|0ei%NtAKd3kt@q~a6Q&(v8XHv_a!-CZl+%8Z|f{5 zy#N|F(sEbS3n3-aLp>t8eLTEmwOG{Qe%wRaS}Xd7D4$OH|EeCmzrGi*JU8l@7Gf1= zdY%tD(=vYGL8hU~RpkFmwqp--J_N;~B)*jJd376Q>Ntu)U$AYloEv8n04yETQ--J+G2_QT5NSudn{i z^LE^E++c5(k9m}y8;pR88;?*#f!WH~8~cnFZHT$isFj>ay~2e0nUq`fY*iii0yZ7j zDgIOWE!#&1x1s8ma)0e>vB^%#KP8o)+Pwe@Ez#5dWm+zK*hM}&e9LNWoopa`ntcEK zBt*8P$!z;|Z(00g$dkCkL*nG>^Hox~)L_Kwr|$xJQahrsA#pTy3?NN5HGZ@^h$_qu zh0vWF9mNR*LFeUHM0@dz^?$)1bK+S3`}@1UXq)-AZF{|5`*DYWK|T5x&mZ+;t|Vz< ziMO-*68X1sKP%%{Q7=2W)-r$I9sLVA8c#N#TtGj_GpW&E=vu#3e*8I7{?yVOY|4N8S%z4 zd$RxB#fSVFB|^OQq0y3rBwk48L3PRp@g&K=MF)kTWzo8%kM}+==Hf=>;GK7L-Dhw*l5ov`-`iuXAGjK7JkaNru^DgUnU z#L8Imk6zCxtXXt}sZ?~V34cXcK#i7QLOK6VQg4fXT({=4@lxm-lCCxFC!BxA2dAN? z<$6->_#XfO|Nqoo(U$8V2-KYI|Nn3IY;zxIW+#xLYE5%@p4v23R0IUkubAmx8*a~x z{KpD||LzpYZzn$F0LNagb=pQBZY)2M2E>$FN5S)RuB>MVR?DV9RlCb%aKjz>WGpiy znr>s6VH44{NQ?box2xOHVz!yyP8zcfsmuNdw?$vEofv#vBgBX5e-5x=j&Qwo^IhgG zwb{zV+Y{U^z=mc^X>QyV@}l^^c{whIfv;;=_SdJwMV6D)(heydbnMzS(M`m4j@dxmhjAZNCtvek7Zjp zaRLdpnB%y+q>$uEgpvcpb}$e##jO=M6Qz(mEZYW}cBqU=Bv2I+&J$I<>VLJ6I9r=m z3Ta^ZJza^n%d4bnmJIAB7@%hjuFwAyxt+#JNA&|d?D)Hl@)t>dmWQ)4bdOvWPbqq+ z#}%Ypx>^o9mY#Lf!Xi#cE&Iq2xYzYFe^_S(P%S2B+8i5ClTkxLW+87T^ga`ukGm_O zkajzKU&(X)ao9rpTi}2?I=|NX^V2u<7_XJK%a>F>yl<2yaPw|@U1~k$W(^op@nJ4M zBiX9nm*qSA+#L@0a;C>b#H7*$mZ)Z7Gq{ZLl?#LwdPt`Q8Z9P)=EM`eLGYN~M`PFh z9s+*nTB|_u&s>t)e)O{&rkvm?KlzNbvRU}+ zy51()!)#9$_9Ja;^Ec%fZtO(6?CT;DQLX}Sy)CEB_p|Z7oHUv5_MTqY4{F`P8Ks~w zrxOmkxW(%4!q$wos%87|`}_N9(ssa!x$yV$KE)F3Z8bE?Kkyk;^6Jp9a)DLwYU{eE|bN8S7(>ppdS znR-1`FW*9s8^c&n+Ce$9NJ_BMK8Lv_tGH4xKPWk`$}zje*u%10`A)nd?5=3fxH5zMC}v6o#&2#UT|ALtL>Xd|OqFGTs{r14An*^4|581?upz!I~s>pmGfLao1g4-EZ`UrV8#f7G}* z_Gn~-b~{1sPiRSiiF79KJJB(412*%_u+~;_Nxb0XMz8;;7i`D!hgtE^tDxd0y@*}A2qEbNMEJ5JgcexJkR0jjM?vLB9j`gT0(MN6`qJRl7YXD5bIFefq(a5*=b3nY zXuyo~K8TfdM-39*x(|oPmUAck>$RW8MIg&fZ9V0&JN~-ISXF!1<+XGbbDgAJ$$hUk zC66t9T-qJnee^A@IUzi z^I1feZx^-$2jxGC4^Bm4&xXyJ*fcaY3XWkMzcjc`Fu@o~f2WZ5bgXzZa(S{W&K?gV zG6~~l1EJW(RKt`=)`|8CdG9;Q7QOX|-Z7MRhuU^L#c)L2Og7V4=+4w$5AwfE!&ag5 zK&6K!9Nz--a-IxRAPDBHeCB3?h2`@&sLFe{n$?wrRCI0LXDE7z6L>IhAs6 zudxi)_4n~uVBJ;SC86je+LayYV zmv)pIvFFYOsE@|Eavu2g!LZNA-Y5T}D38lwUnDnke+==nUaaS*k5)L;Pm<55deP*t zQxra^eo^&eFI#nC;e_VqAtC<|-$qG3_2K9y@nnz>erRO9mMl~Ibks)v%{&tPHw0>; z#ci8i2U+SVHDZ==eDMCL-V`qFuoI1q91|D2fj_bVQT|3x5wMt?g!UdVFYS#mXIOqg zmZBWc!1X+N)%e>_)Hb&CdG6GXI~>uvH;R3s{7V$>bDR(HR@q^)FpgAboK?O4sia+4 z5w2VPTF2gd;sU{=P2s$SOa!ZYcDuM8+-J#?$cgb9H52-&A|)y%4_4_r{1N99+Tl2k z0)|8kDWD&1K4bEmr}RkMPYE8<)bYzz+gC6@edlI=5N+=1xlz%){EC`W+-hc|z1>x$ zoZVVKS0JA<<&<`Jq@>Bo`+96Xc0IPmF8s-9wV8fpHsK8ZOybd~z1_nfPwM@VsuvYS zE~fmew8|-M2q5LF6WB)c=LD}X9^ubfL=5w9JkaY4Am=@M2>B2386~V2?Ps*!Q9etX zJC!RuBn$M{H{?Vj^tj}#_;|dk=AqsPd50=(C?s=IxG{?VHo3RJr$@=+4e|&A$-I0I z={PvY{$+o)MtDhiF(3VB(INBjG2BS})ZS2-jgd(-Mws&V8t~EWESa@BZx>q2D#jfs zL=P?{dZx^w>dHQ3BIww*ZKz$N*gGpOBse_EC;rEz@TG9?Xm@k4!ozV#)vHCS4np(l zv+~1#00030|I}UG*5e=u#GIbK|NDMzvKKaUMsP^9$$qIZ{b8t&-wywXE!k8&cX$D#ljc-?{u7C^cvG-#8IjGpl;L(9+;UT#uv&qB;M}C)?UUJ z5dSZv83Cx*&LUIX&1ntdIe91|}tp_quguY7Cca9+A?M}xj9E0w;tAfM53 zTueToV{#$*R43nTVVpAO_pw2`GJ{pT%YNdlkxWV(f<|z7KA(;~HO?Ah()L7Q{KY|& zwb1Q!H-YC9eBN5V2^>~bM4WcWrSnHs?^sP$3(S)zT|U?L&>jACd^+Rt7r_DL{GeDT z3KkS!@a`ZZx2P7lE9#y=S=tF0?i4BxvDuTTM&q0)@F5z_r`4m5Z8xyG{s2{<_Y@2T z7NQ8&K1%M!Ep>y3`*Em6b9|l|+Vce`+`9H0AMfI4jSOMu+nzO5@);dBaXe}5V5f@@ zs$SK)I@o8mj#}Vfqb+3Tevz4J`Z7LbO|j+wmNX(teEL-Aj|`Yyay{rqrf(pHOTfc* zUF%84Hl-{Cge>GTp0~lC0XJ@nEOl9R0b!(Q-t0Fc|AS(XYAuTa2K&c*OWLftnQ82PnAE^N^o zEJsO=6LUTx#zLDPZlxmpwd$v%d44sor1B?9p$g|!y@-pfJ(XF-T`YuHGMnzTl*@rR z#MiAIECb(+Iuvd`%-1PGW3O#BmzGC{m9W{~`4OXm1^|Th+pZpyl;9O}8_RL>QU2GB zA7My*KR=SNIz$S8rnSlNo8N}^!pvN^+Cn~I+21M0os@g}<-Jd}LiwYsYDcDyXNr^i zlkwLOUFFxN>7@M}Let4|OvDKa4@cK0jE+*V2Ef{mFjNSa#(0w4xltf$>J$#@TglSBzJ`Z_XXjY?pGm{Uemm>oM3KLgFRuCT zwv_O_#5=GPP$^81Qkt_HP-uU76Tvh+jq2|?dClU4r4nJIuhfZQwIEiCO&M7-dG9tp z%KUrd^41F)kqv^t+$`zcJ@m85Fc%FS%R+(S?$wZ5^X9cEH#XHR9+W8{(ridMZ}3%A z6U;A_4kXA=uh%Q(My&J1c;R5EbqUH>x>sBNVposNvZkWt-ZqsY0+%Y**{me4tqHG~ zB)DUqIk*;7#j_oBpw{Y9(CB)3;OQ#n#HXb$8N?(9Hp3f)VR?KdIHxI7< z3iX`@Qx`vszPi_gT^GS?+i-#=t(44nJ1~52-VWyn@>ZUa64&2>ziVoOEX{UPQ=Z=! z3+@4vM4<%tX}eK7(EC8$j7g>|B@gfNVL(oh0K9^odffZ<^Yafdwd_Vg3BmGB*`HG# zs$b2O(m^qs;K7zT(H~JI&@AwKz4Fley!RaUstFhjOuZO*Q*MCL`1zj))_(}`JV01M zjV{ZWoMiPa%Pr^a*YJRSlQnKZlkaX^U(cU5XEOU0y#d;P5SwJgiBEP1;Tz|If*S?35W?*qFj&@Wqg zrT1?qY_I8`Zl!Y|o}4+1zhR!`{jj5ZZd%A)^iN!Tj5-zsc8E8q#p;T-WvSc;xpbBX5@w zr@TC=>$TgU^TDlx@9%HroSu`bqy6msccqe)3_R?rm7fyFE0ja|4n*8EWVR>M{zW}$ zM2>k7SycCLxXn5LhgKs8{8d!s*WtPvJtt0YhZjdmWT$atBS^3iJ8GIHyb|XZIWL}E zn&(;kM{t&WGkVZ#6l?}0W4|@~$;I%iXK#B;!({mr^f}QR&no#N9N$(lyi&vrT@uqv z?WWE1oWmp}3#=o0qQ1A~oATC6h!6G)RNNA7SF?Pq-z{W|4c*5j4y}wSqgK4)JfvhyH=-2qcNgyW@dnS**5$3LF<+|4r?1{cb#I z{+z%anu`_r$w{{0*ajlm3Gw^BX@m|G`yB?^7{C}J=Uhrrb5q%9-}h3=bS^xy0BtQ% zSg3U`ZvQc!9CFad@(&^}nvmZ29UltNytM{9J~VG;N{q1_du&H!RkK4*zc4Tg>Qe*P zo}_Ny&J;5O3UV%hyD$Vb@LFr#wyoBRW%cP6lRuu|D?CGLrv?kOJP;0+{hv5qi{U7XC*WD`{SUm|i8pU!(d5NHUdo?8p5R5bLxIwZDUY+md> z!yjo2s=w7KOw;s!zga&nE=>$i$ht7xP<-gV@DM`SYgKCKCvNmhNvb!MyU>sR$xbkZ zBOMy?b@~4M`D1w%*9<2i2pt}RlHt4-Oipvo%2(31D}buui9W5Z&ZCpB&Vjc>vV5LQ zbM;zkc!HlR-7>*#qCbIL zr<9gufxd_Y_ipuC_x$aN+8sUDb=4VZZaXyAW%H8r2^^rC90v;DwJCjmS^+e(XTG#^ z@LoClgRzAvODQR(*Xwm0$Is8tx~^{joxEEDx;P(dRUGKVnb~QfRibqGd6WVawPw## zy&Rie5sklAxt(0SL#9Q9o#2k)b@Bx`arL-9Q;p@H(x-|Acxx3|_k5lnpS0@hH4`YX z_{Q{g2*H&{8SK*7f))O{Jd{&d2zLC@_|ctSo6~(^I%}tAYIWD8Fn%NR!bxCZ&^wlZ zU`x!`GJuHG;Oo0g0>MmAsVbDge`I==(aqZVz(Yoaiw15{K~{C6&U?;TbzE(0ValSyN$(>mU)H}w2m0_v-SahVyo2)USfj{Y}+=~n^<}~ov|@{^&6bD zv%?obAuMoLU0h{!z=@==i+=UmoqyL2UJQdJ8{a1LQWvlDBM?OD-X$W4w?L@VW&BX( zZfx$uc#EB#{z?6jJKXN%!XjI+dV$4TxIgIj!^Sxo_s3o+)j$(mFuMgP(DSV+B(*4X zK^Y5204O%jsoD9RypIOV?>JM6G4A`W!18*%Y^2ViPm43y@rwvHw1jg$Mfo=8Y=iCC z05;Nx@n>x(3frX&A-vyjTSEz`gdN`Xf3%H8>72N_^+!6o#mUbv2EzH~X z&+@0y%q5wap*^G2t`5UD#_%W|zrgm0CoL#5mG zBkUV3ZZJ7w>&5hbCs5Wd8f7iU_%21Yj5;Rj8rO5?rEBS&GXf6l|913be&YY;=YBAc zp1z{I$9d3Om;0z zolH2+URXQXj(_s}^vdJUnoqCijhd(<8gXFTHrH;!!6H}`4cFLjJf7B<(2d~(S}%{+ zPml8@_{`Re#Wz@c>c3y)^;|q;ayOa0gOx9aV`!s3a`}_dEfBjpwveXs60X_$9*yne zIj_OiMfco}^JV?t>g%pq3It=P$x&Q7;AlcQJ7~x8F#;hMs?^9h@8fc|9mhxFtejf7 zfc_0U4xF=Jk5@w<#JKifUfHjAMSbH)XZJqSD7Xal8Gy>>$+{5Mi-Z5nWm|fqREA8ef_1L8vXis z_K54bK7`$8{r?950RR8oUD0wYAqa)-+`0e%wVlpQviHGwdPG67n>>_Mj( zlkRy?e7VuoB{Venla3^mW#9HvezNThC*af+`Ifj-;|0L>tEoU-5rotIOhQ8zFKpNj zftD$P$3#pMtU@m*ZOi_Gd6dPaEMZc{lyV5I5u}P@q}b z9pSE_)W1@{p94A93 zXWcLs%J`T3g(p$LbFJyu($wvC`=~acweZL!cGpFQkAQcOaDEA)2idUOeu^db3v4{9 z2Mhq#VnQGuvh(~7tE2^)6fwvLf*4;goR6mW_XJ&6#Zfr4_^4Dqetmw*$XjK}^G7TQ z{yC`-(?k>|v63~v;NCsa48ltt5w~zNOrWpZGeZzEFgQ??B?3@mSRZs0%`iR*;tiaj zX`&QHl|IMS3vzE?-Hsl;T(ei0%i37+k4L)$&3Vq@^`%W?oKoLLqBUtN?Qs!VE z{CoR}-uKxdh_@q|VPi{{`HRpA`{dO7?O&yh63+v8x8q@TtVc7L$MYoOoFbne0qL4ZlA}ie8X|YRM-tdd6?EB3UP{90_Fqi4MXdG2VjS381n?G z{to~E|NqQg(U#;Y2*k|p|Nro9y$`lEC0a!7%$((6Pj)&{1O!CH_hvc2$`6ib+>KF^ zoI*DkaO?`-z5{THTtEpMv5B@`lCDte0^;)EMUSKt>i}Wi*kjl8OIKufBYGzciHg@T ztQ*ukl%{+CakEF3joj`VDy_&U*Skt$<83OIMnTf1*}uVb05QPRW_(nldoZh&(>9fJ zta(^qa?XGL{56s~V7RNxl%WL+cn3Y$5S_XUE5Mk?q*DSAfYLwfdMQ8#f_JskP7fNA z1AGjdMm=D#oU!!NsE$TD)`u}TW~~^D>9_b5D1C{OI+MVmK^wRDIm;z9M(*$$Qubfd7{OV<93!H^2EyV``eYUn~ zw)C2+dOTx}qdUBS4>2_B9ah#1&OgC}3b49x?X5B5y9ny%Nd0jmdgDXX25~Mb-8#0< zpWhl61*7hAwqpuTHrzAw@oEXpM%=fSxNN-!NG)mAF{`w?yw)Z%1ayBguS*+La3P2V2D4&issk!d%=9a5fyW|Z6hD;UT zjVfZ+Kn(PJ8AAD6L}0s68!pPX5!Gmw7N=F~xgrZbd@)}(mhU}7qJWV2opZ46^7y*q8+@kBmW z6i!7PFb+2nxg=l(f&Sm^I?>VtK0iw%OKiRNgk6qtwTqv=?ylm6E<%sBGFI-(92g~1 zSWjLcW5k7|Z-$BK!2fmgkzHRlsilYDMholZ1fPJ6@crsVaJNW~bUZ(w%=hS_&X~+y2xEHZ5PDJTsYJIo82Pv5NY8)>jJZSROimQ2`KwrV{Z?GD zEXU8M?_X45F|}~S>-E|tTcAG^Ia;F$U?!$Mi54!snZ1qNT#PT`PE!J0#Yqq~nx(l30%_QAjpZ+u`x>aCFc#1M-5ZKKvQ0uSTIP)X=>Hxr( zv+;787t3J~2eW>@STDmo-*c;s?%FRDHKphVKfzg2<_q%|ewrKIu0Nyj;dKg>HfT7##q&(&y(u zP70Oi#wD@*iKC2K=VAgD+LdGCIC}n@qWd{K6$eoIFnC|hFBa+XL&uk6J@dd_&N2rHl4}CE@?u$D>9$-<8{4Scx}|KSAdd+^qO_o(HJ>lOT>U zZ~wCcbpVcwI_19wEXLEBz6k35N`5EXDW!U5ue6N-RC#|2&t1C=(Pf5Stt_cy<%24v z^07(;^U43xQT{{Md)a32iQ zu{JNcIjJ6cZm5y9j*J)3ufK9LoUs5cl@V208UjT0U&`MztfU7ib(R!TBw()BOdQ(w{9Jtm$8>zL zM|rC7WU@+GTuNHH_!C`UwGR)xfHqfr0((18=i76>@J?l9kkH)L>c+=aitMwIl9rFe z_Bs0pX(SF;0ZvlOXVp`Ccd1WXiV0B_tL$ISf=Z_>+Qnw%Bm5RfC_gi23|yidPuv?= z0LUNl;mIIeDerr;3wO;}eLXKNlO8%4#=A+JG|sEp(`+{ovoIDXtqiaRZfBswzr}l; zR^De)5jd=C(&txX0eBfVx(`&`Ko!l>zfIqz$>Nx_DP~ttWGHSgy(w}(*8U)D z8XL$sVAw1yZ5eG~%B|r>npHE8b7siyb{mK{&P2cVhm|%L;CjA}D&ÏgCV9lPz1 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 +j4$ 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%0D+#5 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⩔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 UF+?~WZ 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

    8rW|*Bt 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%0Dc_u$+g$b=*Z>EDuQ&9cQRQfrS>R{lV!T>n+{B~ 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 -Ua|+z6UTJIdeuwN>X}WkCZ9lUg$ocEz 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 Y0Q%Mbh=G$*_{W8bSq27 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