{"cells":[{"metadata":{},"cell_type":"markdown","source":"![](https://post.medicalnewstoday.com/wp-content/uploads/sites/3/2020/02/305190_2200-1200x628.jpg)\n\n\n<p style='text-align: center;'><span style=\"color: #0D0D0D; font-family: Segoe UI; font-size: 2.6em; font-weight: 300;\">[GPU] VINBIGDATA EFFICIENTDET TRAINING USING TF OBJECT DETECTION API </span></p>\n"},{"metadata":{},"cell_type":"markdown","source":"<p style='text-align: justify;'><span style=\"color: #148998; font-family: Segoe UI; font-size: 2.1em; font-weight: 300;\">Overview</span></p>\n\n<p style='text-align: justify;'><span style=\"color: #19191d; font-family: Arial; font-size: 1.2em;\">TensorFlow 2 Object Detection API is a framework built on top of TF2, which makes it easy to construct, train and deploy, robust and high performance Object Detection Models. This notebook presents the process of TFrecord Data Preparation, loading Pre-trained models, Transfer Learning, Tuning and Inference of state-of-the-art models such as EfficientDet.</span></p>\n\n<p style='text-align: justify;'><span style=\"color: #19191d; font-family: Arial; font-size: 1.2em;\">Serveral models from the TensorFlow Model Zoo can be trained with just 1-2 lines of code change.</span></p>\n\n<br />\n\n<img src=\"https://i.ibb.co/V9wc85F/tboard1.gif\" width=\"813\" height=\"357\" />\n\n<br />\n<br />\n<br />\n\n<p style='text-align: justify;'><span style=\"color: #b02917; font-family: Segoe UI; font-size: 1.5em; font-weight: 300;\">Please do check out the dataset used for training and the notebook for fusing bounding boxes with Weighted Boxes Fusion.</span></p>\n\n<span style=\"font-family: Arial; font-size: 1.0em\">VinBigData COCO Dataset 3x Downsampled</span>\n\nDATASET LINK - https://www.kaggle.com/sreevishnudamodaran/vinbigdata-coco-dataset-with-wbf-3x-downscaled\n\n<span style=\"font-family: Arial; font-size: 1.0em\">VinBigData - Fusing Bboxes + Coco Dataset Creation Notebook</span>\n\nNOTEBOOK LINK - https://www.kaggle.com/sreevishnudamodaran/vinbigdata-fusing-bboxes-coco-dataset\n\n<br />\n<br />\n\n[![Ask Me Anything !](https://img.shields.io/badge/Ask%20me-anything-1abc9c.svg?style=flat-square&logo=kaggle)](https://www.kaggle.com/sreevishnudamodaran)\n\n<br />\n\n![Upvote!](https://img.shields.io/badge/Upvote-If%20you%20like%20my%20work-07b3c8?style=for-the-badge&logo=kaggle)"},{"metadata":{"id":"kFSqkTCdWKMI"},"cell_type":"markdown","source":"## Installations"},{"metadata":{"id":"hGL97-GXjSUw","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"!pip install tf_slim","execution_count":null,"outputs":[]},{"metadata":{"id":"Bg8ZyA47i3pY","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"## Make sure we have `pycocotools` installed\n!pip install pycocotools\n!pip install lvis\n!pip install numba ","execution_count":null,"outputs":[]},{"metadata":{"id":"-vsOL3QR6kqs"},"cell_type":"markdown","source":"## Download and extract TensorFlow Model Garden or `cd` to it if it exists\n\nModel Garden is an official TensorFlow repository on github.com which is a comprehensive repository of trained models ready for fine-tuning."},{"metadata":{"id":"ykA0c-om51s1","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"import os\nimport pathlib\n\nif \"models\" in pathlib.Path.cwd().parts:\n    while \"models\" in pathlib.Path.cwd().parts:\n        os.chdir('..')\nelif not pathlib.Path('models').exists():\n    !git clone --depth 1 https://github.com/tensorflow/models","execution_count":null,"outputs":[]},{"metadata":{"id":"O219m6yWAj9l"},"cell_type":"markdown","source":"## Compile Protobufs and Install the Object Detection Package\n\n\nTensorFlow Object Detection API uses Protobuf library to configure the model and the training parameters."},{"metadata":{"id":"PY41vdYYNlXc","trusted":true},"cell_type":"code","source":"%%bash\ncd models/research/\nprotoc object_detection/protos/*.proto --python_out=.","execution_count":null,"outputs":[]},{"metadata":{"id":"s62yJyQUcYbp","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"%%bash \ncd models/research\npip install .","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Set Environment Variabes"},{"metadata":{"trusted":true},"cell_type":"code","source":"os.environ['PYTHONPATH'] += \":/kaggle/working/models\"\n\nimport sys\nsys.path.append(\"/kaggle/working/models\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Import Packages"},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport os\nimport sys\nimport tarfile\nimport tensorflow as tf\nimport zipfile\nimport cv2\nimport json\nimport pandas as pd\nimport glob\nimport os.path as osp\nfrom path import Path\nimport datetime\nimport random\nimport shutil\nfrom io import StringIO, BytesIO\nfrom PIL import Image\nfrom IPython.display import display\nimport re\n\n%matplotlib inline\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom matplotlib import rcParams\nsns.set(rc={\"font.size\":9,\"axes.titlesize\":15,\"axes.labelsize\":9,\n            \"axes.titlepad\":11, \"axes.labelpad\":9, \"legend.fontsize\":7,\n            \"legend.title_fontsize\":7, 'axes.grid' : False})\n\nfrom sklearn.model_selection import train_test_split\n\n## Import object detection module\nfrom object_detection.utils import ops as utils_ops\nfrom object_detection.utils import label_map_util\nfrom object_detection.utils import visualization_utils as vis_utils\nfrom object_detection.protos.string_int_label_map_pb2 import StringIntLabelMap, StringIntLabelMapItem\nfrom object_detection.utils import config_util\nfrom object_detection.builders import model_builder\n\nfrom google.protobuf import text_format\n\nimport tarfile\nfrom numba import cuda ","execution_count":null,"outputs":[]},{"metadata":{"id":"RYPCiag2iz_q"},"cell_type":"markdown","source":"### Patches"},{"metadata":{"id":"mF-YlMl8c_bM","trusted":true},"cell_type":"code","source":"# patch tf1 into `utils.ops`\nutils_ops.tf = tf.compat.v1\n\n# Patch the location of gfile\ntf.gfile = tf.io.gfile","execution_count":null,"outputs":[]},{"metadata":{"id":"X_sEBLpVWKMQ"},"cell_type":"markdown","source":"# Load and Infer Using a Pre-trained Model\n\nAny model exported using the `export_inference_graph.py` tool can be loaded here simply by changing the path.\n\nSee the [detection model zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md) for a list of other models that can be run out-of-the-box with varying speeds and accuracies."},{"metadata":{"id":"_1MVVTcLWKMW"},"cell_type":"markdown","source":"## Loading Label Map\nLabel maps map indices to category names, so that when our convolution network predicts `5`, we know that this corresponds to `airplane`.  Here we use internal utility functions, but anything that returns a dictionary mapping integers to appropriate string labels would be fine."},{"metadata":{"id":"hDbpHkiWWKMX","trusted":true},"cell_type":"code","source":"PATH_TO_LABELS = 'models/research/object_detection/data/mscoco_label_map.pbtxt'\ncategory_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS, use_display_name=True)","execution_count":null,"outputs":[]},{"metadata":{"id":"f7aOtOlebK7h"},"cell_type":"markdown","source":"## Download Model Files\n\n**Replace this path with the path of your model of choice from the TF Model Garden**"},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"# !rm -r /kaggle/working/training_job/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pretrained_dir = \"/kaggle/working/training_job/model/\"\n\nif not os.path.exists(pretrained_dir):\n    os.makedirs(pretrained_dir)\n    print('Pretrainined Model Directory:', pretrained_dir)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"%%HTML\n<style>\ntd {\n  font-size: 13px\n}\n</style>","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Choosing Pre-trained Model & Downloading Weight Files\n\nChoose your pre-trained model of choice. Please note that I have provided the paths of EfficientDet models in the cell below to choose any EfficientDet model. Apart from these, the TensorFlow Object Detection API provides numerous other models:\n<br /> \n\nVisit the Model Zoo and simply replace the URL and the Model Name in the to get going.\nhttps://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/tf2_detection_zoo.md\n\n<br /> \n\n\n| <div style=\"width:450px\">Model Name</div>                               | Speed (ms) | COCO mAP | Outputs       |\n| :---                                      |   :----:   |  :----:  |:----          |\n|CenterNet HourGlass104 512x512\t            |     70\t |   41.9\t|Boxes          |\n|CenterNet HourGlass104 Keypoints 512x512\t|\t76\t|40.0/61.4|\tBoxes/Keypoints|\n|CenterNet HourGlass104 1024x1024|\t197|\t44.5\t|Boxes|\n|CenterNet HourGlass104 Keypoints 1024x1024|\t211|\t42.8/64.5\t|Boxes/Keypoints|\n|CenterNet Resnet50 V1 FPN 512x512|\t27|\t31.2\t|Boxes|\n|CenterNet Resnet50 V1 FPN Keypoints 512x512|\t30|\t29.3/50.7\t|Boxes/Keypoints|\n|CenterNet Resnet101 V1 FPN 512x512|\t34|\t34.2\t|Boxes|\n|CenterNet Resnet50 V2 512x512|\t27|\t29.5\t|Boxes|\n|CenterNet Resnet50 V2 Keypoints 512x512|\t30|\t27.6/48.2\t|Boxes/Keypoints|\n|EfficientDet D0 512x512|\t39|\t33.6\t|Boxes|\n|EfficientDet D1 640x640|\t54|\t38.4\t|Boxes|\n|EfficientDet D2 768x768|\t67|\t41.8\t|Boxes|\n|EfficientDet D3 896x896|\t95|\t45.4\t|Boxes|\n|EfficientDet D4 1024x1024|\t133|\t48.5\t|Boxes|\n|EfficientDet D5 1280x1280|\t222|\t49.7\t|Boxes|\n|EfficientDet D6 1280x1280|\t268|\t50.5\t|Boxes|\n|EfficientDet D7 1536x1536|\t325|\t51.2\t|Boxes|\n|SSD MobileNet v2 320x320|\t19|\t20.2 |Boxes|\n|SSD MobileNet V1 FPN 640x640|\t48|\t29.1\t|Boxes|\n|SSD MobileNet V2 FPNLite 320x320|\t22|\t22.2\t|Boxes|\n|SSD MobileNet V2 FPNLite 640x640|\t39|\t28.2\t|Boxes|\n|SSD ResNet50 V1 FPN 640x640 (RetinaNet50)|\t46|\t34.3\t|Boxes|\n|SSD ResNet50 V1 FPN 1024x1024 (RetinaNet50)|\t87|\t38.3\t|Boxes|\n|SSD ResNet101 V1 FPN 640x640 (RetinaNet101)|\t57|\t35.6\t|Boxes|\n|SSD ResNet101 V1 FPN 1024x1024 (RetinaNet101)|\t104|\t39.5\t|Boxes|\n|SSD ResNet152 V1 FPN 640x640 (RetinaNet152)|\t80|\t35.4\t|Boxes|\n|SSD ResNet152 V1 FPN 1024x1024 (RetinaNet152)|\t111|\t39.6\t|Boxes|\n|Faster R-CNN ResNet50 V1 640x640|\t53|\t29.3\t|Boxes|\n|Faster R-CNN ResNet50 V1 1024x1024|\t65|\t31\t|Boxes|\n|Faster R-CNN ResNet50 V1 800x1333|\t65|\t31.6\t|Boxes|\n|Faster R-CNN ResNet101 V1 640x640|\t55|\t31.8\t|Boxes|\n|Faster R-CNN ResNet101 V1 1024x1024|\t72|\t37.1\t|Boxes|\n|Faster R-CNN ResNet101 V1 800x1333|\t77|\t36.6\t|Boxes|\n|Faster R-CNN ResNet152 V1 640x640|\t64|\t32.4\t|Boxes|\n|Faster R-CNN ResNet152 V1 1024x1024|\t85|\t37.6\t|Boxes|\n|Faster R-CNN ResNet152 V1 800x1333|\t101|\t37.4\t|Boxes|\n|Faster R-CNN Inception ResNet V2 640x640|\t206|\t37.7\t|Boxes|\n|Faster R-CNN Inception ResNet V2 1024x1024|\t236|\t38.7\t|Boxes|\n|Mask R-CNN Inception ResNet V2 1024x1024|\t301|\t39.0/34.6\t|Boxes/Masks|\n|ExtremeNet|--|\t-- |Boxes|\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"## EfficientDet Configurations\n\nMODELS_CONFIG = {\n    'efficientdet-d0': {\n        'model_name': 'efficientdet_d0_coco17_tpu-32',\n        'base_pipeline_file': 'ssd_efficientdet_d0_512x512_coco17_tpu-8.config',\n        'pretrained_checkpoint': 'efficientdet_d0_coco17_tpu-32.tar.gz',\n    },\n    'efficientdet-d1': {\n        'model_name': 'efficientdet_d1_coco17_tpu-32',\n        'base_pipeline_file': 'ssd_efficientdet_d1_640x640_coco17_tpu-8.config',\n        'pretrained_checkpoint': 'efficientdet_d1_coco17_tpu-32.tar.gz',\n    },\n    'efficientdet-d2': {\n        'model_name': 'efficientdet_d2_coco17_tpu-32',\n        'base_pipeline_file': 'ssd_efficientdet_d2_768x768_coco17_tpu-8.config',\n        'pretrained_checkpoint': 'efficientdet_d2_coco17_tpu-32.tar.gz',\n    },\n    'efficientdet-d3': {\n        'model_name': 'efficientdet_d3_coco17_tpu-32',\n        'base_pipeline_file': 'ssd_efficientdet_d3_896x896_coco17_tpu-32.config',\n        'pretrained_checkpoint': 'efficientdet_d3_coco17_tpu-32.tar.gz',\n    },\n    'efficientdet-d4': {\n        'model_name': 'efficientdet_d4_coco17_tpu-32',\n        'base_pipeline_file': 'ssd_efficientdet_d4_896x896_coco17_tpu-32.config',\n        'pretrained_checkpoint': 'efficientdet_d4_coco17_tpu-32.tar.gz',\n    },\n    'efficientdet-d5': {\n        'model_name': 'efficientdet_d5_coco17_tpu-32',\n        'base_pipeline_file': 'ssd_efficientdet_d5_896x896_coco17_tpu-32.config',\n        'pretrained_checkpoint': 'efficientdet_d5_coco17_tpu-32.tar.gz',\n    },\n    'efficientdet-d6': {\n        'model_name': 'efficientdet_d6_coco17_tpu-32',\n        'base_pipeline_file': 'ssd_efficientdet_d6_896x896_coco17_tpu-32.config',\n        'pretrained_checkpoint': 'efficientdet_d6_coco17_tpu-32.tar.gz',\n    },\n    'efficientdet-d7': {\n        'model_name': 'efficientdet_d7_coco17_tpu-32',\n        'base_pipeline_file': 'ssd_efficientdet_d7_896x896_coco17_tpu-32.config',\n        'pretrained_checkpoint': 'efficientdet_d7_coco17_tpu-32.tar.gz',\n    }\n}\n\n## Choosing D1 here for this tutorial\nchosen_model = 'efficientdet-d1'\nmodel_name = MODELS_CONFIG[chosen_model]['model_name']\npretrained_checkpoint = MODELS_CONFIG[chosen_model]['pretrained_checkpoint']\nbase_pipeline_file = MODELS_CONFIG[chosen_model]['base_pipeline_file']","execution_count":null,"outputs":[]},{"metadata":{"id":"1XNT0wxybKR6","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"model_url = 'http://download.tensorflow.org/models/object_detection/tf2/20200711/'+pretrained_checkpoint\n# pretrained_dir = \"/kaggle/working/models/research/object_detection/pretrained\"\n\n!wget {model_url}\n!tar -xf {pretrained_checkpoint}\n!mv {model_name}/ {pretrained_dir}\n!rm {pretrained_checkpoint}\n\nmodel_dir = os.path.join(pretrained_dir, model_name, \"saved_model\")\nprint(\"Pre-trained model directory\", model_dir)\nmodel = tf.saved_model.load(str(model_dir))","execution_count":null,"outputs":[]},{"metadata":{"id":"Q8u3BjpMJXZF"},"cell_type":"markdown","source":"## Display the Output Structure"},{"metadata":{"id":"oLSZpfaYwuSk","trusted":true},"cell_type":"code","source":"model.signatures['serving_default'].output_dtypes","execution_count":null,"outputs":[]},{"metadata":{"id":"FZyKUJeuxvpT","trusted":true},"cell_type":"code","source":"model.signatures['serving_default'].output_shapes","execution_count":null,"outputs":[]},{"metadata":{"id":"JP5qZ7sXJpwG"},"cell_type":"markdown","source":"## Helper Functions"},{"metadata":{"id":"ajmR_exWyN76","trusted":true},"cell_type":"code","source":"def run_inference_for_single_image(model, image):\n    '''\n    Add a wrapper function to call the model, and cleanup the outputs:\n    '''\n    image = np.asarray(image)\n    # The input needs to be a tensor, convert it using `tf.convert_to_tensor`.\n    input_tensor = tf.convert_to_tensor(image)\n    # The model expects a batch of images, so add an axis with `tf.newaxis`.\n    input_tensor = input_tensor[tf.newaxis,...]\n\n    # Run inference\n    model_fn = model.signatures['serving_default']\n    output_dict = model_fn(input_tensor)\n\n    # All outputs are batches tensors.\n    # Convert to numpy arrays, and take index [0] to remove the batch dimension.\n    # We're only interested in the first num_detections.\n    num_detections = int(output_dict.pop('num_detections'))\n    output_dict = {key:value[0, :num_detections].numpy() for key,value in output_dict.items()}\n    output_dict['num_detections'] = num_detections\n\n    # detection_classes should be ints.\n    output_dict['detection_classes'] = output_dict['detection_classes'].astype(np.int64)\n\n    # Handle models with masks:\n    if 'detection_masks' in output_dict:\n        # Reframe the the bbox mask to the image size.\n        detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(\n                  output_dict['detection_masks'], output_dict['detection_boxes'],\n                   image.shape[0], image.shape[1])      \n        detection_masks_reframed = tf.cast(detection_masks_reframed > 0.5,\n                                           tf.uint8)\n        output_dict['detection_masks_reframed'] = detection_masks_reframed.numpy()\n\n    return output_dict\n\ndef show_inference(model, image_path):\n    # the array based representation of the image will be used later in order to prepare the\n    # result image with boxes and labels on it.\n    image_np = np.array(Image.open(image_path))\n    # Actual detection.\n    output_dict = run_inference_for_single_image(model, image_np)\n    # Visualization of the results of a detection.\n    vis_utils.visualize_boxes_and_labels_on_image_array(\n      image_np,\n      output_dict['detection_boxes'],\n      output_dict['detection_classes'],\n      output_dict['detection_scores'],\n      category_index,\n      instance_masks=output_dict.get('detection_masks_reframed', None),\n      use_normalized_coordinates=True,\n      line_thickness=8)\n\n    return image_np\n    \ndef load_image_into_numpy_array(path):\n    \"\"\"Load an image from file into a numpy array.\n\n    Puts image into numpy array to feed into tensorflow graph.\n    Note that by convention we put it into a numpy array with shape\n    (height, width, channels), where channels=3 for RGB.\n\n    Args:\n    path: a file path.\n\n    Returns:\n    uint8 numpy array with shape (img_height, img_width, 3)\n    \"\"\"\n    img_data = tf.io.gfile.GFile(path, 'rb').read()\n    image = Image.open(BytesIO(img_data))\n    (im_width, im_height) = image.size\n    return np.array(image.getdata()).reshape(\n      (im_height, im_width, 3)).astype(np.uint8)\n\ndef plot_detections(image_np, boxes, classes, scores, category_index,\n                    figsize=(12, 16), image_name=None):\n    \"\"\"Wrapper function to visualize detections.\n\n    Args:\n    image_np: uint8 numpy array with shape (img_height, img_width, 3)\n    boxes: a numpy array of shape [N, 4]\n    classes: a numpy array of shape [N]. Note that class indices are 1-based,\n      and match the keys in the label map.\n    scores: a numpy array of shape [N] or None.  If scores=None, then\n      this function assumes that the boxes to be plotted are groundtruth\n      boxes and plot all boxes as black with no classes or scores.\n    category_index: a dict containing category dictionaries (each holding\n      category index `id` and category name `name`) keyed by category indices.\n    figsize: size for the figure.\n    image_name: a name for the image file.\n    \"\"\"\n    image_np_with_annotations = image_np.copy()\n    viz_utils.visualize_boxes_and_labels_on_image_array(\n      image_np_with_annotations,\n      boxes,\n      classes,\n      scores,\n      category_index,\n      use_normalized_coordinates=True,\n      min_score_thresh=0.8)\n    if image_name:\n        plt.imsave(image_name, image_np_with_annotations)\n    else:\n        plt.imshow(image_np_with_annotations)\n        \n        \ndef plot_img(img, size=(18, 18), is_rgb=True, title=\"\", cmap='gray'):\n    plt.figure(figsize=size)\n    plt.imshow(img, cmap=cmap)\n    plt.suptitle(title)","execution_count":null,"outputs":[]},{"metadata":{"id":"z1wq0LVyMRR_"},"cell_type":"markdown","source":"## Run the Model on Sample Images"},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"!wget https://cdn.pixabay.com/photo/2015/03/26/09/43/city-690158_960_720.jpg\n!wget https://cdn.pixabay.com/photo/2017/08/05/23/31/people-2586656_960_720.jpg\n!wget https://upload.wikimedia.org/wikipedia/commons/6/60/Naxos_Taverna.jpg\n    \n!wget https://cdn.pixabay.com/photo/2020/02/07/15/33/girl-4827500_960_720.jpg\nTEST_IMAGE_PATHS = [\n                    'girl-4827500_960_720.jpg',\n                    'Naxos_Taverna.jpg',\n                    'city-690158_960_720.jpg'\n                   ]\n","execution_count":null,"outputs":[]},{"metadata":{"id":"3a5wMHN8WKMh","trusted":true},"cell_type":"code","source":"for image_path in TEST_IMAGE_PATHS:\n    image = show_inference(model, image_path)\n    os.remove(image_path)\n    plot_img(image)\n    plt.savefig('{}_viz.png'.format(image_path))\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Delete Model and Release GPU Memory"},{"metadata":{"trusted":true},"cell_type":"code","source":"del model\ndevice = cuda.get_current_device()\ndevice.reset()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## TFRecord Creation\n\nWe are using the [vinbigdata-coco-dataset-with-wbf-3x-downscaled](https://www.kaggle.com/sreevishnudamodaran/vinbigdata-coco-dataset-with-wbf-3x-downscaled) dataset in COCO format with Fused Bounding Boxes using the Weighted Boxes Fusion Technique. This makes it easy to create TFRecords in just One Step.\n\nDataset Creation Notebook:\n\nhttps://www.kaggle.com/sreevishnudamodaran/vinbigdata-fusing-bboxes-coco-dataset"},{"metadata":{},"cell_type":"markdown","source":"### Create Ouput TFRecord Folder"},{"metadata":{"trusted":true},"cell_type":"code","source":"tfr_output_dir = \"/kaggle/working/training_job/tfrecords/\"\n\nif not os.path.exists(tfr_output_dir):\n    os.makedirs(tfr_output_dir)\n    print('TFRecord Directory:', tfr_output_dir)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**The cell below uses create_coco_tf_record tool provided by TensorFlow converts COCO datasets into TFRecords directly.**\n\n**Please note that the valications images and annotations are passed to the tool as the test data since the test argument is not optional. We will only be making use of Train and Validations TFRecords.**"},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"%%bash\npython models/research/object_detection/dataset_tools/create_coco_tf_record.py --logtostderr \\\n--train_image_dir=\"../input/vinbigdata-coco-dataset-with-wbf-3x-downscaled/vinbigdata-coco-dataset-with-wbf-3x-downscaled\" \\\n--test_image_dir=\"../input/vinbigdata-coco-dataset-with-wbf-3x-downscaled/vinbigdata-coco-dataset-with-wbf-3x-downscaled\" \\\n--val_image_dir=\"../input/vinbigdata-coco-dataset-with-wbf-3x-downscaled/vinbigdata-coco-dataset-with-wbf-3x-downscaled\" \\\n--train_annotations_file=\"../input/vinbigdata-coco-dataset-with-wbf-3x-downscaled/vinbigdata-coco-dataset-with-wbf-3x-downscaled/train_annotations.json\" \\\n--testdev_annotations_file=\"../input/vinbigdata-coco-dataset-with-wbf-3x-downscaled/vinbigdata-coco-dataset-with-wbf-3x-downscaled/val_annotations.json\" \\\n--val_annotations_file=\"../input/vinbigdata-coco-dataset-with-wbf-3x-downscaled/vinbigdata-coco-dataset-with-wbf-3x-downscaled/val_annotations.json\" \\\n--output_dir=\"/kaggle/working/training_job/tfrecords/\"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Creating the Label Map File\n\nThis is just a file which contains the mapping of the classes and their integer ID. This is be used to internally to encode the train data and to decipher the model predictions during inference."},{"metadata":{"trusted":true},"cell_type":"code","source":"def convert_classes(classes, start=1):\n    msg = StringIntLabelMap()\n    for id, name in enumerate(classes, start=start):\n        msg.item.append(StringIntLabelMapItem(id=id, name=name))\n    text = str(text_format.MessageToBytes(msg, as_utf8=True), 'utf-8')\n    return text\n\nlabels =  [\n            \"Aortic_enlargement\",\n            \"Atelectasis\",\n            \"Calcification\",\n            \"Cardiomegaly\",\n            \"Consolidation\",\n            \"ILD\",\n            \"Infiltration\",\n            \"Lung_Opacity\",\n            \"Nodule_Mass\",\n            \"Other_lesion\",\n            \"Pleural_effusion\",\n            \"Pleural_thickening\",\n            \"Pneumothorax\",\n            \"Pulmonary_fibrosis\"\n            ]\n\ntxt = convert_classes(labels)\nprint(txt)\nwith open('/kaggle/working/training_job/label_map.pbtxt', 'w') as f:\n    f.write(txt)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Preparing Train Job Folder "},{"metadata":{"trusted":true},"cell_type":"code","source":"model_files_dir = \"/kaggle/working/training_job/model_files/\"\n\nif not os.path.exists(model_files_dir):\n    os.makedirs(model_files_dir)\n    print('Model Files Directory:', model_files_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"## Download pretrained weights\ndownload_tar = 'http://download.tensorflow.org/models/object_detection/tf2/20200711/' + pretrained_checkpoint\n!wget {download_tar} -P {model_files_dir}\ntar = tarfile.open(os.path.join(model_files_dir, pretrained_checkpoint))\ntar.extractall()\ntar.close()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"!rm {model_files_dir}/ssd_efficientdet_d2_768x768_coco17_tpu-8.config","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"## Download base training configuration file\n\ndownload_config = 'https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/configs/tf2/'+base_pipeline_file\n!wget {download_config} -P {model_files_dir}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Get the Total Number of Classes\n\ndef get_num_classes(pbtxt_fname):\n    from object_detection.utils import label_map_util\n    label_map = label_map_util.load_labelmap(pbtxt_fname)\n    categories = label_map_util.convert_label_map_to_categories(\n        label_map, max_num_classes=90, use_display_name=True)\n    category_index = label_map_util.create_category_index(categories)\n    return len(category_index.keys())\n\n\nval_record_fname = '/kaggle/working/training_job/tfrecords/coco_val.record*'\ntrain_record_fname = '/kaggle/working/training_job/tfrecords/coco_train.record*'\nlabel_map_pbtxt_fname = '/kaggle/working/training_job/label_map.pbtxt'\n\npipeline_file = os.path.join(model_files_dir, base_pipeline_file)\nfine_tune_checkpoint = os.path.join(pretrained_dir, model_name, 'checkpoint/ckpt-0')\nnum_classes = get_num_classes(label_map_pbtxt_fname)\nprint(\"No. of Classes\", num_classes)\nprint(\"Checkpoint File Path\", fine_tune_checkpoint)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Configuring the Model Training Pipeline File\n\n## File Structure\n\nThis file represents the configuration and hyperparamters which will be used for the training job. It can be configured as required for further tuning.\n\n\n```python\n# SSD with EfficientNet-b1 + BiFPN feature extractor,\n# shared box predictor and focal loss (a.k.a EfficientDet-d1).\n# See EfficientDet, Tan et al, https://arxiv.org/abs/1911.09070\n# See Lin et al, https://arxiv.org/abs/1708.02002\n# Trained on COCO, initialized from an EfficientNet-b1 checkpoint.\n#\n# Train on TPU-8\n\nmodel {\n  ssd {\n    inplace_batchnorm_update: true\n    freeze_batchnorm: false\n    num_classes: 90\n    add_background_class: false\n    box_coder {\n      faster_rcnn_box_coder {\n        y_scale: 10.0\n        x_scale: 10.0\n        height_scale: 5.0\n        width_scale: 5.0\n      }\n    }\n    matcher {\n      argmax_matcher {\n        matched_threshold: 0.5\n        unmatched_threshold: 0.5\n        ignore_thresholds: false\n        negatives_lower_than_unmatched: true\n        force_match_for_each_row: true\n        use_matmul_gather: true\n      }\n    }\n    similarity_calculator {\n      iou_similarity {\n      }\n    }\n    encode_background_as_zeros: true\n    anchor_generator {\n      multiscale_anchor_generator {\n        min_level: 3\n        max_level: 7\n        anchor_scale: 4.0\n        aspect_ratios: [1.0, 2.0, 0.5]\n        scales_per_octave: 3\n      }\n    }\n    image_resizer {\n      keep_aspect_ratio_resizer {\n        min_dimension: 640\n        max_dimension: 640\n        pad_to_max_dimension: true\n        }\n    }\n    box_predictor {\n      weight_shared_convolutional_box_predictor {\n        depth: 88\n        class_prediction_bias_init: -4.6\n        conv_hyperparams {\n          force_use_bias: true\n          activation: SWISH\n          regularizer {\n            l2_regularizer {\n              weight: 0.00004\n            }\n          }\n          initializer {\n            random_normal_initializer {\n              stddev: 0.01\n              mean: 0.0\n            }\n          }\n          batch_norm {\n            scale: true\n            decay: 0.99\n            epsilon: 0.001\n          }\n        }\n        num_layers_before_predictor: 3\n        kernel_size: 3\n        use_depthwise: true\n      }\n    }\n    feature_extractor {\n      type: 'ssd_efficientnet-b1_bifpn_keras'\n      bifpn {\n        min_level: 3\n        max_level: 7\n        num_iterations: 4\n        num_filters: 88\n      }\n      conv_hyperparams {\n        force_use_bias: true\n        activation: SWISH\n        regularizer {\n          l2_regularizer {\n            weight: 0.00004\n          }\n        }\n        initializer {\n          truncated_normal_initializer {\n            stddev: 0.03\n            mean: 0.0\n          }\n        }\n        batch_norm {\n          scale: true,\n          decay: 0.99,\n          epsilon: 0.001,\n        }\n      }\n    }\n    loss {\n      classification_loss {\n        weighted_sigmoid_focal {\n          alpha: 0.25\n          gamma: 1.5\n        }\n      }\n      localization_loss {\n        weighted_smooth_l1 {\n        }\n      }\n      classification_weight: 1.0\n      localization_weight: 1.0\n    }\n    normalize_loss_by_num_matches: true\n    normalize_loc_loss_by_codesize: true\n    post_processing {\n      batch_non_max_suppression {\n        score_threshold: 1e-8\n        iou_threshold: 0.5\n        max_detections_per_class: 100\n        max_total_detections: 100\n      }\n      score_converter: SIGMOID\n    }\n  }\n}\n\ntrain_config: {\n  fine_tune_checkpoint: \"PATH_TO_BE_CONFIGURED/ckpt-0\"\n  fine_tune_checkpoint_version: V2\n  fine_tune_checkpoint_type: \"classification\"\n  batch_size: 128\n  sync_replicas: true\n  startup_delay_steps: 0\n  replicas_to_aggregate: 8\n  use_bfloat16: true\n  num_steps: 300000\n  data_augmentation_options {\n    random_horizontal_flip {\n    }\n  }\n  data_augmentation_options {\n    random_scale_crop_and_pad_to_square {\n      output_size: 640\n      scale_min: 0.1\n      scale_max: 2.0\n    }\n  }\n  optimizer {\n    momentum_optimizer: {\n      learning_rate: {\n        cosine_decay_learning_rate {\n          learning_rate_base: 8e-2\n          total_steps: 300000\n          warmup_learning_rate: .001\n          warmup_steps: 2500\n        }\n      }\n      momentum_optimizer_value: 0.9\n    }\n    use_moving_average: false\n  }\n  max_number_of_boxes: 100\n  unpad_groundtruth_tensors: false\n}\n\ntrain_input_reader: {\n  label_map_path: \"PATH_TO_BE_CONFIGURED/label_map.txt\"\n  tf_record_input_reader {\n    input_path: \"PATH_TO_BE_CONFIGURED/train2017-?????-of-00256.tfrecord\"\n  }\n}\n\neval_config: {\n  metrics_set: \"coco_detection_metrics\"\n  use_moving_averages: false\n  batch_size: 1;\n}\n\neval_input_reader: {\n  label_map_path: \"PATH_TO_BE_CONFIGURED/label_map.txt\"\n  shuffle: false\n  num_epochs: 1\n  tf_record_input_reader {\n    input_path: \"PATH_TO_BE_CONFIGURED/val2017-?????-of-00032.tfrecord\"\n  }\n}\n    \n```"},{"metadata":{},"cell_type":"markdown","source":"## Define Parameters"},{"metadata":{"trusted":true},"cell_type":"code","source":"## Train Images = 3296\n## 3296/8 = 412\n## Val Images = 1098\n## 1098/8 ~= 138\n\n## Training Configurations\nnum_epochs = 5\nnum_steps = 412*num_epochs\nnum_eval_steps = 138\nbatch_size = 8\nprint(\"Number of Steps:\", num_steps)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Modify the Pipeline Configuration File"},{"metadata":{"trusted":true},"cell_type":"code","source":"#write custom configuration file by slotting our dataset, model checkpoint, and training parameters into the base pipeline file\n\nprint('Updading the Training Configuration file')\nwith open(pipeline_file) as f:\n    s = f.read()\n    \nwith open(pipeline_file, 'w') as f:\n    \n    # fine_tune_checkpoint\n    s = re.sub('fine_tune_checkpoint: \".*?\"',\n               'fine_tune_checkpoint: \"{}\"'.format(fine_tune_checkpoint), s)\n    \n    # tfrecord files train and test.\n    s = re.sub('(input_path: \".*?)(PATH_TO_BE_CONFIGURED/train)(.*?\")',\n               'input_path: \"{}\"'.format(train_record_fname), s)\n    \n    s = re.sub('(input_path: \".*?)(PATH_TO_BE_CONFIGURED/val)(.*?\")',\n               'input_path: \"{}\"'.format(val_record_fname), s)\n\n    # label_map_path\n    s = re.sub('label_map_path: \".*?\"',\n               'label_map_path: \"{}\"'.format(label_map_pbtxt_fname), s)\n\n    # Set training batch_size.\n    s = re.sub('batch_size: [0-9]+',\n               'batch_size: {}'.format(batch_size), s)\n\n    # Set training steps, num_steps\n    s = re.sub('num_steps: [0-9]+',\n               'num_steps: {}'.format(num_steps), s)\n    \n    # Set number of classes num_classes.\n    s = re.sub('num_classes: [0-9]+',\n               'num_classes: {}'.format(num_classes), s)\n    \n    \n    #fine-tune checkpoint type\n    s = re.sub('fine_tune_checkpoint_type: \"classification\"',\n               'fine_tune_checkpoint_type: \"{}\"'.format('detection'), s)\n        \n    f.write(s)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Check the pipeline config file\n!cat {pipeline_file}","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Train Custom TF2 Object Detector\n\n\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"model_dir = \"/kaggle/working/training_job/model_files/training/\"\n\nif not os.path.exists(model_dir):\n    os.makedirs(model_dir)\n    print('Training Files:', model_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Checking GPU Load\n!nvidia-smi","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Start Training\n\n\nmodel_dir: the location tensorboard logs and saved model checkpoints will save to"},{"metadata":{"trusted":true,"_kg_hide-output":true,"collapsed":true},"cell_type":"code","source":"!python /kaggle/working/models/research/object_detection/model_main_tf2.py \\\n    --pipeline_config_path={pipeline_file} \\\n    --model_dir={model_dir} \\\n    --alsologtostderr \\\n    --num_train_steps={num_steps} \\\n    --sample_1_of_n_eval_examples=1 \\\n    --num_eval_steps={num_eval_steps}","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model Evaluation & Sample Inference\n## Perform Evaluation using Model Main"},{"metadata":{"trusted":true},"cell_type":"code","source":"import glob\nimport os\nos.environ['PYTHONPATH'] += \":/kaggle/working/models\"\nimport sys\nsys.path.append(\"/kaggle/working/models\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_dir = \"/kaggle/working/training_job/model_files/training/\"\npipeline_file = glob.glob(os.path.join('/kaggle/working/training_job/model_files/', '*.config'))[0]\npipeline_file","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true,"collapsed":true},"cell_type":"code","source":"## Stop this cell manually\n!python /kaggle/working/models/research/object_detection/model_main_tf2.py \\\n     --pipeline_config_path={pipeline_file} \\\n     --model_dir={model_dir} \\\n     --checkpoint_dir={model_dir} \\\n     --run_once=True","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Reloading Packages & Env Variables\n\nRunning the model training and evaluation scripts will unload all the packages loaded. Please note that it does not reset the environment. No new installations need to be done."},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nos.environ['PYTHONPATH'] += \":/kaggle/working/models\"\n\nimport sys\nsys.path.append(\"/kaggle/working/models\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\n\nimport sys\nimport cv2\nimport glob\nimport os.path as osp\nfrom path import Path\nimport random\nimport io\nimport scipy.misc\nfrom six import BytesIO\nfrom PIL import Image, ImageDraw, ImageFont\n\n%matplotlib inline\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom matplotlib import rcParams\nsns.set(rc={\"font.size\":9,\"axes.titlesize\":15,\"axes.labelsize\":9,\n            \"axes.titlepad\":11, \"axes.labelpad\":9, \"legend.fontsize\":7,\n            \"legend.title_fontsize\":7, 'axes.grid' : False})\n\nimport tensorflow as tf\nfrom object_detection.utils import label_map_util\nfrom object_detection.utils import config_util\nfrom object_detection.utils import visualization_utils as viz_utils\nfrom object_detection.builders import model_builder\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_dir = \"/kaggle/working/training_job/model_files/training/\"\npipeline_file = glob.glob(os.path.join('/kaggle/working/training_job/model_files/', '*.config'))[0]\npipeline_file","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## See our saved weights\n!ls {model_dir}","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Monitoring & Evaluation\n### Unfortunately running Tensorboard on Kaggle Notebooks directly is put on hold at the moment but, there is way to see it using ngrox!\n\n**Thanks to [shivam1600](https://www.kaggle.com/shivam1600)**\n<br />\nhttps://www.kaggle.com/shivam1600/tensorboard-on-kaggle\n\n### Uncomment the cells below to get tensorboard. It only works in editing mode and in a new tab."},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"# # Download Ngrok to tunnel the tensorboard port to an external port\n# !wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip\n# !unzip ngrok-stable-linux-amd64.zip","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"# import multiprocessing\n\n# log_path = os.path.join(model_dir, 'train')\n# print(\"log_path\", log_path)\n\n# # Run tensorboard as well as Ngrox (for tunneling as non-blocking processes)\n# pool = multiprocessing.Pool(processes = 10)\n# results_of_processes = [pool.apply_async(os.system, args=(cmd, ), callback = None )\n#                         for cmd in [\n#                         f\"tensorboard --logdir {log_path} --host 0.0.0.0 --port 6006 &\",\n#                         \"./ngrok http 6006 &\"\n#                         ]]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Click the link in the output of the cell below after running the notebook to view Tensorboard"},{"metadata":{"trusted":true},"cell_type":"code","source":"# !curl -s http://localhost:4040/api/tunnels | python3 -c \\\n#     \"import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])\"","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"# !ps -ef | grep 6006","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<img src=\"https://i.ibb.co/V9wc85F/tboard1.gif\" width=\"813\" height=\"357\" />"},{"metadata":{},"cell_type":"markdown","source":"## Load the Latest Checkpoint"},{"metadata":{"trusted":true},"cell_type":"code","source":"last_ckpt = Path(sorted(glob.glob(os.path.join(model_dir,'ckpt-*')))[-1]).stem\nlast_ckpt","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"configs = config_util.get_configs_from_pipeline_file(pipeline_file)\nmodel_config = configs['model']\ndetection_model = model_builder.build(model_config=model_config, is_training=False)\n\n## Restore checkpoint\nckpt = tf.compat.v2.train.Checkpoint(model=detection_model)\nckpt.restore(os.path.join(model_dir, last_ckpt))\n\ndef get_model_detection_function(model):\n    \"\"\"Get a tf.function for detection.\"\"\"\n    @tf.function\n    def detect_fn(image):\n        \"\"\"Detect objects in image.\"\"\"\n        image, shapes = model.preprocess(image)\n        prediction_dict = model.predict(image, shapes)\n        detections = model.postprocess(prediction_dict, shapes)\n        return detections, prediction_dict, tf.reshape(shapes, [-1])\n    return detect_fn\n\ndetect_fn = get_model_detection_function(detection_model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Load Label Map File For Scoring & Visualization"},{"metadata":{"trusted":true},"cell_type":"code","source":"## Map labels for Inference\nlabel_map_path = configs['eval_input_config'].label_map_path\nlabel_map = label_map_util.load_labelmap(label_map_path)\ncategories = label_map_util.convert_label_map_to_categories(\n                label_map,\n                max_num_classes=label_map_util.get_max_label_map_index(label_map),\n                use_display_name=True)\ncategory_index = label_map_util.create_category_index(categories)\nlabel_map_dict = label_map_util.get_label_map_dict(label_map, use_display_name=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Score on Sample Images\n\n### Helper Functions for Visualization"},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_imgs(imgs, cols=2, size=10, is_rgb=True, title=\"\", cmap='gray', img_size=None):\n    rows = len(imgs)//cols + 1\n    fig = plt.figure(figsize=(round(cols*size*0.7), rows*size))\n    for i, img in enumerate(imgs):\n        if img_size is not None:\n            img = cv2.resize(img, img_size)\n        fig.add_subplot(rows, cols, i+1)\n        plt.imshow(img, cmap=cmap)\n    plt.suptitle(title)   \n    \ndef draw_bbox(image, box, label, color):   \n    alpha = 0.1\n    alpha_box = 0.4\n    overlay_bbox = image.copy()\n    overlay_text = image.copy()\n    output = image.copy()\n    output = cv2.rectangle(output, (box[0], box[1]), (box[2], box[3]),\n                           color, 2)\n\n    text_width, text_height = cv2.getTextSize(label.upper(), cv2.FONT_HERSHEY_SIMPLEX, 0.6, 1)[0]\n    cv2.rectangle(overlay_bbox, (box[0], box[1]), (box[2], box[3]),\n                  color, -1)\n    cv2.addWeighted(overlay_bbox, alpha, output, 1 - alpha, 0, output)\n    \n    cv2.rectangle(overlay_text, (box[0], box[1]-7-text_height),\n                  (box[0]+text_width+2, box[1]), (0, 0, 0), -1)\n    \n    cv2.addWeighted(overlay_text, alpha_box, output, 1 - alpha_box, 0, output)\n    cv2.putText(output, label.upper(), (box[0], box[1]-5),\n            cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2, cv2.LINE_AA)\n    return output","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"val_images = glob.glob('../input/vinbigdata-coco-dataset-with-wbf-3x-downscaled/vinbigdata-coco-dataset-with-wbf-3x-downscaled/val_images/*.jpg')\n\nviz_images = []\nfor img_path in val_images[:4]:\n    image_np = cv2.imread(img_path)\n    input_tensor = tf.convert_to_tensor(np.expand_dims(image_np, 0),\n                                        dtype=tf.float32)\n    detections, predictions_dict, shapes = detect_fn(input_tensor)\n    label_id_offset = 1\n    image_np_with_detections = image_np.copy()\n\n    label2color = [[59, 238, 119], [222, 21, 229], [94, 49, 164], [206, 221, 133], [117, 75, 3],\n                 [210, 224, 119], [211, 176, 166], [63, 7, 197], [102, 65, 77], [194, 134, 175],\n                 [209, 219, 50], [255, 44, 47], [89, 125, 149], [110, 27, 100]]\n    \n    min_score_thresh = 0.4\n    width, height, _ = image_np.shape\n    boxes = detections['detection_boxes'][0].numpy()\n    boxes = boxes[:,[1, 0, 3, 2]]*np.array([height, width, height, width])\n    \n    for box, label_id, score in zip(boxes,\n                                    (detections['detection_classes'][0].numpy() + label_id_offset).astype(int),\n                                     detections['detection_scores'][0].numpy()):\n        if (score > min_score_thresh):\n            image_np_with_detections = draw_bbox(image_np_with_detections, list(np.int_(box)),\n                                                 category_index[label_id]['name']+'_'+str(round(score*100,1))+'%',\n                                                 label2color[label_id-1])\n        \n    viz_images.append(image_np_with_detections)\n\nplot_imgs(viz_images, cols=2, size=10, cmap=None)\nplt.savefig('inference_sample.png')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"# !rm -r ./models\n# !rm -r ./efficientdet_d1_coco17_tpu-32","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<p style='text-align: center;'><span style=\"color: #0D0D0D; font-family: Segoe UI; font-size: 2.0em; font-weight: 200;\">THANK YOU! PLEASE UPVOTE</span></p>\n\n<p style='text-align: center;'><span style=\"color: #0D0D0D; font-family: Segoe UI; font-size: 2.5em; font-weight: 100;\">HOPE IT WAS USEFUL</span></p>\n\n<p style='text-align: center;'><span style=\"color: #009BAE; font-family: Segoe UI; font-size: 1.3em; font-weight: 300;\">Tuning & updation in progress.</span></p>"}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}