{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Importing required library"},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nimport cv2\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport seaborn as sns\n\nfrom tqdm import tqdm_notebook, tnrange\nfrom tqdm import tqdm","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Reading CSV file[](http://)"},{"metadata":{"trusted":true},"cell_type":"code","source":"main_ship_data = pd.read_csv(\"../input/airbus-ship-detection/train_ship_segmentations_v2.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"main_ship_data[\"has_ship\"] = main_ship_data[\"EncodedPixels\"].map(lambda x:1 if isinstance(x,str) else 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"main_ship_data.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Preprocessing of data\n\nIn the original ship data there are many duplicate Image_Id, because an image with 5 ships in it will have 5 different bounding boxes and so on. So creating a dataframe with unique Image_Id so that we can have a better visualisation and understanding."},{"metadata":{"trusted":true},"cell_type":"code","source":"unique_ship_data = main_ship_data.groupby(\"ImageId\").agg({\"has_ship\":sum}).reset_index()\nunique_ship_data[\"number_of_ships\"] = unique_ship_data[\"has_ship\"]\nunique_ship_data.drop(\"has_ship\", axis = 1, inplace = True)\n\nunique_ship_data[\"has_ship\"] = unique_ship_data[\"number_of_ships\"].map(lambda x:1.0 if x>=1.0 else 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unique_ship_data.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Decoding the Encodedpixels\n\nDefined a function, which converts the encodedpixels to X_center, Y_center, Height, Width of the bounding box.\n\n*Here Encodedpixels are in the Run-length encoding format, which is a form of lossless data compression in which runs of data are stored as a single data value and count, rather than as the original run.*"},{"metadata":{"trusted":true},"cell_type":"code","source":"def rle2bbox(rle, shape):\n   \n   a = np.fromiter(rle.split(), dtype=np.uint)\n   a = a.reshape((-1, 2))  # an array of (start, length) pairs\n   a[:,0] -= 1  # `start` is 1-indexed\n   \n   y0 = a[:,0] % shape[0]\n   y1 = y0 + a[:,1]\n   if np.any(y1 > shape[0]):\n       # got `y` overrun, meaning that there are a pixels in mask on 0 and shape[0] position\n       y0 = 0\n       y1 = shape[0]\n   else:\n       y0 = np.min(y0)\n       y1 = np.max(y1)\n   \n   x0 = a[:,0] // shape[0]\n   x1 = (a[:,0] + a[:,1]) // shape[0]\n   x0 = np.min(x0)\n   x1 = np.max(x1)\n   \n   if x1 > shape[1]:\n       # just went out of the image dimensions\n       raise ValueError(\"invalid RLE or image dimensions: x1=%d > shape[1]=%d\" % (\n           x1, shape[1]\n       ))\n    \n   xC = (x1+x0)/(2*768)\n   yC = (y1+y0)/(2*768)\n   h = np.abs(y1-y0)/768\n   w = np.abs(x1-x0)/768\n\n   return [xC, yC, h, w]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"main_ship_data[\"bbox\"] = main_ship_data[\"EncodedPixels\"].map(lambda x: rle2bbox(x, (768,768)) if isinstance(x,str) else np.NaN )\nmain_ship_data.drop(\"EncodedPixels\", axis=1, inplace = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Creating a new column with the area of bounding box in it.\nmain_ship_data[\"bboxArea\"]=main_ship_data[\"bbox\"].map(lambda x:x[2]*768*x[3]*768 if x==x else 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"main_ship_data.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Exploratory Data Analysis and Visualization"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Plotting the distribution of the bounding box areas to check the ship sizes\n\narea = main_ship_data[main_ship_data[\"has_ship\"]>0]\n\nplt.figure(figsize = (12,5))\nplt.subplot(1,2,1)\nsns.boxplot(area[\"bboxArea\"])\nplt.title(\"Areas of Bounding boxes for ships\")\n# plt.xscale(\"log\")\nplt.subplot(1,2,2)\nplt.hist(area[\"bboxArea\"], bins=50)\n# plt.xscale(\"log\")\nplt.title(\"Distribution of Bounding box area\")\nplt.xlabel(\"Bounding Box Area\")\nplt.tight_layout()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"area = main_ship_data[(main_ship_data[\"has_ship\"]>0)&(main_ship_data[\"bboxArea\"]<20)]\narea[\"bboxArea\"] = np.round(area[\"bboxArea\"])\n\nplt.figure(figsize=(10,5))\nsns.countplot(x=\"bboxArea\", data=area)\nplt.xlabel(\"Area of bounding box\")\nplt.ylabel(\"Number of Images\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* There are few bounding boxes with area less than 10 pixels and some have area equal to 0. So, removing these tiny boxes as they learn wrong features and may result in wrong prediction while testing. "},{"metadata":{"trusted":true},"cell_type":"code","source":"# Finding the distribution of no of ships\n\nplt.figure(figsize = (20,10))\nplt.subplot(2,2,1)\nclasses=[\"No Ship\",\"Ship\"]\nax = sns.countplot(unique_ship_data[\"has_ship\"])\nax.set_xticklabels(classes)\nplt.ylabel(\"Number of Images\")\nplt.title(\"Images with ship vs Without Ship\")\n\nplt.subplot(2,2,2)\nsns.countplot(unique_ship_data[\"number_of_ships\"])\n# plt.yscale(\"log\")\nplt.xlabel(\"Number of Ships\")\nplt.ylabel(\"Number of Images\")\nplt.title(\"Number of Ships count (Including no ship)\")\n\nwithship = unique_ship_data[unique_ship_data[\"has_ship\"]==1]\nplt.subplot(2,2,3)\nsns.countplot(withship[\"number_of_ships\"])\nplt.xlabel(\"Number of Ships\")\nplt.ylabel(\"Number of Images\")\nplt.title(\"Number of Ships count (Excluding no ship)\")\n\nplt.subplot(2,2,4)\nsns.boxplot(withship[\"number_of_ships\"])\nplt.xlabel(\"Number of Ships\")\nplt.title(\"Distribution of number of ships(Excluding no ship)\")\n\nplt.tight_layout()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* Almost 75% of the images containing ships have ships less or equal to 3.\n* Most of the images with ships contains 1 ship.\n* There is a data imbalance for the no of ships in the Images.\n* Most of the ships are very small in sizes although there are few images with significantly large ship sizes."},{"metadata":{},"cell_type":"markdown","source":"## Data preparation and creating a balance dataframe\n\nAfter creating dataframe(unique_ship_data) with unique Image_Id, we found that the disribution of of image containing ship and the image not containing the ship is highly imbalanced and moreover it will be computionally expensive. So to train the model fast and efficently, we took the full data from kaggle and created a smaller balanced dataframe from it by taking 1000 images from every class of images(here class is number of ships in an image). There are total 16 classes including the image with no ship."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Removing boxes which are less than 1 percentile\n# main_ship_data = main_ship_data[(main_ship_data[\"bboxArea\"]>10) & (main_ship_data[\"has_ship\"]==1)]\n\nmain_ship_data = main_ship_data.drop(main_ship_data[(main_ship_data[\"bboxArea\"]<10) & (main_ship_data[\"has_ship\"]!=0)].index)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"numberofships = 1000\n\nbalance_ship_data = unique_ship_data.groupby(\"number_of_ships\").apply(lambda x:x.sample(numberofships) if len(x)>numberofships else x)\nbalance_ship_data = balance_ship_data.reset_index(drop = True)\nbalance_ship_data = balance_ship_data.drop(\"has_ship\", axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"balance_ship_data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"balance_ship_data[\"number_of_ships\"].hist(bins=16)\nplt.xlabel(\"Number of Ships\")\nplt.ylabel(\"Number of Images\")\nplt.title(\"Number of Ships count on unique Image_Id \")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Merging the the balance_ship_data with main_ship_data in order to have the Encodedpixels\nbalance_ship_data = pd.merge(balance_ship_data, main_ship_data, on='ImageId')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"balance_ship_data.sample(5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Exploratory Data Analysis for balance ship data"},{"metadata":{"trusted":true},"cell_type":"code","source":"#Distrubution of count of images with ships and no ships in balance_ship_data dataframe\nclasses=[\"No Ship\",\"Ship\"]\nsns.set_style('darkgrid')  \nax = sns.countplot(x=\"has_ship\", data=balance_ship_data)\nax.set_xticklabels(classes)\nplt.ylabel(\"Number of Images\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Distrubution of number of ships in a single image in balance_ship_data dataframe\nsns.set_style('darkgrid')  \nax = sns.countplot(x=\"number_of_ships\", data=balance_ship_data)\n# ax.set_xticklabels(classes)\nplt.xlabel(\"Number of Ships\")\nplt.ylabel(\"Number of Images\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Balance Data Image Visualization"},{"metadata":{"trusted":true},"cell_type":"code","source":"#Defining a function to load image\ndef load_img(path):\n    image = cv2.imread(path)\n    return image[...,::-1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path = \"../input/airbus-ship-detection/train_v2/\"\n\nplt.figure(figsize=(20, 15))\n\nfor i in range(16):\n    \n  imageid = balance_ship_data[\"ImageId\"][balance_ship_data[\"number_of_ships\"]==i].sample(5).reset_index(drop=True)    \n  imageid = imageid[0]\n  image = np.array(load_img(path+imageid))\n\n  text = \"Name of the image:{0}\".format(imageid[0])\n    \n  Bbox = balance_ship_data[\"bbox\"][balance_ship_data[\"ImageId\"]==imageid].reset_index(drop=True)\n\n  plt.subplot(4,5,i+1)\n    \n  if i>0:\n    for j in Bbox:\n      # print(i[0])\n      xc = j[0]\n      yc = j[1]\n      h = j[2]\n      w = j[3]\n\n      x0 = int((xc-(w/2))*768)\n      y0 = int((yc-(h/2))*768)\n      x1 = int((xc+(w/2))*768)\n      y1 = int((yc+(h/2))*768)\n\n      cv2.rectangle(image,\n            pt1=(x0,y0),\n            pt2=(x1,y1),\n            color=(255,0,0),\n            thickness=3)\n    \n  plt.imshow(image)\n  plt.title(\"Number of ship:{}\".format(i),fontsize=10)\n  plt.axis('off')\n  \nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Extracting the Bounding box coordinates into YOLO format"},{"metadata":{"trusted":true},"cell_type":"code","source":"# folder_location = \"/content/drive/My Drive/Colab_Notebooks/Capstone\" ##Location of the folder which contains the train and test images\n\n# for i, img_id in tqdm(enumerate(balance_ship_data[\"ImageId\"])):\n\n#     filt_df = balance_ship_data[balance_ship_data.ImageId==img_id]\n#     all_boxes = filt_df.bbox.values\n#     img_id = img_id.split(\".\")[0]\n#     file_name = \"{}/{}.txt\".format(folder_location,img_id) \n\n#     s = \"0 %s %s %s %s \\n\" \n#     with open(file_name, 'a') as file: \n#         if filt_df[\"has_ship\"]>0:\n#             for i in all_boxes:\n#                 new_line = (s % tuple(i))\n#                 file.write(new_line)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Spliting the image data into train and test"},{"metadata":{"trusted":true},"cell_type":"code","source":"# X = balance_ship_data[[\"ImageId\"]]\n# y = balance_ship_data[\"EncodedPixels\"]\n\n# train, test, _, _ = train_test_split(X, y, test_size = 0.2, random_state = 2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# path = \"/content/Capstone/shipimages/\" #path where ship images are there\n# path_txt = \"/content/Capstone/\"        #path where you want the txt file to be created\n\n# train[\"ImageId\"] = path + train[\"ImageId\"]\n# test[\"ImageId\"] = path +test[\"ImageId\"]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Extracting the path of train and test image data into .txt file"},{"metadata":{"trusted":true},"cell_type":"code","source":"# train.to_csv(path_txt+\"Train_path.txt\",index=None, header=None, sep=\" \", mode=\"a\")\n# test.to_csv(path_txt+\"Test_path.txt\",index=None, header=None, sep=\" \", mode=\"a\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}