{"cells":[{"metadata":{"trusted":true,"_uuid":"c1a6bf14b72e41d2de4212f34bc220e08a5c4c35"},"cell_type":"markdown","source":"# Introduction\nThis is a course project of [Standford SCI 54 Fall 2018](https://continuingstudies.stanford.edu/courses/liberal-arts-and-sciences/artificial-intelligence-master-class-guided-journeys-into-the-brave-new-world-of-ai/20181_SCI-54). Which aims to create an Object Instance Segmentation Minimum Viable Model for a real-world problem on Kaggle platform, to provide a starting point for further work, and to illustrate the key concepts of Machine Learning on Visual Recognition.    \n\n## Airbus Ship Detection Challenge \nThe goal of [Airbus Ship Detection Kaggle Challenge](https://www.kaggle.com/c/airbus-ship-detection) is to detect all ships in satellite images as quickly as possible. Which is a good real-world problem of Object Instance Segmentation with labeled dataset ready for training and testing.\n\n## The problem\nThe challenge is to detect ships in satellite Images and generate mask images of ships, such as:\n![ship mask example](https://github.com/samlin001/Mask_RCNN/raw/master/assets/ship_mask_example.png)\n\nThe key application specific constraints are:\n* Detecting multiple ships and their locations\n* Generating a pixel level mask and a bounding boxe for each ship  \n* Ships can be very small in a satellite image\n* Ships can be partly in a satellite image"},{"metadata":{"_uuid":"947ab06d7b7d62f1febe368d613cf8389b3604be"},"cell_type":"markdown","source":"# Select a right model\nIt is important to select a model with good fit of the application and constraints. There are 4 types of tasks in general and this challenge is an instance segmentation problem.  \n![Computer vision taks](https://github.com/samlin001/Mask_RCNN/raw/master/assets/Conputer_vision_tasks_cs231n_stanford.png)\n[Source: Fei-Fei Li, Andrej Karpathy & Justin Johnson (2016) cs231n, Lecture 8 - Slide 8, Spatial Localization and Detection](http://cs231n.stanford.edu/slides/2016/winter1516_lecture8.pdf)\n\n## Popular Convolutional Object Detectors\nFollowing references provide good summary of popular models.\n* [R-CNN, Fast R-CNN, Faster R-CNN, YOLO — Object Detection Algorithms](https://towardsdatascience.com/r-cnn-fast-r-cnn-faster-r-cnn-yolo-object-detection-algorithms-36d53571365e)  \n* [A year in computer vision](http://www.themtank.org/a-year-in-computer-vision) is a comprehensive update for the recent development in the field in 2016.\n\n## Mask R-CNN\n[Mask R-CNN](https://github.com/facebookresearch/Detectron) is selected for this project because it can generate high-quality segmentation mask for each object. Its mask prediction branche is added in parallel to Faster R-CNN's bounding box and image class prediction.\n\n![Mask R-CNN Head Architecture](https://github.com/samlin001/Mask_RCNN/raw/master/assets/Mask_R_CNN_Head_Architecture_%20arXiv1703.06870.png)\n[Source: Kaiming He, Georgia Gkioxari, Piotr Dollár & Ross Girshickar (2017) Mask R-CNN, Xiv:1703.06870](https://arxiv.org/abs/1703.06870)\n\n## You Only Look Once\n[YOLO](https://pjreddie.com/darknet/yolo/) has very impressive real-time performance on detect objects. However, it is not a good choice for this challenge because it can not achieve follows:\n* Generating pixel level masks\n* Detecting groups of small objects\n\nBecause YOLO uses SxS grids for bounding boxes and image classes prediction, it is not designed for those tasks.    \n![image.png](https://github.com/samlin001/Mask_RCNN/raw/master/assets/YOLO_model_arXiv_1506.02640.png)[Source: Joseph Redmon, Santosh Divvala, Ross Girshick & Ali Farhadi (2015) You Only Look Once: Unified, Real-Time Object Detection, arXiv:1506.02640](https://arxiv.org/abs/1506.02640)"},{"metadata":{"_uuid":"47d0328e464ab04835bf981f3ae8617eb50f82d9"},"cell_type":"markdown","source":"# Project Configuration"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt # plot & image processing\nfrom skimage.morphology import label\nfrom skimage.data import imread\n\nimport os\nimport time\nimport sys\n\n# Configurations\n# Split x ratio of train dataset for validation \nTRAINING_VALIDATION_RATIO = 0.2\nWORKING_DIR = '/kaggle/working'\nINPUT_DIR = '/kaggle/input'\nOUTPUT_DIR = '/kaggle/output'\nLOGS_DIR = os.path.join(WORKING_DIR, \"logs\")\nTRAIN_DATA_PATH = os.path.join(INPUT_DIR, 'train_v2')\nTEST_DATA_PATH = os.path.join(INPUT_DIR, 'test_v2')\nSAMPLE_SUBMISSION_PATH = os.path.join(INPUT_DIR, 'sample_submission_v2.csv')\nTRAIN_SHIP_SEGMENTATIONS_PATH = os.path.join(INPUT_DIR, 'train_ship_segmentations_v2.csv')\nMASK_RCNN_PATH = os.path.join(WORKING_DIR, 'Mask_RCNN-master')\nCOCO_WEIGHTS_PATH = os.path.join(WORKING_DIR, \"mask_rcnn_coco.h5\")\nSHIP_CLASS_NAME = 'ship'\nIMAGE_WIDTH = 768\nIMAGE_HEIGHT = 768\nSHAPE = (IMAGE_WIDTH, IMAGE_HEIGHT)\n\ntest_ds = os.listdir(TEST_DATA_PATH)\ntrain_ds = os.listdir(TRAIN_DATA_PATH)\n\nprint('Working Dir:', WORKING_DIR, os.listdir(WORKING_DIR))\nprint('Input Dir:', INPUT_DIR, os.listdir(INPUT_DIR))\nprint('train dataset from: {}, {}'.format(TRAIN_DATA_PATH, len(train_ds)))\nprint('test dataset from: {}, {}'.format(TRAIN_DATA_PATH, len(test_ds)))\nprint(TRAIN_SHIP_SEGMENTATIONS_PATH)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"39020e0712387e8a2fc11ca92a93bb23e40d07d6"},"cell_type":"markdown","source":"# Preparing Dataset\n## Run-length mask encording"},{"metadata":{"trusted":true,"_uuid":"11c19903f97a53de869d94a468209dd92fc2f267"},"cell_type":"code","source":"# Read mask encording from the input CSV file \nmasks = pd.read_csv(TRAIN_SHIP_SEGMENTATIONS_PATH)\nmasks.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8e20324e1871426da843b539e6b13d7c0350f311"},"cell_type":"markdown","source":"Each mask are stored by run length pixel encoding, where:\n* ImageId is the filename of the corresponding image in train_v2.zip\n* EncodedPixels contain in run-length encoding format, [StartPosition] [Length] pairs of masked pixels\n* StartPosition is a position in 1D array\n* [For example, '1 3 10 5' implies pixels 1,2,3,10,11,12,13,14 are to be included in the mask.](https://www.kaggle.com/c/airbus-ship-detection#evaluation) \n\n## Utility functions\nUtility functions are adapted from [Run Length Encode And Decode](https://www.kaggle.com/paulorzp/run-length-encode-and-decode) and [Baseline U Net Model Part 1](https://www.kaggle.com/kmader/baseline-u-net-model-part-1) "},{"metadata":{"trusted":true,"_uuid":"cb81ee007e820e6711069f8f3895812e59b24533"},"cell_type":"code","source":"# ref: https://www.kaggle.com/kmader/baseline-u-net-model-part-1\ndef multi_rle_encode(img):\n    labels = label(img[:, :, 0])\n    return [rle_encode(labels==k) for k in np.unique(labels[labels>0])]\n\n# ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode\ndef rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated: [start0] [length0] [start1] [length1]... in 1d array\n    '''\n    # reshape to 1d array\n    pixels = img.T.flatten() # Needed to align to RLE direction\n    # pads the head & the tail with 0 & converts to ndarray\n    pixels = np.concatenate([[0], pixels, [0]])\n    # gets all start(0->1) & end(1->0) positions \n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    # transforms end positions to lengths\n    runs[1::2] -= runs[::2]\n    # converts to the string formated: '[s0] [l0] [s1] [l1]...'\n    return ' '.join(str(x) for x in runs)\n\ndef rle_decode(mask_rle, shape=SHAPE):\n    '''\n    mask_rle: run-length as string formated: [start0] [length0] [start1] [length1]... in 1d array\n    shape: (height,width) of array to return \n    Returns numpy array according to the shape, 1 - mask, 0 - background\n    '''\n    s = mask_rle.split()\n    # gets starts & lengths 1d arrays \n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0::2], s[1::2])]\n    starts -= 1\n    # gets ends 1d array\n    ends = starts + lengths\n    # creates blank mask image 1d array\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    # sets mark pixles\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    # reshape as a 2d mask image\n    return img.reshape(shape).T  # Needed to align to RLE direction\n\ndef masks_as_image(in_mask_list, shape=SHAPE):\n    '''Take the individual ship masks and create a single mask array for all ships\n    in_mask_list: pd Series: [idx0] [RLE string0]...\n    Returns numpy array as (shape.h, sahpe.w, 1)\n    '''\n    all_masks = np.zeros(shape, dtype = np.int16)\n    # if isinstance(in_mask_list, list):\n    for mask in in_mask_list:\n        if isinstance(mask, str):\n            all_masks += rle_decode(mask)\n    return np.expand_dims(all_masks, -1)\n\ndef shows_decode_encode(image_id, path=TRAIN_DATA_PATH):\n    '''Show image, ship mask, and encoded/decoded result\n    '''\n    fig, axarr = plt.subplots(1, 3, figsize = (10, 5))\n    # image\n    img_0 = imread(os.path.join(path, image_id))\n    axarr[0].imshow(img_0)\n    axarr[0].set_title(image_id)\n    \n    # input mask\n    rle_1 = masks.query('ImageId==\"{}\"'.format(image_id))['EncodedPixels']\n    img_1 = masks_as_image(rle_1)\n    # takes 2d array (shape.h, sahpe.w)\n    axarr[1].imshow(img_1[:, :, 0])\n    axarr[1].set_title('Ship Mask')\n    \n    # encode & decode mask \n    rle_2 = multi_rle_encode(img_1)\n    img_2 = masks_as_image(rle_2)\n    axarr[2].imshow(img_0)\n    axarr[2].imshow(img_2[:, :, 0], alpha=0.3)\n    axarr[2].set_title('Encoded & Decoded Mask')\n    plt.show()\n    print(image_id , ' Check Decoding->Encoding',\n          'RLE_0:', len(rle_1), '->',\n          'RLE_1:', len(rle_2))\n\n# inspects a few example\nshows_decode_encode('000155de5.jpg')\nshows_decode_encode('00003e153.jpg')\nprint('It could be different when there is no mask.')\nshows_decode_encode('00021ddc3.jpg')\nprint('It could be different when there are masks overlapped.')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9c312f477005641cd3d4a4eeb28ca92ad668ab3c"},"cell_type":"markdown","source":"## Split Test and Validation datasets\n"},{"metadata":{"trusted":true,"_uuid":"5f7da5d8ff0061fc809ef9edb9698e228d6f762e"},"cell_type":"code","source":"# check if a mask has a ship \nmasks['ships'] = masks['EncodedPixels'].map(lambda encoded_pixels: 1 if isinstance(encoded_pixels, str) else 0)\n# sum ship# by ImageId and create the unique image id/mask list\nstart_time = time.time()\nunique_img_ids = masks.groupby('ImageId').agg({'ships': 'sum'})\nunique_img_ids['RleMaskList'] = masks.groupby('ImageId')['EncodedPixels'].apply(list)\nunique_img_ids = unique_img_ids.reset_index()\nend_time = time.time() - start_time\nprint(\"unique_img_ids groupby took: {}\".format(end_time))\n\n# Only care image with ships\nunique_img_ids = unique_img_ids[unique_img_ids['ships'] > 0]\nunique_img_ids['ships'].hist()\nunique_img_ids.sample(3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"77fa915c8c928f19a27e32e656d119ce465d049b"},"cell_type":"code","source":"# split to training & validation sets \nfrom sklearn.model_selection import train_test_split\ntrain_ids, val_ids = train_test_split(unique_img_ids, \n                 test_size = TRAINING_VALIDATION_RATIO, \n                 stratify = unique_img_ids['ships'])\nprint(train_ids.shape[0], 'training masks')\nprint(val_ids.shape[0], 'validation masks')\ntrain_ids['ships'].hist()\nval_ids['ships'].hist()\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"534bf07e33f0932b2272d8ab40e7f8e67a9bbdca"},"cell_type":"markdown","source":"# Mask R-CNN model\nThis project uses [Mask R-CNN for object detection and instance segmentation on Keras and TensorFlow](https://github.com/matterport/Mask_RCNN) for the task, with minor changes.\n* Forked the github project for customization: [forked Mask_RCNN](https://github.com/samlin001/Mask_RCNN)  \n* Add [SAVE_BEST_ONLY](https://keras.io/callbacks/) configuration to allow more than 17-epochs training. Because each Kaggle kernel has 5.2GB disk space limitation, and each epoch weights file is about 250MB. \n\n## Import Mask R-CNN mode\nDownload and import Mask R-CNN mode."},{"metadata":{"trusted":true,"_uuid":"2bf4b1b2e24e9d212210d635f17a15eeb3e11dc0"},"cell_type":"code","source":"# if to clone Mask_R-CNN git when it exists \nUPDATE_MASK_RCNN = False\n\nos.chdir(WORKING_DIR)\nif UPDATE_MASK_RCNN:\n    !rm -rf {MASK_RCNN_PATH}\n\n# Downlaod Mask RCNN code to a local folder \nif not os.path.exists(MASK_RCNN_PATH):\n    ! wget https://github.com/samlin001/Mask_RCNN/archive/master.zip -O Mask_RCNN-master.zip\n    ! unzip Mask_RCNN-master.zip 'Mask_RCNN-master/mrcnn/*'\n    ! rm Mask_RCNN-master.zip\n\n# Import Mask RCNN\nsys.path.append(MASK_RCNN_PATH)  # To find local version of the library\nfrom mrcnn.config import Config\nfrom mrcnn import utils\nimport mrcnn.model as modellib\nfrom mrcnn import visualize\nfrom mrcnn.model import log    ","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"67ffe9eba1d347b11c05f733a1bf5112de546e82"},"cell_type":"markdown","source":"## Transform dataset\nAirbusShipDetectionChallengeDataset class enables Mask R-CNN model to load Airbus Ship train v2 dataset and masks.   \nThis [balloon color splash sample tutorial](https://engineering.matterport.com/splash-of-color-instance-segmentation-with-mask-r-cnn-and-tensorflow-7c761e238b46) provides excellent guidances and illustration of Mask R-CNN. "},{"metadata":{"trusted":true,"_uuid":"5767146c1a5ab4663dce7e5e59bf00792b840935"},"cell_type":"code","source":"class AirbusShipDetectionChallengeDataset(utils.Dataset):\n    \"\"\"Airbus Ship Detection Challenge Dataset\n    \"\"\"\n    def __init__(self, image_file_dir, ids, masks, image_width=IMAGE_WIDTH, image_height=IMAGE_HEIGHT):\n        super().__init__(self)\n        self.image_file_dir = image_file_dir\n        self.ids = ids\n        self.masks = masks\n        self.image_width = image_width\n        self.image_height = image_height\n        \n        # Add classes\n        self.add_class(SHIP_CLASS_NAME, 1, SHIP_CLASS_NAME)\n        self.load_dataset()\n        \n    def load_dataset(self):\n        \"\"\"Load dataset from the path\n        \"\"\"\n        # Add images\n        for index, row in self.ids.iterrows():\n            image_id = row['ImageId']\n            image_path = os.path.join(self.image_file_dir, image_id)\n            rle_mask_list = row['RleMaskList']\n            #print(rle_mask_list)\n            self.add_image(\n                SHIP_CLASS_NAME,\n                image_id=image_id,\n                path=image_path,\n                width=self.image_width, height=self.image_height,\n                rle_mask_list=rle_mask_list)\n\n    def load_mask(self, image_id):\n        \"\"\"Generate instance masks for shapes of the given image ID.\n        \"\"\"\n        info = self.image_info[image_id]\n        rle_mask_list = info['rle_mask_list']\n        mask_count = len(rle_mask_list)\n        mask = np.zeros([info['height'], info['width'], mask_count],\n                        dtype=np.uint8)\n        i = 0\n        for rel in rle_mask_list:\n            if isinstance(rel, str):\n                np.copyto(mask[:,:,i], rle_decode(rel))\n            i += 1\n        \n        # Return mask, and array of class IDs of each instance. Since we have\n        # one class ID only, we return an array of 1s\n        return mask.astype(np.bool), np.ones([mask.shape[-1]], dtype=np.int32)\n    \n    def image_reference(self, image_id):\n        \"\"\"Return the path of the image.\"\"\"\n        info = self.image_info[image_id]\n        if info['source'] == SHIP_CLASS_NAME:\n            return info['path']\n        else:\n            super(self.__class__, self).image_reference(image_id)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"39e7ebcb85fa36dbd5140753e011b77afb3cfa02"},"cell_type":"markdown","source":"## Model configurations\nOverride [the default configurations](https://github.com/samlin001/Mask_RCNN/blob/master/mrcnn/config.py) for the challenge."},{"metadata":{"trusted":true,"_uuid":"d65d5335db367f346c2b8c71859a102c2ca44884"},"cell_type":"code","source":"class AirbusShipDetectionChallengeGPUConfig(Config):\n    \"\"\"\n    Configuration of Airbus Ship Detection Challenge Dataset \n    Overrides values in the base Config class.\n    From https://github.com/samlin001/Mask_RCNN/blob/master/mrcnn/config.py\n    \"\"\"\n    # https://www.kaggle.com/docs/kernels#technical-specifications\n    NAME = 'ASDC_GPU'\n    # NUMBER OF GPUs to use.\n    GPU_COUNT = 1\n    IMAGES_PER_GPU = 2\n    \n    NUM_CLASSES = 2  # ship or background\n    IMAGE_MIN_DIM = IMAGE_WIDTH\n    IMAGE_MAX_DIM = IMAGE_WIDTH\n    STEPS_PER_EPOCH = 300\n    VALIDATION_STEPS = 50\n    SAVE_BEST_ONLY = True\n    \n    # Minimum probability value to accept a detected instance\n    # ROIs below this threshold are skipped\n    DETECTION_MIN_CONFIDENCE = 0.95\n\n    # Non-maximum suppression threshold for detection\n    # Keep it small to merge overlapping ROIs \n    DETECTION_NMS_THRESHOLD = 0.05\n\n    \nconfig = AirbusShipDetectionChallengeGPUConfig()\nconfig.display()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"216e602cbe93af42697e9a3783d814fd086726c1"},"cell_type":"markdown","source":"## Prepare and load training dataset\n"},{"metadata":{"trusted":true,"_uuid":"69e444fa1d9061b07175fd833120f42527d33388"},"cell_type":"code","source":"start_time = time.time()\n# Training dataset.\ndataset_train = AirbusShipDetectionChallengeDataset(image_file_dir=TRAIN_DATA_PATH, ids=train_ids, masks=masks)\ndataset_train.prepare()\n\n# Validation dataset\ndataset_val = AirbusShipDetectionChallengeDataset(image_file_dir=TRAIN_DATA_PATH, ids=val_ids, masks=masks)\ndataset_val.prepare()\n\n# Load and display random samples\nimage_ids = np.random.choice(dataset_train.image_ids, 3)\nfor image_id in image_ids:\n    image = dataset_train.load_image(image_id)\n    mask, class_ids = dataset_train.load_mask(image_id)\n    visualize.display_top_masks(image, mask, class_ids, dataset_train.class_names, limit=1)\n\nend_time = time.time() - start_time\nprint(\"dataset prepare: {}\".format(end_time))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5cbafccaad2be91cc9b57d841b6557b56f6ba8f9"},"cell_type":"markdown","source":"## Load pre-trained wieghts\nPre-trained weights for MS COCO is loaded to provide a better straing point for training. "},{"metadata":{"trusted":true,"_uuid":"699ad18606e3c2b9d430b967c984f1965514d66b"},"cell_type":"code","source":"start_time = time.time()\nmodel = modellib.MaskRCNN(mode=\"training\", config=config, model_dir=WORKING_DIR)\n\nimport errno\ntry:\n    weights_path = model.find_last()\n    load_weights = True\nexcept FileNotFoundError:\n    # if there is no previous trained weights, load COCO\n    load_weights = True\n    weights_path = COCO_WEIGHTS_PATH\n    utils.download_trained_weights(weights_path)\n    \nif load_weights:\n    print(\"Loading weights: \", weights_path)\n    model.load_weights(weights_path, by_name=True, exclude=[\n                \"mrcnn_class_logits\", \"mrcnn_bbox_fc\",\n                \"mrcnn_bbox\", \"mrcnn_mask\"])\n\nend_time = time.time() - start_time\nprint(\"loading weights: {}\".format(end_time))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7c376a3ba3bcc0127a903383e9656f726c17d479"},"cell_type":"markdown","source":"# Train the model"},{"metadata":{"trusted":true,"_uuid":"f00d812de48f9cbc99b9db7ccec54dbff643ac64"},"cell_type":"code","source":"\"\"\"Train the model.\"\"\"\nstart_time = time.time()    \nmodel.train(dataset_train, dataset_val,\n            learning_rate=config.LEARNING_RATE * 1.5,\n            epochs=21,\n            layers='all')\nend_time = time.time() - start_time\nprint(\"Train model: {}\".format(end_time))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ca6f0db4d5a282caf76adcc9fd27e600fbbd28b9"},"cell_type":"markdown","source":"# Inference\n"},{"metadata":{"trusted":true,"_uuid":"62d99adbb8c5b7eaf19b1f731acbb01f87b24553"},"cell_type":"code","source":"class InferenceConfig(AirbusShipDetectionChallengeGPUConfig):\n    GPU_COUNT = 1\n    # 1 image for inference \n    IMAGES_PER_GPU = 1\n\ninference_config = InferenceConfig()\n\n# create a model in inference mode\ninfer_model = modellib.MaskRCNN(mode=\"inference\", \n                          config=inference_config,\n                          model_dir=WORKING_DIR)\n\nmodel_path = infer_model.find_last()\n\n# Load trained weights\nprint(\"Loading weights from \", model_path)\ninfer_model.load_weights(model_path, by_name=True)\n\n\n# Test on a random image\nimage_id = np.random.choice(dataset_val.image_ids)\noriginal_image, image_meta, gt_class_id, gt_bbox, gt_mask =\\\n    modellib.load_image_gt(dataset_val, inference_config, \n                           image_id, use_mini_mask=False)\n\nlog(\"original_image\", original_image)\nlog(\"image_meta\", image_meta)\nlog(\"gt_class_id\", gt_class_id)\nlog(\"gt_bbox\", gt_bbox)\nlog(\"gt_mask\", gt_mask)\n\nvisualize.display_instances(original_image, gt_bbox, gt_mask, gt_class_id, \n                            dataset_train.class_names, figsize=(8, 8))\n\nresults = infer_model.detect([original_image], verbose=1)\n\nr = results[0]\nvisualize.display_instances(original_image, r['rois'], r['masks'], r['class_ids'], \n                            dataset_val.class_names, r['scores'])\n\n# Compute VOC-Style mean Average Precision @ IoU=0.5\n# Running on a few images. Increase for better accuracy.\nimage_ids = np.random.choice(dataset_val.image_ids, 20)\nAPs = []\ninference_start = time.time()\nfor image_id in image_ids:\n    # Load image and ground truth data\n    image, image_meta, gt_class_id, gt_bbox, gt_mask =\\\n        modellib.load_image_gt(dataset_val, inference_config,\n                               image_id, use_mini_mask=False)\n    molded_images = np.expand_dims(modellib.mold_image(image, inference_config), 0)\n    # Run object detection\n    results = infer_model.detect([image], verbose=1)\n    r = results[0]\n    visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], \n                            dataset_val.class_names, r['scores'])\n\n    # Compute AP\n    AP, precisions, recalls, overlaps =\\\n        utils.compute_ap(gt_bbox, gt_class_id, gt_mask,\n                         r[\"rois\"], r[\"class_ids\"], r[\"scores\"], r['masks'])\n    APs.append(AP)\n\ninference_end = time.time()\nprint('Inference Time: %0.2f Minutes'%((inference_end - inference_start)/60))\nprint(\"mAP: \", np.mean(APs))\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fe91b26f605f3ba08ce222d8b4068205fe3c1028"},"cell_type":"markdown","source":"# Clean up"},{"metadata":{"trusted":true,"_uuid":"152d9d0d8332c87958ebe6ab95e9751ba06c97ec"},"cell_type":"code","source":"!rm -rf {MASK_RCNN_PATH}","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}