{"cells":[{"metadata":{"_uuid":"2fa6425fc80fd2ed626a31dd05c110489f5e40e8"},"cell_type":"markdown","source":"<h1><center>HumpBack Whale Identification</center></h1>"},{"metadata":{"_uuid":"aca8f0bc5ea4c8c1ead263d848239b1b49801044"},"cell_type":"markdown","source":"<img src=\"https://i.ibb.co/NpWmp2n/Whale-identity.jpg\" width=\"750px\"/>\n"},{"metadata":{"_uuid":"22bf70bc6fd19f9ff298aebbcbc49dcc03880555"},"cell_type":"markdown","source":"### Table Of Content:\n* [Introduction](#1)\n* [Submission Format](#2)\n* [Evaluation metric explained](#3)\n* [Whale Classes Distribution](#4)\n* [Plotting image For one class at time](#5)\n* [Plotting Odd Looking Images](#6)\n* [Resolution distribution of whales Images](#7)\n* [Color distribution of whales Images](#8)\n* [Analysis on Bounding Boxes Images](#9)\n* [Visualize upper and lower bound of the Bounding Box Ratio's](#10)\n* [References](#11)"},{"metadata":{"_uuid":"9380b95b41b503eeda3b5473d947595b882cef0a"},"cell_type":"markdown","source":"## Introduction<a id=\"1\"></a>\nIn this competition, we’re challenged to build an algorithm to identify individual whales in images. Happywhale’s database of over 25,000 images, gathered from research institutions and public contributors are available to build our model.Happywhale is a platform that uses image process algorithms to let anyone to submit their whale photo and have it automatically identified.\n\nThe goal of this competition is to identify individual whales in images. Despite several whales are well represented in images, most of whales are unique or shown only in a few pictures."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"%matplotlib inline\nimport numpy as np # linear algebra\nimport pandas as pd\nimport cv2\nimport os\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nplt.rcParams['figure.figsize'] = [14, 12]\nimport collections\nfrom PIL import Image\nimport matplotlib.image as mpimg\nimport matplotlib.patches as patches\nimport random\nDIR = \"../input/humpback-whale-identification\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5334161828173427f3b24642014ea704c4b80d54"},"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", category=DeprecationWarning)\nwarnings.simplefilter(action='ignore', category=FutureWarning)\nwarnings.simplefilter(action='ignore', category=Warning)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fcfe23ce41f427fd54db969f53457a33279da680"},"cell_type":"markdown","source":"### Lets see what's the data provided by the kaggle"},{"metadata":{"trusted":true,"_uuid":"aefe968e8788b04acddd835f974486578caebd6f"},"cell_type":"code","source":"train = pd.read_csv(os.path.join(DIR, \"train.csv\"))\ntest = pd.read_csv(os.path.join(DIR, \"sample_submission.csv\"))\ntrain.shape, test.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3bfb1f4459d57f64b76f8152aadc320688feb4c2"},"cell_type":"code","source":"os.listdir(DIR)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5979264e2ea4e60824789f29ea06a0c1f7ee9f4c"},"cell_type":"markdown","source":"#### Having two csv files\n* train.csv - contain image name,label for the images in train folder\n\n> format(Image- image name in the train folder,Id- whale identification name)\n\n*  sample_submission.csv - contain image name,dummy label for the images in the test folder\n\n> format(Image- image name in the test folder,Id- dummy whale identification name)\n\n#### And two folders contain the images\n* train - having 25361 images of different type of whales.There Labels have provided in the train.csv file\n* test - having 7960 images of different type of whales.There Labels we need to predict"},{"metadata":{"trusted":true,"_uuid":"3a51f095f9e5efe38c2b37934d1146ddf5adf1ee"},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2a34f1916bd1626649f7bd0a10f82e99f9d070cc"},"cell_type":"code","source":"test.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"11fd6be8f44acb72f817e7560bfc938d2ae9752e"},"cell_type":"markdown","source":"## Submission Format for the Competition<a id=\"2\"></a>"},{"metadata":{"_uuid":"2381176a9ae7dffb2ef1011de34d4ae5218bb709"},"cell_type":"markdown","source":"### We need to predict 5 labels for each of the image.\n> Take example of first row 00028a005.jpg\tnew_whale w_23a388d w_9b5109b w_9c506f6 w_0369a5c.\n\n>In the Above example we have predicted labels new_whale,w_23a388d,w_9b5109b,w_9c506f6,w_0369a5c for the image named 00028a005.jpg.\n\nIf we didn't submit in this format for all the 7960 rows then we will got error while submiting our predictions"},{"metadata":{"_uuid":"92313033ae8dd73a448f82a8dc5c2b713ebb00ee"},"cell_type":"markdown","source":"## Evaluation Metric Explained<a id=\"3\"></a>"},{"metadata":{"_uuid":"8d44747514f566b4358a6bd302f16870bd07906a"},"cell_type":"markdown","source":"The evaluation metric in the competition's description is Mean Average Precision @ 5 (MAP@5):\n$$MAP@5 = {1 \\over U} \\sum_{u=1}^{U} \\sum_{k=1}^{min(n,5)}P(k)  × rel(k)$$\n\nwhere `U` is the number of images, `P(k)` is the precision at cutoff `k`, rel(k)  is an indicator function equaling 1 if the item at rank k is a relevant (correct) label, zero otherwise and `n` is the number of predictions per image.\n\n> the calculation would stop after the first occurrence of the correct whale, so `P(1) = 1`. So, a prediction that is `correct` `incorrect` `incorrect` `incorrect` `incorrect` also scores `1`.\n\nSo we don't have to sum up to 5, only up to the first correct answer. In this competition there is only one correct (`TP`) answer per image, so the possible precision scores per image are either `0` or `P(k)=1/k`.\n\n| true  | predicted   | k  | Image score |\n|:-:|:-:|:-:|:-:|:-:|\n| [x]  | [x, ?, ?, ?, ?]   | 1  | 1.0  |\n| [x]  | [?, x, ?, ?, ?]   | 2  | 0 + 1/2 = 0.5 |\n| [x]  | [?, ?, x, ?, ?]   | 3  | 0/1 + 0/2 + 1/3  = 0.33 |\n| [x]  | [?, ?, ?, x, ?]   | 4  | 0/1 + 0/2 + 0/3 + 1/4  = 0.25 |\n| [x]  | [?, ?, ?, ?, x]   | 5  | 0/1 + 0/2 + 0/3 + 0/4 + 1/5  = 0.2 |\n| [x]  | [?, ?, ?, ?, ?]   | 5  | 0/1 + 0/2 + 0/3 + 0/4 + 0/5  = 0.0 |\n\nwhere `x` is the correct and `?` is incorrect prediction. \n\n### The final score is simply the average over the scores of the images."},{"metadata":{"_uuid":"e2713744e0df5f158df42e9efff8f3c767670cf0"},"cell_type":"markdown","source":"### Let's look at some random whale images from Both train and test folders."},{"metadata":{"trusted":true,"_uuid":"909670952d3f7b169f773c28894788d81fd04e52"},"cell_type":"code","source":"random_train_whales = np.random.choice([os.path.join(DIR+'/train',whale) for whale in train['Image']],3)\nrandom_test_whales = np.random.choice([os.path.join(DIR+'/test',whale) for whale in test['Image']],3)\nboth_whales = np.concatenate([random_train_whales,random_test_whales])\nprint('Training Images:')\nfor i,whale in enumerate(both_whales):\n    if i==3:\n        print('Test Images:')\n    img = Image.open(whale)\n    plt.imshow(img)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"78fae8cf8414bd5761a3fe4ca067284d911d7624"},"cell_type":"markdown","source":"## Distribution of images per Whale Class<a id=\"4\"></a>"},{"metadata":{"trusted":true,"_uuid":"584664f772898cf0da7d739e1b978c61720aa1ec"},"cell_type":"code","source":"train['Id'].value_counts()[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9a7a1f427d6a115c27eca6c938ffe0984e9cad5e"},"cell_type":"code","source":"print(f\"There are {len(os.listdir(DIR+'/train'))} images in train dataset with {train.Id.nunique()} unique classes.\")\nprint(f\"There are {len(os.listdir(DIR+'/test'))} images in test dataset.\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a4a53fa477a566cd1a3f460207c95ba0fd421c8e"},"cell_type":"code","source":"for i in range(1, 4):\n    print(f'There are {train.Id.value_counts()[train.Id.value_counts().values==i].shape[0]} classes with {i} samples in train data.')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"34f6818d8398260625a9742f16feb11ed8829961"},"cell_type":"code","source":"plt.title('Distribution of Classes excluding new_whale');\ntrain.Id.value_counts()[1:].plot(kind='hist', bins=8,figsize=(20,14));","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5c68f8bbafa40382b4372e03ec68098ae0eabcc0"},"cell_type":"code","source":"counted = train.groupby(\"Id\").count().rename(columns={\"Image\":\"image_count\"})\ncounted.loc[counted[\"image_count\"] > 80,'image_count'] = 80\nplt.figure(figsize=(20,14))\nsns.countplot(data=counted, x=\"image_count\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c6f6edf11d9ac020a80807bcc9cd68485a299072"},"cell_type":"code","source":"image_count_for_whale = train.groupby(\"Id\", as_index=False).count().rename(columns={\"Image\":\"image_count\"})\nwhale_count_for_image_count = image_count_for_whale.groupby(\"image_count\", as_index=False).count().rename(columns={\"Id\":\"whale_count\"})\nwhale_count_for_image_count['image_total_count'] = whale_count_for_image_count['image_count'] * whale_count_for_image_count['whale_count']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a610fe51e0e3fdb632f70d29938e8a2739adc555"},"cell_type":"code","source":"whale_count_for_image_count[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1c719f2a56f7b70841be6d4214767b369212fe65"},"cell_type":"code","source":"whale_count_for_image_count[-3:]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7262fd2a944cd8489011b530fddd2198dc8f383e"},"cell_type":"markdown","source":"## Observation Regarding Class Distribution\nThere is a huge disbalance in the data. There are many classes with only one or several samples:\n\n1. Total Number of classes are 5005\n2. 2000+ whales have just one image\n3. Single whale with most images have 73 of them\n4. Images dsitribution:\n  1. almost 30% comes from whales with 4 or less images.\n  1. almost 40% comes from 'new_whale' or 'Default' group around 10k samples.\n  1. the rest 30% comes from whales with 5-73 images."},{"metadata":{"trusted":true,"_uuid":"a70cb8f482d9bf4ac60cd27cc69e03251c7f7c0b"},"cell_type":"markdown","source":"## Explore images Based upon Class<a id=\"5\"></a>\n\n### Some image samples of 'new_whale'"},{"metadata":{"trusted":true,"_uuid":"618c315b0065423fb0d89ab86d0feb2803991dc2"},"cell_type":"code","source":"fig = plt.figure(figsize = (20, 15))\nfor idx, img_name in enumerate(train[train['Id'] == 'new_whale']['Image'][:12]):\n    y = fig.add_subplot(3, 4, idx+1)\n    img = cv2.imread(os.path.join(DIR,\"train\",img_name))\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    y.imshow(img)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9ab60c77896ace5a3644ec600445fbdf50be92b2"},"cell_type":"markdown","source":"   ### Now some images of whales that have just 1 image"},{"metadata":{"trusted":true,"_uuid":"a94a39aab2d80a58beb45cfd5d7db293dc8ccfc5"},"cell_type":"code","source":"single_whales = train['Id'].value_counts().index[-12:]\nfig = plt.figure(figsize = (20, 15))\n\nfor widx, whale in enumerate(single_whales):\n    for idx, img_name in enumerate(train[train['Id'] == whale]['Image'][:1]):\n        axes = widx + idx + 1\n        y = fig.add_subplot(3, 4, axes)\n        img = cv2.imread(os.path.join(DIR,\"train\",img_name))\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        y.imshow(img)\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ebd86af4630c32b7b70129cce52005efa769364c"},"cell_type":"markdown","source":"## Odd looking Images in the Training Set<a id=\"6\"></a>"},{"metadata":{"trusted":true,"_uuid":"b89a2304c436ef63a54d336b8c6de3b2c01ae72a"},"cell_type":"code","source":"def Plot_image_tog(ls,row,col):\n    fig = plt.figure(figsize = (20, 15))\n    for idx, img_name in enumerate(ls):\n        y = fig.add_subplot(row, col, idx+1)\n        img = cv2.imread(os.path.join(DIR,\"train\",img_name))\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        y.imshow(img)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"756cc26b761010236d1247a4e3bf9dcc70a6fb43"},"cell_type":"code","source":"ls = ['0b75361cd.jpg','0c6772887.jpg','0ef9d37be.jpg','fabc19a85.jpg']\nPlot_image_tog(ls,2,2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"46686802959a8035b9f885caebf6f583d766418c"},"cell_type":"markdown","source":"###  Images with Text Part"},{"metadata":{"trusted":true,"_uuid":"e0d6ccb3692c0b6a06ece8f86fe0a64727c828b9"},"cell_type":"code","source":"text_ls=[\"2b96cac5a.jpg\",'f110a9721.jpg','0b6e959b8.jpg','0b7aef92f.jpg','00b92e9bf.jpg','f045d7afc.jpg']\nPlot_image_tog(text_ls,2,3)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a37bb8853699fbcd9883dd5cf23399423e649cf0"},"cell_type":"markdown","source":"###  Images with Single Fin"},{"metadata":{"trusted":true,"_uuid":"325c16361b264df1e3439e2ef3021a61ba929496"},"cell_type":"code","source":"single_ls=['f3f2023c6.jpg','f0cfd99be.jpg','ed309eb49.jpg','155116572.jpg','0ac7c6cf0.jpg','fdb27aea3.jpg']\n#\nPlot_image_tog(single_ls,2,3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"28e3a661ad1aeb8f1c121332211e197e338c9a1d"},"cell_type":"code","source":"# train[train[\"Image\"] == \"2b96cac5a.jpg\"]\n# train[train[\"Id\"] == \"w_c7bd8e7\"]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"52423bb6b1fa39654f91e68260d3da0dc808fd7c"},"cell_type":"markdown","source":"## Distribution of Resolutions of Whale<a id=\"7\"></a>"},{"metadata":{"trusted":true,"_uuid":"c1107cc3865eeea714027c596f6b0235af596b28"},"cell_type":"code","source":"imageSizes_train = collections.Counter([Image.open(f'{DIR}/train/{filename}').size\n                        for filename in os.listdir(f\"{DIR}/train\")])\nimageSizes_test = collections.Counter([Image.open(f'{DIR}/test/{filename}').size\n                        for filename in os.listdir(f\"{DIR}/test\")])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":false,"_uuid":"a616eed4c4179088ffc9be49065aa1e38fb94802"},"cell_type":"code","source":"def isdf(imageSizes):\n    imageSizeFrame = pd.DataFrame(list(imageSizes.most_common()),columns = [\"imageDim\",\"count\"])\n    imageSizeFrame['fraction'] = imageSizeFrame['count'] / sum(imageSizes.values())\n    imageSizeFrame['count_cum'] = imageSizeFrame['count'].cumsum()\n    imageSizeFrame['count_cum_fraction'] = imageSizeFrame['count_cum'] / sum(imageSizes.values())\n    return imageSizeFrame\n\ntrain_isdf = isdf(imageSizes_train)\ntrain_isdf['set'] = 'train'\ntest_isdf = isdf(imageSizes_test)\ntest_isdf['set'] = 'test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5c715493bf9b602ef72982d64060fb9b641e542e"},"cell_type":"code","source":"isizes = train_isdf.merge(test_isdf, how=\"outer\", on=\"imageDim\")\nisizes['total_count'] = isizes['count_x'] + isizes['count_y']\ndims_order = isizes.sort_values('total_count', ascending=False)[['imageDim']]\nprint('Number of Unique Resolutions Available are: ',len(dims_order))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"49869b33cc46d88d9e9722cb7f3b0a973d94da68"},"cell_type":"code","source":"isizes = pd.concat([train_isdf, test_isdf])\nprint('Number of Unique Resolutions Available in both train and test are',isizes.shape[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f6729c47a67ab16f8be9094fc0001399c9a9e850"},"cell_type":"code","source":"isizes.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5ca9e2049b12347b48ad8e17a02f35abc7b6b94c"},"cell_type":"code","source":"popularSizes = isizes[isizes['fraction'] > 0.002]\npopularSizes.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"becfc1c181a6aefa5241176219f4b7b96c9825b2"},"cell_type":"code","source":"plt.figure(figsize=(20,14))\nsns.barplot(x='imageDim',y='fraction',data = popularSizes, hue=\"set\")\n_ = plt.xticks(rotation=45)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2f6c9773b1ac5a91a01198033a08eaece0bb22ac"},"cell_type":"markdown","source":"### Observation Regarding Resolution Distribution\n1. There are Over 7000 unique resolutions.\n2. 39 most popular cover  Approx.45% images (both in train and test)"},{"metadata":{"_uuid":"e9da4b613794f36ce9d853ab599d2aa0981045d1"},"cell_type":"markdown","source":"## Color Scale Distribution of Whale<a id=\"8\"></a>"},{"metadata":{"_uuid":"1cca0fb7c4e934a4bacb53e28f995d3a5583f060"},"cell_type":"markdown","source":"#### We saw from our above EDA that some of the images are either on a greyscale or redscale format, which is different from typical RGB pictures. Let's explore that"},{"metadata":{"trusted":true,"_uuid":"33618c7afa070061c117cd5cccce3b2b08335578"},"cell_type":"code","source":"def is_grey_scale(givenImage):\n    \"\"\"Adopted from https://www.kaggle.com/lextoumbourou/humpback-whale-id-data-and-aug-exploration\"\"\"\n    w,h = givenImage.size\n    for i in range(w):\n        for j in range(h):\n            r,g,b = givenImage.getpixel((i,j))\n            if r != g != b: return False\n    return True","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"96c7fd1e9545febda08eb2fa95300f318786ad2c"},"cell_type":"markdown","source":"### Train Color Scale Distribution"},{"metadata":{"trusted":true,"_uuid":"6fa950e6f255fbc919d63c8ed12076c7767541dd"},"cell_type":"code","source":"sampleFrac = 0.1\n#get our sampled images\nimageList = [Image.open(f'{DIR}/train/{imageName}').convert('RGB')\n            for imageName in train['Image'].sample(frac=sampleFrac)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1c0e09034cee9a206ccda68cdd63b6513cdb2dd1"},"cell_type":"code","source":"isGreyList = [is_grey_scale(givenImage) for givenImage in imageList]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"86ecb0b2ac5443c27d8e1408efb26a1f5f6fc2e5"},"cell_type":"code","source":"#then get proportion greyscale\nnp.sum(isGreyList) / len(isGreyList)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b49bd8e71f55e6bdda8b6c4c506b61a2d19b54ac"},"cell_type":"markdown","source":"### Test Colour Scale Distribution"},{"metadata":{"trusted":true,"_uuid":"bc65cbdbe63f5d39cf213ab439ae81bfc581d7d8"},"cell_type":"code","source":"sampleFrac = 0.1\nimageListtest = [Image.open(f'{DIR}/test/{imageName}').convert('RGB')\n            for imageName in test['Image'].sample(frac=sampleFrac)]\nisGreyListtest = [is_grey_scale(givenImage) for givenImage in imageListtest]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3b06b2fe099ed68030d96e4835b6d9a894ef2a63"},"cell_type":"code","source":"#then get proportion greyscale\nnp.sum(isGreyListtest) / len(isGreyListtest)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"df30c1599c5afc1a5ab0d9d99a066b0c346500b2"},"cell_type":"markdown","source":"### Get mean intensity for each channel RGB"},{"metadata":{"trusted":true,"_uuid":"2e7a54ef9444dcd962e131314468cc6a0ecf8764"},"cell_type":"code","source":"def get_rgb_men(row):\n    img = cv2.imread(DIR + '/train/' + row['Image'])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    return np.sum(img[:,:,0]), np.sum(img[:,:,1]), np.sum(img[:,:,2])\n\ntrain['R'], train['G'], train['B'] = zip(*train.apply(lambda row: get_rgb_men(row), axis=1) )","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4c9f7e0c1d971398790a3ca8c8854c9b8bfba1b0"},"cell_type":"markdown","source":"### Red images and there Colour Distribution"},{"metadata":{"trusted":true,"_uuid":"2a90172a79ae783dd912c8b05e2cf18ffc26624e","collapsed":true},"cell_type":"code","source":"df = train[(train['B'] < train['R']) & (train['G'] < train['R'])]\nnum_photos = 6\nfig, axr = plt.subplots(num_photos,2,figsize=(15,15))\nfor i,(_,row) in enumerate(df.iloc[:num_photos].iterrows()):\n    img = cv2.imread(DIR + '/train/' + row['Image'])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    axr[i,0].imshow(img)\n    axr[i,0].axis('off')\n    axr[i,1].set_title('R={:.0f}, G={:.0f}, B={:.0f} '.format(np.mean(img[:,:,0]), np.mean(img[:,:,1]), np.mean(img[:,:,2]))) \n    x, y = np.histogram(img[:,:,0], bins=255, normed=True)\n    axr[i,1].bar(y[:-1], x, label='R', alpha=0.8, color='C0')\n    x, y = np.histogram(img[:,:,1], bins=255, normed=True)\n    axr[i,1].bar(y[:-1], x, label='G', alpha=0.8, color='C5')\n    x, y = np.histogram(img[:,:,2], bins=255, normed=True)\n    axr[i,1].bar(y[:-1], x, label='B', alpha=0.8, color='C1')\n    axr[i,1].legend()\n    axr[i,1].axis('off')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f5d9d379e1ac26b7d36118ecd4429a3b8772dc3d"},"cell_type":"markdown","source":"### Blue images and there Colour Distribution"},{"metadata":{"trusted":true,"_uuid":"25da38759d0ae57617f781f67227c75c3948821b","collapsed":true},"cell_type":"code","source":"df = train[(train['B'] > train['R']) & (train['B'] > train['G'])]\nnum_photos = 6\nfig, axr = plt.subplots(num_photos,2,figsize=(15,15))\nfor i,(_,row) in enumerate(df.iloc[:num_photos].iterrows()):\n    img = cv2.imread(DIR + '/train/' + row['Image'])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    axr[i,0].imshow(img)\n    axr[i,0].axis('off')\n    axr[i,1].set_title('R={:.0f}, G={:.0f}, B={:.0f} '.format(np.mean(img[:,:,0]), np.mean(img[:,:,1]), np.mean(img[:,:,2]))) \n    x, y = np.histogram(img[:,:,0], bins=255, normed=True)\n    axr[i,1].bar(y[:-1], x, label='R', alpha=0.8, color='C0')\n    x, y = np.histogram(img[:,:,1], bins=255, normed=True)\n    axr[i,1].bar(y[:-1], x, label='G', alpha=0.8, color='C5')\n    x, y = np.histogram(img[:,:,2], bins=255, normed=True)\n    axr[i,1].bar(y[:-1], x, label='B', alpha=0.8, color='C1')\n    axr[i,1].legend()\n    axr[i,1].axis('off')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cf70f7540eb439b5ecbf2324ec7573d98be08844"},"cell_type":"markdown","source":"### Observation Regarding Colour Distribution\n1. We see that around 31% of the images in the training set are greyscale. While 29% in the Test set are greyscale.\n2. Some whales have yellow spots and some images are reddish.This can happened due to sunset.\n3. This suggests that we need to create image transformations that are very agnostic to the RGB spectrum (i.e. bump up the number of greyscaled images in the smaller classes)."},{"metadata":{"_uuid":"46251df75acb0c6039198277bcd202184eec5fdc"},"cell_type":"markdown","source":"## Analysis on Bounding Boxes Images<a id=\"9\"></a>"},{"metadata":{"trusted":true,"_uuid":"fc07e17876e0e079b64d2090f7fe567f3c67d4c3"},"cell_type":"code","source":"##Bounding Boxes for the whale fins only.\nbbox = pd.read_csv('../input/bounding-box/bounding_boxes.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"acaa38f5413b0a8a1febef0ff97623f382e17936","collapsed":true},"cell_type":"code","source":"bbox.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"53edb04f06117f5e3f302e4ba3fe8a0186a17b04"},"cell_type":"code","source":"# DIR = '/home/aiml/ml/share/data/all_kagg'\nTRAIN = os.path.join(DIR, 'train')\nTEST = os.path.join(DIR, 'test')\n\ntrain_paths = [img for img in os.listdir(TRAIN)]\ntest_paths = [img for img in os.listdir(TEST)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d361dae0196b5d3eb5ad5611a40edd950799bc66"},"cell_type":"code","source":"len(train_paths)\nlen(test_paths)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b88eb45cfc14c8b374cbf75f6817d849bb1fcbf0"},"cell_type":"code","source":"## Create full path for the images\ndef full_path(row):\n    if row in train_paths:\n        return TRAIN+'/'+row\n    else:\n        return TEST+'/'+row","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8148e8302295bf0955920963a9555426d6bb0ebe"},"cell_type":"code","source":"bbox['Full_Path'] = bbox['Image'].apply(lambda row: full_path(row))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"db745a15448bf689af4a41c152109dd986ada2c5"},"cell_type":"code","source":"##check images are already present in the directory or not.\nbbox[bbox['Image'] ==test_paths[0]]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6bb882a17fc52a9338e1df879e3cba8f1ed62e54"},"cell_type":"markdown","source":"### Visualize Original and Bounding boxed images"},{"metadata":{"trusted":true,"_uuid":"fda3bdca2dd24acf75c77fa71af3db45167808af","collapsed":true},"cell_type":"code","source":"i=2\nfig,ax = plt.subplots(6,2,figsize=(25,20))\nfor i in range(6):\n    img_row = bbox[bbox['Image'] ==test_paths[i]]\n    img = cv2.imread(TEST+'/'+img_row['Image'].values[0])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    # fig,ax = plt.subplots(2)\n    ax[i,0].imshow(img)\n    xmin1 = img_row['x0'].values[0]\n    ymin1 = img_row['y0'].values[0]\n    xmax = img_row['x1'].values[0]\n    ymax = img_row['y1'].values[0]\n    rect = patches.Rectangle((xmin1,ymin1),xmax-xmin1,ymax-ymin1,linewidth=1,edgecolor='r',facecolor='none')\n    ax[i,1].add_patch(rect)\n    ax[i,1].imshow(img)\n    # plt.imshow(img)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2cf155649d272a35201866c6a90c527f069eb620"},"cell_type":"markdown","source":"### Get the Original Images sizes for comparison"},{"metadata":{"trusted":true,"_uuid":"b82b353bb0d4f3ea7f5445a4a115480ecba1abe1"},"cell_type":"code","source":"def x_orig_img(row):\n    if row in train_paths:\n        return Image.open(TRAIN+'/'+row).size[0]\n    else:\n        return Image.open(TEST+'/'+row).size[0]\n\ndef y_orig_img(row):\n    if row in train_paths:\n        return Image.open(TRAIN+'/'+row).size[1]\n    else:\n        return Image.open(TEST+'/'+row).size[1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"83c98ba1500df051b766657e2b025d27e427ad20"},"cell_type":"code","source":"bbox['x_orig'] = bbox['Image'].apply(lambda row: x_orig_img (row))\nbbox['y_orig'] = bbox['Image'].apply(lambda row: y_orig_img (row))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ef7f8979c6d1afe530b9aac679cb8374e1bd9062"},"cell_type":"code","source":"bbox['ratio'] = ((bbox['x1']-bbox['x0']) * (bbox['y1']-bbox['y0']))/(bbox['x_orig'] * bbox['y_orig']) * 100","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d74db10dabb5b3b9c0a6220d7690206e28912c25"},"cell_type":"code","source":"plt.figure(figsize=(20,14))\nplt.title(\"Comparison Of Full and Cropped Images\", {'size':'14'})\nf = sns.distplot(bbox['ratio'])\nf.set_xlabel(\"In Percentage Cropped Size Over Original\", {'size':'14'})\nf.set_ylabel(\"Frequency\", {'size':'14'}) ","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7b8dba55c62ae10583d737c851de1a1efb5b826d"},"cell_type":"markdown","source":"## Visualize upper and lower bound of the Bounding Box Ratio's<a id=\"10\"></a>"},{"metadata":{"trusted":true,"_uuid":"23c1cf2025514bc1259b9823690a1738eb201388"},"cell_type":"code","source":"bbox[bbox['ratio']<5].sort_values(['ratio']).sort_values(['ratio']).head(5)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f1c02f4d29aa8c5665f50b0d3a0dc68ef7e9322d"},"cell_type":"markdown","source":"### Lower bound Bounding box ratio"},{"metadata":{"trusted":true,"_uuid":"a6c6692133d08b02d940d9a4557695e26c35188d"},"cell_type":"code","source":"i=2\nfig,ax = plt.subplots(6,2,figsize=(25,20))\nfor i in range(6):\n    img_row = bbox[bbox['ratio']<5].sort_values(['ratio'],ascending=[False])[i:i+1]\n    img = cv2.imread(img_row['Full_Path'].values[0])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    ax[i,0].imshow(img)\n    xmin1 = img_row['x0'].values[0]\n    ymin1 = img_row['y0'].values[0]\n    xmax = img_row['x1'].values[0]\n    ymax = img_row['y1'].values[0]\n    rect = patches.Rectangle((xmin1,ymin1),xmax-xmin1,ymax-ymin1,linewidth=1,edgecolor='r',facecolor='none')\n    ax[i,1].add_patch(rect)\n    ax[i,1].imshow(img)\n    # plt.imshow(img)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c604b7401c1b4c5f768d8025e62924d98b501f73"},"cell_type":"code","source":"bbox[bbox['ratio']>95].sort_values(['ratio']).sort_values(['ratio'],ascending=[False]).head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f7d79d162d9a93de0f4b03d96ec5bd3ff11c32b8"},"cell_type":"markdown","source":"### Upper Bound bounding box ratio"},{"metadata":{"trusted":true,"_uuid":"5e21a963f39880c71f1aa7742a6cb377fabc3b5a"},"cell_type":"code","source":"i=2\nfig,ax = plt.subplots(6,2,figsize=(25,20))\nfor i in range(6):\n    img_row = bbox[bbox['ratio']>90].sort_values(['ratio'], ascending=[False])[i:i+1]\n#     img_row = bbox[bbox['Image'] ==test_paths[i]]\n    img = cv2.imread(img_row['Full_Path'].values[0])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    ax[i,0].imshow(img)\n    xmin1 = img_row['x0'].values[0]\n    ymin1 = img_row['y0'].values[0]\n    xmax = img_row['x1'].values[0]\n    ymax = img_row['y1'].values[0]\n    rect = patches.Rectangle((xmin1,ymin1),xmax-xmin1,ymax-ymin1,linewidth=1,edgecolor='r',facecolor='none')\n    ax[i,1].add_patch(rect)\n    ax[i,1].imshow(img)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d9b2d0612132072e9c81ab24e11efbadeaca360b"},"cell_type":"markdown","source":"### Conclusion\n1. Most of the whale fins images are between 30 to 50% of the original and the peak near to 90% also show some images are already nicely cropped.\n2. Some of the images are not bounded correctly.so we can't take the same crop as in Bounding Box.csv\n3. Decision to crop the images or not is difficult some of the images are bounded correctly which help to get good score but some images are only identifiable by the sea where cropping make the score worse."},{"metadata":{"_uuid":"90deec734bbd92061d30c46a5a486836a33a68dc"},"cell_type":"markdown","source":"## References<a id=\"11\"></a>"},{"metadata":{"trusted":true,"_uuid":"c9a62db761dc155067084f3ec760008aef3db29f"},"cell_type":"code","source":"## I have used these awesome kernels for whole EDA\n##https://www.kaggle.com/pestipeti/explanation-of-map5-scoring-metric\n##https://www.kaggle.com/artgor/pytorch-whale-identifier\n##https://www.kaggle.com/kretes/eda-distributions-images-and-no-duplicates\n##https://www.kaggle.com/cristianpb/on-finding-rgb-or-bgr\n##https://www.kaggle.com/suicaokhoailang/generating-whale-bounding-boxes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5ae1288ab57b7ac9d8f5261c86ddf1603b68c749"},"cell_type":"code","source":"##Model Building coming soon...","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}