{"cells":[{"metadata":{"_uuid":"18c735c4a3e7d53bbcd82dfd676240301cb075e0"},"cell_type":"markdown","source":"**Introduction**\n\nThis notebook is forked from [Siddhartha](https://www.kaggle.com/meaninglesslives/airbus-ship-detection-data-visualization)  Data Visualization notebook and mixed with [Hugo Lapointe](https://www.kaggle.com/hugolapointe/airbus-ship-detection-challenge) notebook with nice object-oriented classes. It also includes some code from other great kernels."},{"metadata":{"_uuid":"d8d19639fac647b9933ba36071a63ea26a638416"},"cell_type":"markdown","source":"**Reading CSV information from the train dataset**\n\nSome images have no ships on them. Some images have one ship and some other images have more than one ship on them. There is one record in RLE per ship in the image hence multiple records for the same image. "},{"metadata":{"trusted":true,"_uuid":"f1a78c7e479a65719964c9536298f82afb969ebf","_kg_hide-input":true,"_kg_hide-output":false},"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\nINPUT_PATH = '../input'\nDATA_PATH = INPUT_PATH\nTRAIN_PATH = os.path.join(DATA_PATH, \"train_v2\")\nTEST_PATH = os.path.join(DATA_PATH, \"test_v2\")\nTRAIN_MASKS_PATH = os.path.join(DATA_PATH, \"train/masks\")\n\nprint(\"Reading CSV file\")\ndf = pd.read_csv(DATA_PATH+'/train_ship_segmentations_v2.csv')\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"75274f21209996066b2b22630205313c8916e144"},"cell_type":"markdown","source":"**Analysing images with no ships**\n\nThere are 150,000 images without any ship on them. Since the sea is mostly empty, this is representative of the normal situation."},{"metadata":{"trusted":true,"_uuid":"81c29fe0ccbb5cd7f8f7eb52fca8bff5157ab807","_kg_hide-input":true},"cell_type":"code","source":"#df = df.reset_index()\nwithoutships = df[(df.EncodedPixels.isna() == True)]\nprint(withoutships.describe())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"06fb68db57e1c4bc71af35871eedfa9ac3f08f22"},"cell_type":"markdown","source":"**Displaying some examples of images with no ships** \n\nLet's plot some random images from training set. The images are 768 x 768 pixels each."},{"metadata":{"trusted":true,"_uuid":"b9447b5a9c6369010e3f949ec741def0687a139a","_kg_hide-input":true},"cell_type":"code","source":"# Helper class to read images\nimport sys\nimport random\nimport cv2\nimport pdb\n\nfrom tqdm import tqdm\nfrom PIL import Image\nfrom glob import glob\nfrom tqdm import tqdm_notebook, tnrange\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nclass SatImage(object):       \n    def __init__(self):\n        self.title = \"\"\n        self.image_id = \"\"\n        self.image = None\n        self.width = 0\n        self.height = 0\n        self.shape = (0, 0)\n        self.mask = None\n    \n    def load_image(self, image_id, image_type):\n        '''\n        image_id: name of the image to read (including extension)\n        image_type: type of image (from Train, Mask, Test)\n        Returns SatImage instance\n        '''\n        matrix = self._get_image_data(image_id, image_type)\n        instance = SatImage()\n        instance.image_id = image_id\n        instance.image = matrix\n        instance.height = matrix.shape[0]\n        instance.width = matrix.shape[1]\n        instance.shape = (instance.height, instance.width)\n        return instance\n\n    def _get_filename(self, image_id, image_type):\n        check_dir = False\n        if \"Train\" == image_type:\n            data_path = TRAIN_PATH\n        elif \"Mask\" in image_type:\n            data_path = TRAIN_MASKS_PATH\n        elif \"Test\" in image_type:\n            data_path = TEST_PATH\n        else:\n            raise Exception(\"Image type '%s' is not recognized\" % image_type)\n\n        if check_dir and not os.path.exists(data_path):\n            os.makedirs(data_path)\n\n        return os.path.join(data_path, \"{}\".format(image_id))\n\n    def _get_image_data_opencv(self, image_id, image_type):\n        fname = self._get_filename(image_id, image_type)\n        img = cv2.imread(fname)\n        assert img is not None, \"Failed to read image : %s, %s\" % (image_id, image_type)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        return img\n\n    def _get_image_data(self, image_id, image_type):\n        img = self._get_image_data_opencv(image_id, image_type)\n        img = img.astype('uint8')\n        return img\n    \n    def set_title(self, title):\n        self.title = title\n    \n    def add_objects(self, rle_masks):   \n        r_mask = np.zeros(self.shape, dtype = np.uint8)\n        g_mask = np.zeros(self.shape, dtype = np.uint8)\n        b_mask = np.zeros(self.shape, dtype = np.uint8)\n        \n        for rle_mask in rle_masks:\n            if isinstance(rle_mask, str):\n                r_mask += 255 * RLE.decode(rle_mask, self.shape)\n        \n        self.mask = np.dstack((r_mask, g_mask, b_mask)) \n        #np.expand_dims(_mask, -1)\n\n    # https://github.com/ternaus/TernausNet/blob/master/Example.ipynb\n    def _mask_overlay(self, image, mask):\n        \"\"\"\n        Helper function to visualize mask\n        \"\"\"\n        #mask = mask.astype(np.uint8)\n        weighted_sum = cv2.addWeighted(mask, 0.75, image, 0.5, 0.)\n        #img = image.copy()\n        #ind = mask[:, :, 1] > 0    \n        #img[ind] = weighted_sum[ind]    \n        #return img\n        return weighted_sum\n\n    def show(self, with_mask = False):\n        plt.axis(\"off\")\n        plt.title(self.title)\n        \n        if with_mask:\n            rle_masks = df.loc[df['ImageId'] == self.image_id,'EncodedPixels'].tolist()\n            self.add_objects(rle_masks)\n            copy = self._mask_overlay(self.image, self.mask)\n            plt.imshow(copy)\n            \n        else:\n            plt.imshow(self.image)\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"35b6bc052378f15e37a92aab7f0b031f375999ec"},"cell_type":"code","source":"def display_SatImages(names, cols = 4, figsize = (5, 5)):\n    w, h = figsize\n    rows = len(names) * 1 // cols + 1\n    plt.figure(figsize = (cols * w, rows * h))\n\n    i = 1    \n    for name in names:\n        plt.subplot(rows, cols, i)\n        satimage = SatImage().load_image(name, \"Train\")\n        satimage.set_title(name)\n        satimage.show(True)\n        i += 1\n\n    plt.tight_layout()\n    plt.show()\n\nsample = df[(df.EncodedPixels.isna() == True)].sample(n=16)\nimgs = np.squeeze(sample[['ImageId']].values.tolist())\ndisplay_SatImages(imgs, 4, (5, 5))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5b320174ac080cf945a88d4d8a2b736d0a326d2e"},"cell_type":"markdown","source":"**Analysing images with ships**\n\nThere are 42 556 images with ships on them. There is a total of 81 723 ships on all images. Some images have more than one ship on them."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"b404beadbab97607b30225b94f58f1c461e28ea2"},"cell_type":"code","source":"withships = df[(df.EncodedPixels.isna() == False)]\nprint(withships.describe())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"649667f3248e57201d0b1872c04cfa3a76bb31a4"},"cell_type":"markdown","source":"**Analysing ship frequency distribution**\n\nThere are roughly 4 ships per images but this is moslty unbalanced as more than 25% of images have only 1 ship on them. Then the number of ship per image grows up to 15 ships per image."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"e0a5a9c8b9ee0b722531a7363b9ea4c77145c2b7"},"cell_type":"code","source":"withships['ship_count'] = withships.groupby('ImageId')['ImageId'].transform('count')\nprint(withships['ship_count'].describe())","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"1b59c4aff4440c240f2cb5be8a3e195869e4642f"},"cell_type":"code","source":"import seaborn as sns\n\nsns.set_style(\"white\")\nsns.set_context(\"notebook\", font_scale=1.5, rc={\"lines.linewidth\": 2.5})\n#sns.distplot(withships['ship_count'],kde=False)\n\nplt.figure(figsize = (23, 8))\nplt.title('Ship Count Distribution in Train Set')\nax = sns.countplot(data = withships, x = \"ship_count\")\n    \nfor p in ax.patches:\n    x = p.get_bbox().get_points()[:,0]\n    y = p.get_bbox().get_points()[1,1]\n    ax.annotate(\"{:.2f}%\".format(y / len(withships) * 100), (x.mean(), y), ha = \"center\", va = \"bottom\")\n    \nplt.title(\"Ships Frequency Distribution\")\nplt.ylabel(\"Frequency\")\nplt.xlabel(\"Ships count\")\nplt.show()\n    ","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"338497fc51d3a8876a67ff056faaa9de1f2e61b7"},"cell_type":"markdown","source":"**Displaying some examples of images with ships** \n\nLet's plot some random images from training set with the mask overlayed in red on top of them. "},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"0377e11248c0511ddde99899854d2ab9cf66fecc"},"cell_type":"code","source":"# Helper class to decode and encode RLE\n# ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode\nclass RLE(object):\n    def encode(image):\n        pixels = img.T.flatten()\n        pixels = np.concatenate([[0], pixels, [0]])\n        runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n        runs[1::2] -= runs[::2]\n        return ' '.join(str(x) for x in runs)\n\n    def decode(encoding, shape):\n        '''\n        encoding: run-length as string formated (start length)\n        shape: (height,width) of array to return \n        Returns numpy array, 1 - mask, 0 - background\n        '''\n        s = encoding.split()\n        starts, lengths = [np.asarray(x, dtype = int) for x in (s[0:][::2], s[1:][::2])]\n        starts -= 1\n        ends = starts + lengths\n        image = np.zeros(shape[0] * shape[1], dtype = np.uint8)\n        for lo, hi in zip(starts, ends):\n            image[lo:hi] = 1\n        return image.reshape(shape).T  # Needed to align to RLE direction","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"53332d94ebcdab5c9d2d2a708e619a52c2492009"},"cell_type":"code","source":"sample = df[(df.EncodedPixels.isna() == False)].sample(n=16)\nimgs = np.squeeze(sample[['ImageId']].values.tolist())\ndisplay_SatImages(imgs, 4, (5, 5))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"397b7202a0106ee3e944124d2371e560bcc60ac9"},"cell_type":"markdown","source":"**Trying to optimize the imagery**\n\nLet's try to do some pre-processing on the images."},{"metadata":{"trusted":true,"_uuid":"b1fbefd0c66cbfbf2609a05eff6dbcd8aa40af28","_kg_hide-input":true},"cell_type":"code","source":"from skimage.filters import gaussian,laplace\nfrom skimage.feature import canny\nfrom skimage.filters import scharr\nfrom skimage import exposure\nfrom skimage.color.adapt_rgb import adapt_rgb, each_channel, hsv_value","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"729250fbe0ba64e10df5318655e70147e5e1b39d","_kg_hide-input":true},"cell_type":"code","source":"@adapt_rgb(hsv_value)\ndef canny_hsv(image):\n    return canny(image)\n\n@adapt_rgb(hsv_value)\ndef scharr_hsv(image):\n    return scharr(image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c871dc640f824a9e6f971ce92a3cee094f03c9f4","_kg_hide-input":true},"cell_type":"code","source":"# simple features that can be easily extracted and used for training deep networks\n# these features may be used along with original image\n\n# initializing random for reproductible results\nnp.random.seed(13)\n\ntrain_ids = df.ImageId.values\n_train_ids = list(train_ids)\n\nplt.figure(figsize=(30,15))\nplt.subplots_adjust(bottom=0.2, top=1.2)  #adjust this to change vertical and horiz. spacings..\n\ndef displayImg(row, col, index, title, img):\n    plt.subplot(row, col, index)\n    plt.imshow(img, cmap='binary')\n    plt.title(title)\n    plt.axis('off')\n    \nnProc = 7 # nb of processings    \nnImg = 5  #nb of images to process\nfor i in range(nImg):\n    image_id = _train_ids[np.random.randint(0, len(_train_ids))]\n    #ax = fig.add_subplot(3,3,i+1)\n    img = SatImage().load_image(image_id, 'Train').image\n    \n    # Original image\n    displayImg(nImg, nProc, i*nProc+1, 'Original', img)\n\n    # Smoothing\n    displayImg(nImg, nProc, i*nProc+2, 'Smoothed', gaussian(img))\n    \n    # Contrast stretching\n    p2, p98 = np.percentile(img, (2, 98))\n    img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98))\n    displayImg(nImg, nProc, i*nProc+3, 'Stretched', img_rescale)\n    \n    # Equalization\n    displayImg(nImg, nProc, i*nProc+4, 'Equalization', exposure.equalize_hist(img))\n\n    # Adaptive Equalization\n    displayImg(nImg, nProc, i*nProc+5, 'Adaptative', exposure.equalize_adapthist(img))\n    \n    # Scharr Edge Magnitude\n    displayImg(nImg, nProc, i*nProc+6, 'Scharr Edge Magnitude', scharr_hsv(img))\n\n    # Canny features\n    displayImg(nImg, nProc, i*nProc+7, 'Canny features', canny_hsv(img))\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7cd76c0346b89636c5e17239678aca80a584b19e"},"cell_type":"code","source":"","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}