{"cells":[{"metadata":{},"cell_type":"markdown","source":"# About the notebook\nThis notebook visualized the accompanying instance masks for the iWildCam 2021 challenge.\nInstance masks are provided by the *DeepMAC* model from the paper [The surprising impact of mask-head architecture on novel class segmentation](https://arxiv.org/abs/2104.00613).\nDeepMAC was designed to produce accurate instance segmentation masks for unseen classes. \nFor this challenge, we use the best model from the paper (trained on all of COCO) and\ncombine it with detections from [MegaDetector](https://github.com/microsoft/CameraTraps/blob/master/megadetector.md).\nFor each detection in MegaDetector, there is an accompanying instance mask.\nThe format is described in detail [here](https://github.com/visipedia/iwildcam_comp#format-details)."},{"metadata":{},"cell_type":"markdown","source":"# Imports and Definitions"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import json\nimport os\nimport random\n\nimport cycler\nfrom matplotlib import colors\nfrom matplotlib import pyplot as plt\nimport matplotlib.patches as patches\nimport numpy as np\nfrom PIL import Image\nimport tensorflow as tf\n\n\nCOLOR_CYCLER = cycler.cycler(color=['tab:blue', 'tab:green', 'tab:orange',\n                                    'tab:red', 'tab:purple'])\n\n\ndef read_image(path):\n  with tf.io.gfile.GFile(path, 'rb') as f:\n    return np.array(Image.open(f))\n\n\ndef read_json(path):\n  with tf.io.gfile.GFile(path) as f:\n    return json.load(f)\n\n\ndef create_detection_map(annotations):\n  \"\"\"Creates a dict mapping IDs to detections.\"\"\"\n\n  ann_map = {}\n  for image in annotations['images']:\n    ann_map[image['id']] = image['detections']\n  return ann_map\n\n\ndef image_name_to_id(name):\n  return name.rstrip('.jpg')\n\n\ndef plot_image_annotation(image, detection_annotations, categories,\n                          instance_id_image, show_label=True):\n  \"\"\"Plot boxes and mask annotations for a given image.\n\n  Args:\n    image: An image array of shape [H, W, 3]\n    detection_annotations: A list of detections. Each detection is a dict\n      containing the keys 'category', 'bbox' and 'conf'.\n    categories: A dict mapping category IDs to names.\n    instance_id_image: An array of shape [H, W] containing the instance ID\n      at each pixel. IDs are expected to be 1-indexed, with 0 reserved for\n      the background.\n    show_label: bool, whether or not to show the label of each object\n      in the plot.\n  \"\"\"\n\n  fig, ax = plt.subplots(figsize=(12, 9))\n  image_height, image_width = image.shape[:2]\n\n  ax.imshow(image)\n\n  cycle_iter = COLOR_CYCLER()\n  for i, annotation in enumerate(detection_annotations):\n    xmin, ymin, width, height = annotation['bbox']\n    xmin *= image_width\n    ymin *= image_height\n    width *= image_width\n    height *= image_height\n\n    color = next(cycle_iter)['color']\n    rect = patches.Rectangle((xmin, ymin), width, height,\n                             linewidth=3, edgecolor=color, facecolor='none')\n    ax.add_patch(rect)\n    label = '{}:{:.2f}'.format(categories[annotation['category']],\n                               annotation['conf'])\n    if show_label:\n      ax.text(xmin, ymin - 5, label, fontsize=30, color='white',\n              bbox=dict(boxstyle='square,pad=0.0', facecolor=color, alpha=0.75,\n                        ec='none'))\n    \n    r, g, b, _ = colors.to_rgba(color)\n    color_array = np.array([r, g, b]).reshape(1, 1, 3)\n    color_image = np.ones((image_height, image_width, 3)) * color_array\n    mask = (instance_id_image == (i + 1)).astype(np.float32)[:, :, np.newaxis]\n    color_mask = np.concatenate([color_image, mask], axis=2)\n\n    ax.imshow(color_mask, alpha=0.5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Load metadata information"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Either train or test directory\nIMAGES_DIR = \"/kaggle/input/iwildcam2021-fgvc8/train\"\nBOX_ANNOTATION_FILE = \"/kaggle/input/iwildcam2021-fgvc8/metadata/iwildcam2021_megadetector_results.json\"\nMASKS_DIR = \"/kaggle/input/iwildcam2021-fgvc8/instance_masks/instance_masks\"\n\nimages = tf.io.gfile.listdir(IMAGES_DIR)\n\n# The annotations file contains annotations for all images in train and test\nannotations = read_json(BOX_ANNOTATION_FILE)\ndetection_map = create_detection_map(annotations)\nimage_ids = list(detection_map.keys())\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Visaulize a random sample\nSample a random image from `IMAGES_DIR` and visualize its instances\nif there are any."},{"metadata":{"trusted":true},"cell_type":"code","source":"image_name = random.choice(images)\nimage_path = os.path.join(IMAGES_DIR, image_name)\nimage_id = image_name_to_id(image_name)\nmask_path = os.path.join(MASKS_DIR, f'{image_id}.png')\n\nif image_id not in detection_map:\n  print(f'Image {image_name} is missing detection data.')\nelif len(detection_map[image_id]) == 0:\n  print(f'There are no detected objects in the image {image_name}.')\nelif not tf.io.gfile.exists(mask_path):\n  print(f'No mask found for {image_id}')\nelse:\n  detection_annotations = detection_map[image_name_to_id(image_name)]\n  image = read_image(image_path)\n  instance_id_image = read_image(mask_path)\n  plot_image_annotation(image, detection_annotations,\n                        annotations['detection_categories'], instance_id_image)","execution_count":null,"outputs":[]}],"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}