{"cells":[{"metadata":{},"cell_type":"markdown","source":"### Overview"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"markdown","source":"In this kernel, I'm going to make bounding box for each ship in the image."},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import os\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom skimage.io import imread\nimport matplotlib.pyplot as plt\nfrom skimage.segmentation import mark_boundaries\nfrom skimage.util import montage\nmontage_rgb = lambda x: np.stack([montage(x[:, :, :, i]) for i in range(x.shape[3])], -1)\nship_dir = '../input/airbus-ship-detection'\ntrain_image_dir = os.path.join(ship_dir, 'train_v2')\ntest_image_dir = os.path.join(ship_dir, 'test_v2')\nimport gc; gc.enable() # memory is tight","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Get data"},{"metadata":{"trusted":true},"cell_type":"code","source":"data = pd.read_csv(os.path.join(ship_dir, 'train_ship_segmentations_v2.csv'))\n\ndata.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Useful functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"from skimage.morphology import label\n\ndef multi_rle_encode(img):\n    labels = label(img[:, :, 0])\n    return [rle_encode(labels==k) for k in np.unique(labels[labels>0])]\n\n# ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode\ndef rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\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\ndef rle_decode(mask_rle, shape=(768, 768)):\n    '''\n    mask_rle: 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 = mask_rle.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    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape).T  # Needed to align to RLE direction\n\ndef masks_as_image(in_mask_list):\n    # Take the individual ship masks and create a single mask array for all ships\n    all_masks = np.zeros((768, 768), dtype = np.uint8)\n    for mask in in_mask_list:\n        if isinstance(mask, str):\n            all_masks |= rle_decode(mask)\n    return np.expand_dims(all_masks, -1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Choose images with at least one ship"},{"metadata":{"trusted":true},"cell_type":"code","source":"data['ships'] = data['EncodedPixels'].map(lambda c_row: 1 if isinstance(c_row, str) else 0)\ndata.dropna(subset=['EncodedPixels'], inplace=True)\nunique_img_ids = data.groupby('ImageId').agg({'ships': 'sum'}).reset_index()\nunique_img_ids['has_ship'] = unique_img_ids['ships'].map(lambda x: 1.0 if x>0 else 0.0)\n\nunique_img_ids.head()\ndata.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#unique_img_ids = unique_img_ids.groupby('ships').apply(lambda x : x.sample(10000) if len(x)>10000 else x)\nunique_img_ids['ships'].hist(bins=unique_img_ids['ships'].max())\ndata.drop(['ships'], axis=1, inplace=True)\nmodified_data = pd.merge(data, unique_img_ids)\nmodified_data.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_images = list(modified_data.groupby('ImageId'))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Visual check of original segmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"NUMBER_IN_SAMPLE = 4\nnp.random.shuffle(all_images)\nsample_images = all_images[:NUMBER_IN_SAMPLE]\n\nfig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (30, 10))\n\nimg = []\nseg = []\nfor i in range(NUMBER_IN_SAMPLE):\n    img += [imread(os.path.join(train_image_dir, sample_images[i][0]))]\n    seg += [masks_as_image(sample_images[i][1]['EncodedPixels'].values)]\n\nimg = np.stack(img, 0)/255.0\nseg = np.stack(seg, 0)\n\nprint('x', img.shape, img.min(), img.max())\nprint('y', seg.shape, seg.min(), seg.max())\n    \nbatch_rgb = montage_rgb(img)\nbatch_seg = montage(seg[:, :, :, 0])\nax1.imshow(batch_rgb)\nax1.set_title('Images')\nax2.imshow(batch_seg)\nax2.set_title('Segmentations')\nax3.imshow(mark_boundaries(batch_rgb, \n                           batch_seg.astype(int)))\nax3.set_title('Outlined Ships')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Make bounding box"},{"metadata":{"trusted":true},"cell_type":"code","source":"def mask_to_box(img):\n    x_min = img.shape[1]\n    y_min = img.shape[0]\n    x_max = 0\n    y_max = 0\n    for i in range(img.shape[0]): # height\n        for j in range(img.shape[1]): # width\n            if img[i][j] == 1:\n                x_min = min(x_min, j)\n                y_min = min(y_min, i)\n                x_max = max(x_max, j)\n                y_max = max(y_max, i)\n    return x_min, y_min, x_max, y_max","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# too time consuming\n#modified_data['bounding_box'] = modified_data['EncodedPixels'].apply(mask_to_box)\n#modified_data.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def coor_to_box(box_coor, shape=(768,768)):\n    img = np.zeros(shape, dtype=np.int16)\n    for i in range(box_coor[0],box_coor[2]+1):\n        img[box_coor[1]][i] = 1\n        img[box_coor[3]][i] = 1\n    for j in range(box_coor[1],box_coor[3]+1):\n        img[j][box_coor[0]] = 1\n        img[j][box_coor[2]] = 1\n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"NUMBER_IN_SAMPLE = 4\nnp.random.shuffle(all_images)\nsample_images = all_images[:NUMBER_IN_SAMPLE]\n\nfig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (30, 10))\n\nimg = []\nseg = []\nbox = []\nfor i in range(NUMBER_IN_SAMPLE):\n    img += [imread(os.path.join(train_image_dir, sample_images[i][0]))]\n    m_img = masks_as_image(sample_images[i][1]['EncodedPixels'].values)\n    seg += [m_img]\n    box += [np.expand_dims(coor_to_box(mask_to_box(m_img)),-1)]\n\nimg = np.stack(img, 0)/255.0\nseg = np.stack(seg, 0)\nbox = np.stack(box, 0)\n\n\nprint('x', img.shape, img.min(), img.max())\nprint('y', seg.shape, seg.min(), seg.max())\nprint('z', box.shape, box.min(), box.max())\n    \nbatch_rgb = montage_rgb(img)\nbatch_seg = montage(seg[:, :, :, 0])\nbatch_box = montage(box[:, :, :, 0])\nax1.imshow(batch_rgb)\nax1.set_title('Images')\nax2.imshow(batch_seg)\nax2.set_title('Segmentations')\nax3.imshow(mark_boundaries(batch_rgb, \n                           batch_box.astype(int)))\nax3.set_title('Outlined Ships')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"yet, needed to be repaired.. such as **'make separate boxes per mask'** or **'time consuming issues'**(too much time needed for making bounding boxes for all of the images)"}],"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":1}