{"cells":[{"metadata":{},"cell_type":"markdown","source":"<div style=\"text-align: center\"><h2><font color=\"sky_blue\">iWildCam 2020 - FGVC7</font></h2></div>\n<div style=\"text-align: center\"><h3><font color=\"sky_blue\">Categorize animals in the wild</font></h3></div>\n\n"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd \nimport os\nimport json\nimport glob\nimport random\nfrom IPython.display import display, display_markdown\nfrom math import floor\nfrom matplotlib import pyplot as plt\nimport matplotlib.image as mpimg\nimport matplotlib.patches as patches\nfrom mpl_toolkits.axes_grid1 import ImageGrid\nimport seaborn as sns\nfrom PIL import Image\nfrom tqdm.notebook import tqdm","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"img = \"/kaggle/input/iwildcam-2020-fgvc7/train/92b8a1d0-21bc-11ea-a13a-137349068a90.jpg\"\n_ = plt.figure(figsize = (15,20))\n_ = plt.axis('off')\n_ = plt.imshow(mpimg.imread(img)[100:-100])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This kernel is made to provide a quick overview of the content of the data provided. Includes-\n* Sample data of each of the meta data files \n* Code to display multiple training images with the its catergory name\n* Distribution of the classes\n* Bounding box annotation\n* Extract animals/humans to feed to your classifier  \n* New dataset for easier classificaton\n"},{"metadata":{},"cell_type":"markdown","source":"<div class=\"alert alert-block alert-success\">\nI hope this kernel gives you a good overview of the data. Thanks for reading! Consider an <b>upvote!</b> if it helps, it helps me :) \n</div>"},{"metadata":{},"cell_type":"markdown","source":"<div class=\"alert alert-block alert-warning\">\n<b>Note:</b>  Do not run the direcory listing cod provided. It takes too long as it tries to print all of the training and test data files\n</div>"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","collapsed":true,"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":false},"cell_type":"markdown","source":"## Meta data files"},{"metadata":{"trusted":true},"cell_type":"code","source":"os.listdir(\"/kaggle/input/iwildcam-2020-fgvc7\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<div class=\"alert alert-block alert-warning\">\n<b>Note:</b>  pd.read_json() is tricky as you have different data in the json. Its easier to convert to dic\n</div>"},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Number of train images: \", len(glob.glob(f'/kaggle/input/iwildcam-2020-fgvc7/train/*')))\nprint(\"Number of test images: \", len(glob.glob(f'/kaggle/input/iwildcam-2020-fgvc7/test/*')))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Training Annotaions"},{"metadata":{"trusted":true},"cell_type":"code","source":"with open('/kaggle/input/iwildcam-2020-fgvc7/iwildcam2020_train_annotations.json') as json_data:\n    train_annotations = json.load(json_data)\n    print(train_annotations.keys())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_cat = pd.DataFrame(train_annotations[\"categories\"])\ndisplay(f\"Total Categories: {df_cat.name.nunique()}\")\ndisplay(df_cat.sample(5))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display(\"Samples of annotations and images\")\ndf_train_annotations = pd.DataFrame(train_annotations[\"annotations\"])\ndisplay(df_train_annotations.sample())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Megadetector Results"},{"metadata":{"trusted":true},"cell_type":"code","source":"with open('/kaggle/input/iwildcam-2020-fgvc7/iwildcam2020_megadetector_results.json') as json_data:\n    megadetector_results = json.load(json_data)\n    print(megadetector_results.keys())\nprint(megadetector_results['info'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_detections = pd.DataFrame(megadetector_results[\"images\"])\nprint(f'detection categories :\\n {megadetector_results[\"detection_categories\"]}')\nprint(f'detection output :\\n {df_detections.head()}')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Test Information"},{"metadata":{"trusted":true},"cell_type":"code","source":"with open('/kaggle/input/iwildcam-2020-fgvc7/iwildcam2020_test_information.json') as json_data:\n    test_info = json.load(json_data)\n    print(test_info.keys())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f'test images :\\n {test_info[\"images\"][0]}')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Image Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"train = glob.glob(f'/kaggle/input/iwildcam-2020-fgvc7/train/*')\nprint(\"Train Path \\n\", train[0])\ntest = glob.glob(f'/kaggle/input/iwildcam-2020-fgvc7/test/*')\nprint(\"Test Path \\n\", test[0])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## View Images"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"def plot_images(rows,cols):\n    fig = plt.figure(figsize=(15., 12.))\n    grid = ImageGrid(fig, 111,  # similar to subplot(111)\n                 nrows_ncols=(rows, cols),  # creates 5x5 grid of axes\n                 axes_pad=0.3,  # pad between axes in inch.\n                 )\n\n    for ax, img in zip(grid, random.sample(train, rows*cols)):\n        image_id = img.split('/')[-1].split('.')[0]\n        cat_id = df_train_annotations[df_train_annotations.image_id == image_id].category_id\n        cat = df_cat[df_cat.id == int(cat_id)].name.values[0]\n        # Iterating over the grid returns the Axes.\n        _ = ax.set_title(str(cat))\n        _ = ax.imshow(mpimg.imread(img))\n        _ = ax.axis('off')\n\n    _ = plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_images(3,3)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## BBoxes Visualization"},{"metadata":{"trusted":true},"cell_type":"code","source":"def draw_bbox(img_path = \"/kaggle/input/iwildcam-2020-fgvc7/train/92b8a1d0-21bc-11ea-a13a-137349068a90.jpg\"):\n    \n    img_id = img_path.split('/')[-1].split('.')[0] \n    img = mpimg.imread(img_path)\n    detections = df_detections[df_detections.id==img_id].detections.values[0]\n    annotation = df_train_annotations[df_train_annotations.image_id == img_id]\n    \n    count = annotation['count'].values\n    cat_id = annotation.category_id\n    cat = df_cat[df_cat.id == int(cat_id)].name.values[0]\n    \n    _ = plt.figure(figsize = (15,20))\n    _ = plt.axis('off')\n    ax = plt.gca()\n    ax.text(10,100, f'{cat} {count}', fontsize=20, color='fuchsia')\n\n    for detection in detections:\n        # ref - https://github.com/microsoft/CameraTraps/blob/e530afd2e139580b096b5d63f0d7ab9c91cbc7a4/visualization/visualization_utils.py#L392\n        x_rel, y_rel, w_rel, h_rel = detection['bbox']    \n        img_height, img_width, _ = img.shape\n        x = x_rel * img_width\n        y = y_rel * img_height\n        w = w_rel * img_width\n        h = h_rel * img_height\n        \n        cat = 'animal' if detection['category'] == \"1\" else 'human'\n        bbox = patches.FancyBboxPatch((x,y), w, h, alpha=0.8, linewidth=6, capstyle='projecting', edgecolor='fuchsia', facecolor=\"none\")\n        \n        ax.text(x+1.5, y-8, f'{cat} {detection[\"conf\"]}', fontsize=10, bbox=dict(facecolor='fuchsia', alpha=0.8, edgecolor=\"none\"))\n        ax.add_patch(bbox)\n\n    _ = plt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_path = \"/kaggle/input/iwildcam-2020-fgvc7/train/92b8a1d0-21bc-11ea-a13a-137349068a90.jpg\"\ndraw_bbox(img_path)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Animal Distribution\nNow that we have checked out the data, lets analyze what we have!"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train_annotations.category_id.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(40,5))\ndf_cat_dist = df_train_annotations.category_id.value_counts()\nprint(f\"Excluding {df_cat_dist[0]} images from the empty class in the barplot visualization\")\ndf_cat_dist = df_cat_dist[1:]\nchart = sns.barplot(y=df_cat_dist.values, x=df_cat_dist.index, orient='v')\n_ = chart.set_xticklabels(chart.get_xticklabels(), rotation=90)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"You can notice that there is so a huge imbalance in the classes.   \nThis is very expected, what are the odds of catching an Yeti in one of these cams 😉"},{"metadata":{},"cell_type":"markdown","source":"## Extract Objects"},{"metadata":{"trusted":true},"cell_type":"code","source":"def extract_objects(img_path = \"/kaggle/input/iwildcam-2020-fgvc7/train/92b8a1d0-21bc-11ea-a13a-137349068a90.jpg\", show=False):\n    objects = []\n    confidences = []\n    categories = []\n    \n    img_id = img_path.split('/')[-1].split('.')[0] \n    img = np.array(mpimg.imread(img_path))\n    if (df_detections[df_detections.id==img_id].detections.values):\n        pass\n    else:\n        return None\n    detections = df_detections[df_detections.id==img_id].detections.values[0]\n    annotation = df_train_annotations[df_train_annotations.image_id == img_id]\n    cat_id = annotation.category_id\n    cat = df_cat[df_cat.id == int(cat_id)].name.values[0]\n    \n    for idx, detection in enumerate(detections):\n        # save confidence\n        confidences.append(detection[\"conf\"])\n        if detection['category'] == \"1\":\n            categories.append(cat)\n        else:\n            categories.append('human')\n\n        x_rel, y_rel, w_rel, h_rel = detection['bbox']    \n        img_height, img_width, _ = img.shape\n        x = floor(x_rel * img_width)\n        y = floor(y_rel * img_height)\n        w = floor(w_rel * img_width)\n        h = floor(h_rel * img_height)\n\n        obj = img[int(y):int(y+h),int(x):int(x+w)]\n        objects.append(obj)\n        if show:\n            _ = plt.figure()\n            _ = plt.xticks([])\n            _ = plt.yticks([])\n            _ = plt.imshow(obj)\n    \n    return objects, categories, confidences","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"_ = extract_objects(show=True)  ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Create new cropped dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"def save_data(img_path):\n    img_id = img_path.split('/')[-1].split('.')[0] \n    objects, cats, confs = extract_objects(img_path)\n    for i in range(len(objects)):\n        meta_df.loc[len(meta_df)] = [f'{img_id}_{i}', img_id, cats[i], confs[i]]\n        try:\n            mpimg.imsave(f'train/{img_id}_{i}.jpg', objects[i])\n        except:\n            pass","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}