{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # numeric library\nimport pandas as pd # data structure library\n\nimport matplotlib.pyplot as plt # plot library","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-12-27T21:19:49.930389Z","iopub.execute_input":"2021-12-27T21:19:49.931654Z","iopub.status.idle":"2021-12-27T21:19:49.960583Z","shell.execute_reply.started":"2021-12-27T21:19:49.931500Z","shell.execute_reply":"2021-12-27T21:19:49.959560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# reading the dataset\npath = \"../input/tensorflow-great-barrier-reef/\"\ntrain = pd.read_csv(path+\"train.csv\")\ntest = pd.read_csv(path+\"test.csv\")\n\n# dataset shape\nprint('Train Images: {}'.format(train.shape[0]))\nprint('Test Images: {}'.format(test.shape[0]))\n\n# how many images contain the starfish and how many does not\nprint('Train Images without Starfish: {} and Train Images with Starfish: {}'.format(train[train['annotations']=='[]'].shape[0], train[train['annotations']!='[]'].shape[0]))\nprint('Percentage of Images with Starfish: {:.2f}%'.format(train[train['annotations']!='[]'].shape[0]/train.shape[0]*100))","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:49.962410Z","iopub.execute_input":"2021-12-27T21:19:49.962886Z","iopub.status.idle":"2021-12-27T21:19:50.066362Z","shell.execute_reply.started":"2021-12-27T21:19:49.962853Z","shell.execute_reply":"2021-12-27T21:19:50.064140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Add images path to dataframe\ntrain[\"image_path\"] = \"../input/tensorflow-great-barrier-reef/train_images/video_\"+train[\"video_id\"].astype(str)+\"/\"+train[\"image_id\"].apply(lambda x: x.split(\"-\")[1])+\".jpg\"\n\n# eval annotations\ntrain[\"annotations\"] = train[\"annotations\"].apply(eval)\n\n# viewing some sample rows of the dataframe\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:50.067939Z","iopub.execute_input":"2021-12-27T21:19:50.068263Z","iopub.status.idle":"2021-12-27T21:19:50.542497Z","shell.execute_reply.started":"2021-12-27T21:19:50.068230Z","shell.execute_reply":"2021-12-27T21:19:50.541411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from collections import OrderedDict\ndef draw_bar_graph(ax, x, y, div_factor, *args):\n    d = dict(zip(x, y)) # creating a dictionary using the argument (x, y): x=key, y=value\n    d = OrderedDict(sorted(d.items())) # sorting the dictionary w.r.t. keys\n\n    width = 0.75 # the width of the bars \n\n    ax.bar(list(d.keys()), list(d.values()), width=width, align='center', edgecolor='darkblue', facecolor='lightblue')\n    ax.set_xticks(list(d.keys()), list(d.keys()))\n\n    # this draws the labels\n    for i, v in d.items():\n        ax.text(i-width/div_factor, v+10, str(v), color='black', fontweight='bold')\n        \n    if len(args) == 3:\n        ax.set_title('{}: {}'.format(args[2], np.dot(list(d.values()), list(d.keys()))))\n     \n    ax.set_xlabel(args[0])\n    ax.set_ylabel(args[1])\n    return ax","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:50.544547Z","iopub.execute_input":"2021-12-27T21:19:50.544783Z","iopub.status.idle":"2021-12-27T21:19:50.554594Z","shell.execute_reply.started":"2021-12-27T21:19:50.544754Z","shell.execute_reply":"2021-12-27T21:19:50.553713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(1, 2, figsize=(12.5, 5))\nimage_count = train['video_id'].value_counts()\naxes[0] = draw_bar_graph(axes[0], image_count.index, image_count.values, 10, 'Video Id', 'Number of Images')\n\n# count of images with/without starfish\ntemp_series1 = train[train['annotations'].str.len()==0].groupby('video_id').count()['annotations']\ntemp_series2 = train[train['annotations'].str.len()!=0].groupby('video_id').count()['annotations']\n\n# creating a dataframe\ntemp_df = pd.DataFrame({ 'Starfish (without)': temp_series1, 'Starfish (with)': temp_series2 })\n\nvideo_id = [0,1,2]\n\n# From raw value to percentage\ntotals = [i+j for i,j in zip(temp_df['Starfish (without)'], temp_df['Starfish (with)'])]\ngreenBars = [i / j * 100 for i,j in zip(temp_df['Starfish (without)'], totals)]\norangeBars = [i / j * 100 for i,j in zip(temp_df['Starfish (with)'], totals)]\n \n# plot\nwidth = 0.75\n# Create green Bars\naxes[1].bar(video_id, greenBars, color='#119999', edgecolor='white', width=width, label='Starfish (without)')\n# Create orange Bars\naxes[1].bar(video_id, orangeBars, bottom=greenBars, color='#f9bc86', edgecolor='white', width=width, label='Starfish (with)')\n\nfor i in video_id:\n    axes[1].text(i-width/5, greenBars[i]-50, '{:.2f}%'.format(greenBars[i]), color='black', fontweight='bold')\n    axes[1].text(i-width/5, greenBars[i]+3, '{:.2f}%'.format(orangeBars[i]), color='black', fontweight='bold')\n    \n# Custom x axis\naxes[1].set_xticks(video_id, video_id)\naxes[1].set_xlabel(\"Video id\")\naxes[1].set_ylabel(\"Percentage of Images\")\n\n# Add a legend\n#axes[1].legend(loc='upper left', bbox_to_anchor=(1,1), ncol=1)\naxes[1].legend(loc='lower right')\n\nplt.tight_layout()\nplt.show()\nplt.close() # doesn't hold the image in memory anymore","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:50.555895Z","iopub.execute_input":"2021-12-27T21:19:50.556643Z","iopub.status.idle":"2021-12-27T21:19:51.104586Z","shell.execute_reply.started":"2021-12-27T21:19:50.556603Z","shell.execute_reply":"2021-12-27T21:19:51.103250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(10, 7.5))\n    \nstarfish_count = train[train.annotations.str.len()!=0].annotations.str.len().value_counts()\ndraw_bar_graph(ax, starfish_count.index, starfish_count.values, 3, 'Number of Starfish per Image', 'Number of Images', 'Distribution of starfish numbers across images\\nTotal starfish in all images')\n\nplt.tight_layout()\nplt.show()\nplt.close() # doesn't hold the image in memory anymore","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:51.105921Z","iopub.execute_input":"2021-12-27T21:19:51.106579Z","iopub.status.idle":"2021-12-27T21:19:51.539895Z","shell.execute_reply.started":"2021-12-27T21:19:51.106524Z","shell.execute_reply":"2021-12-27T21:19:51.539231Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# creating a new dataframe temp_df just separating the bounding box information\n# this is to just create the histogram of bounding box sizes\nout = {}\nfor i, (k, v) in enumerate(train[train['annotations'].str.len()!=0]['annotations'].items()):\n    temp_df = pd.DataFrame(v)\n    if temp_df.empty:\n        out[(i, k)] = pd.DataFrame(index=[0], columns=['Id'])\n    else:\n        out[(i, k)] = temp_df\ntemp_df = pd.concat(out, sort=True).reset_index(level=[0,2], drop=True)\n# temp_df will contain all the 11898 starfish bounding box details\ntemp_df['area'] = temp_df['height'] * temp_df['width']\ntemp_df['aspect_ratio'] = temp_df['width'] / temp_df['height']\nprint('Number of bounding boxes (which is also the number of starfish): {}'.format(temp_df.shape[0]))\ntemp_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:51.540991Z","iopub.execute_input":"2021-12-27T21:19:51.541369Z","iopub.status.idle":"2021-12-27T21:19:55.989121Z","shell.execute_reply.started":"2021-12-27T21:19:51.541330Z","shell.execute_reply":"2021-12-27T21:19:55.988175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(2,2, figsize=(15, 10))\n\n# drawing histograms by dividing into different bounding box area ranges\n# gives an idea how big/small starfish objects are within the images\ntemp_df[temp_df['area']<=1600]['area'].hist(ax = axes[0, 0]) # number of bounding boxes where area < 1600 pixel^2\ntemp_df[(temp_df['area']>1600)&(temp_df['area']<=5000)]['area'].hist(ax = axes[0, 1]) # number of bounding boxes where area > 1600 pixel^2 and <= 5000 pixel^2\ntemp_df[(temp_df['area']>5000)&(temp_df['area']<=10000)]['area'].hist(ax = axes[1, 0]) # ...\ntemp_df[(temp_df['area']>10000)]['area'].hist(ax = axes[1, 1]) # ...\n\n# setting x and y labels of the figures\nfor i in range(2):\n    for j in range(2):\n        axes[i, j].set_xlabel('Bounding box area, (pixel)$^2$')\n        axes[i, j].set_ylabel('Frequency')\n        \nplt.tight_layout()\nplt.show()\nplt.close()","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:55.990744Z","iopub.execute_input":"2021-12-27T21:19:55.990989Z","iopub.status.idle":"2021-12-27T21:19:57.369859Z","shell.execute_reply.started":"2021-12-27T21:19:55.990956Z","shell.execute_reply":"2021-12-27T21:19:57.368881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# looking at the various aspect ratios of the bounding boxes containing starfish object\nfig, axes = plt.subplots(1,2, sharey=True, figsize=(12.5, 5))\n\ntemp_df[temp_df['aspect_ratio'] < 1.0]['aspect_ratio'].hist(ax=axes[0])\ntemp_df[temp_df['aspect_ratio'] >= 1.0]['aspect_ratio'].hist(ax=axes[1])\n\naxes[0].set_xlabel('Aspect Ratio')\naxes[1].set_xlabel('Aspect Ratio')\naxes[0].set_ylabel('Frequency')\nplt.tight_layout()\nplt.show()\nplt.close()","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:57.371242Z","iopub.execute_input":"2021-12-27T21:19:57.371519Z","iopub.status.idle":"2021-12-27T21:19:57.796795Z","shell.execute_reply.started":"2021-12-27T21:19:57.371466Z","shell.execute_reply":"2021-12-27T21:19:57.795825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('The image ID with the largest bounding box area: {}'.format(temp_df['area'].idxmax()))\n# we have seen an image can contain upto 18 starfish(es): finding one such image id\nprint('The image ID with the highest number of starfish: {}'.format(train['annotations'].str.len().idxmax()))","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:57.799223Z","iopub.execute_input":"2021-12-27T21:19:57.799626Z","iopub.status.idle":"2021-12-27T21:19:57.822395Z","shell.execute_reply.started":"2021-12-27T21:19:57.799591Z","shell.execute_reply":"2021-12-27T21:19:57.821092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from PIL import Image, ImageDraw\n\n# draw an image with bounding boxes: argument is the dataframe and image id\ndef img_viz(df, id):\n    image = df['image_path'][id]\n    img = Image.open(image)\n    \n    for box in df['annotations'][id]:\n        shape = [box['x'], box['y'], box['x']+box['width'], box['y']+box['height']]\n        ImageDraw.Draw(img).rectangle(shape, outline =\"red\", width=3)\n    return img\n\n# in this part, we draw a few images to get an idea of the image quality, surroundings, shapes of starfish inside it, etc.\nfig, axes = plt.subplots(2,2, figsize=(15, 10))\n\n# draw an image with starfish\nimg1 = img_viz(train, id=5474)\naxes[0, 0].set_title('An image with starfish')\naxes[0, 0].imshow(img1)\n\n# draw an image with the largest bounding box containing starfish\nimg2 = img_viz(train, id=7336)\naxes[0, 1].set_title('The image with the largest bounding box containing starfish')\naxes[0, 1].imshow(img2)\n\n# draw an image with the highest number of starfish\nimg3 = img_viz(train, id=12679)\naxes[1, 0].set_title('One of three images with the highest number (18) of starfish')\naxes[1, 0].imshow(img3)\n\n# draw an image without a starfish as well\nimg4 = img_viz(train, id=1)\naxes[1, 1].set_title('An image with no starfish')\naxes[1, 1].imshow(img4)\n\nplt.tight_layout()\nplt.show()\nplt.close() # doesn't hold the image in memory anymore","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:19:57.823431Z","iopub.execute_input":"2021-12-27T21:19:57.823654Z","iopub.status.idle":"2021-12-27T21:19:59.548326Z","shell.execute_reply.started":"2021-12-27T21:19:57.823625Z","shell.execute_reply":"2021-12-27T21:19:59.547155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# in this part, we draw a few images to get an idea of the image quality, surroundings, shapes of starfish inside it, etc.\nfig, axes = plt.subplots(1,1, figsize=(15, 10))\n\n# draw an image with starfish\nimg1 = img_viz(train, id=7336)\naxes.set_title('An image with starfish')\naxes.imshow(img1)\n\nplt.tight_layout()\nplt.show()\nplt.close()","metadata":{"execution":{"iopub.status.busy":"2021-12-27T21:21:36.899154Z","iopub.execute_input":"2021-12-27T21:21:36.899469Z","iopub.status.idle":"2021-12-27T21:21:37.723661Z","shell.execute_reply.started":"2021-12-27T21:21:36.899437Z","shell.execute_reply":"2021-12-27T21:21:37.722766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2>Summary</h2>\n<ul>\n    <li>The images vary in quality (e.g., clarity). The background colour seems to be affected as well (not always sea blue?). </li>\n    <li>The surroudnings should definitely be considered in terms of choosing the object (starfish) detection algorithm - also if applying 'transfer learning' (pre-built model for object detection) too.</li>\n    <li>There are different bounding box sizes within the image. Some of them are very hard to identify with naked eye. Is there a need to apply 'image augmentation' techniques especially for starfish bounding boxes (the larger ones?) that are not abundant in quantity?</li>\n    <li>Semantic segmenation algorighms for only learning the 'semantic' inforamtion of the starfish. In other words, no need to differentiate between multiple starfish. As long as, a starfish object can be detected and localised within the image correctly, the task will be achieved.</li>\n    <li>The projection angle of the scene seems to be important too, e.g., the bigger starfish will be easier to identify than the distant ones. Is there a way to differentiate between different projections, e.g., presence of prodominant blue gives a notion of whether the image is taken from farther away (or difficult angle) than images where there is absence of blue as a predominant colour?</li>\n    <li>The initial choice of algorithm: Mask R-CNN algorithm?</li>\n</ul>","metadata":{}}]}