{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Blending submissions using np.logical_or"},{"metadata":{},"cell_type":"markdown","source":"This kernels shows an example of blending masks using the np.logical_or function. I try blending three submissions which has 0.66842, 0.67042 and 0.67291 public scores, respectively, and see if there is an improvement."},{"metadata":{"trusted":true},"cell_type":"code","source":"from subprocess import check_output\n\nprint(check_output([\"ls\", \"../input\"]).decode(\"utf8\"))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"import os\nimport json\nimport gc\n\nimport albumentations as albu\nimport cv2\nimport keras\nfrom keras import backend as K\nfrom keras.models import Model\nfrom keras.layers import Input, Dropout, Conv2D, BatchNormalization, add, LeakyReLU\nfrom keras.layers.convolutional import Conv2D, Conv2DTranspose\nfrom keras.layers.pooling import MaxPooling2D\nfrom keras.layers.merge import concatenate, Concatenate, Add\nfrom keras.losses import binary_crossentropy\nfrom keras.callbacks import Callback, ModelCheckpoint, LearningRateScheduler, EarlyStopping, ReduceLROnPlateau\nfrom skimage.exposure import adjust_gamma\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom tqdm import tqdm, tqdm_notebook\nimport keras.backend as K\nfrom keras.legacy import interfaces\nfrom keras.optimizers import Optimizer\n\ndef np_resize(img, input_shape):\n    \"\"\"\n    Reshape a numpy array, which is input_shape=(height, width), \n    as opposed to input_shape=(width, height) for cv2\n    \"\"\"\n    height, width = input_shape\n    return cv2.resize(img, (width, height))\n    \ndef mask2rle(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 rle2mask(rle, input_shape):\n    width, height = input_shape[:2]\n    \n    mask= np.zeros( width*height ).astype(np.uint8)\n    \n    array = np.asarray([int(x) for x in rle.split()])\n    starts = array[0::2]\n    lengths = array[1::2]\n\n    current_position = 0\n    for index, start in enumerate(starts):\n        mask[int(start):int(start+lengths[index])] = 1\n        current_position += lengths[index]\n        \n    return mask.reshape(height, width).T\n\ndef build_masks(rles, input_shape, reshape=None):\n    depth = len(rles)\n    if reshape is None:\n        masks = np.zeros((*input_shape, depth))\n    else:\n        masks = np.zeros((*reshape, depth))\n    \n    for i, rle in enumerate(rles):\n        if type(rle) is str:\n            if reshape is None:\n                masks[:, :, i] = rle2mask(rle, input_shape)\n            else:\n                mask = rle2mask(rle, input_shape)\n                reshaped_mask = np_resize(mask, reshape)\n                masks[:, :, i] = reshaped_mask\n    \n    return masks\n\ndef build_rles(masks, reshape=None):\n    width, height, depth = masks.shape\n    \n    rles = []\n    \n    for i in range(depth):\n        mask = masks[:, :, i]\n        \n        if reshape:\n            mask = mask.astype(np.float32)\n            mask = np_resize(mask, reshape).astype(np.int64)\n        \n        rle = mask2rle(mask)\n        rles.append(rle)\n        \n    return rles\n\ndef dice_coef(y_true, y_pred, smooth=1):\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n    intersection = K.sum(y_true_f * y_pred_f)\n    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n\ndef dice_loss(y_true, y_pred):\n    smooth = 1.\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n    intersection = y_true_f * y_pred_f\n    score = (2. * K.sum(intersection) + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n    return 1. - score\n\ndef bce_dice_loss(y_true, y_pred):\n    return binary_crossentropy(y_true, y_pred) + dice_loss(y_true, y_pred)\n\ndef post_process(probability, threshold, min_size):\n    \"\"\"\n    Post processing of each predicted mask, components with lesser number of pixels\n    than `min_size` are ignored\n    \"\"\"\n    \n    mask = cv2.threshold(probability, threshold, 1, cv2.THRESH_BINARY)[1]\n    \n    num_component, component = cv2.connectedComponents(mask.astype(np.uint8))\n    predictions = np.zeros((350, 525), np.float32)\n    num = 0\n    for c in range(1, num_component):\n        p = (component == c)\n        if p.sum() > min_size:\n            predictions[p] = 1\n            num += 1\n    return predictions, num\n\ndef post_process_minsize(mask, min_size):\n    \"\"\"\n    Post processing of each predicted mask, components with lesser number of pixels\n    than `min_size` are ignored\n    \"\"\"\n    \n    num_component, component = cv2.connectedComponents(mask.astype(np.uint8))\n    predictions = np.zeros(mask.shape)\n    num = 0\n    for c in range(1, num_component):\n        p = (component == c)\n        if p.sum() > min_size:\n            predictions[p] = 1\n            num += 1\n    return predictions\n\ndef draw_convex_hull(mask, mode='convex'):\n    \n    img = np.zeros(mask.shape)\n    contours, hier = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\n    \n    for c in contours:\n        if mode=='rect': # simple rectangle\n            x, y, w, h = cv2.boundingRect(c)\n            cv2.rectangle(img, (x, y), (x+w, y+h), (255, 255, 255), -1)\n        elif mode=='convex': # minimum convex hull\n            hull = cv2.convexHull(c)\n            cv2.drawContours(img, [hull], 0, (255, 255, 255),-1)\n        elif mode=='approx':\n            epsilon = 0.02*cv2.arcLength(c,True)\n            approx = cv2.approxPolyDP(c,epsilon,True)\n            cv2.drawContours(img, [approx], 0, (255, 255, 255),-1)\n        else: # minimum area rectangle\n            rect = cv2.minAreaRect(c)\n            box = cv2.boxPoints(rect)\n            box = np.int0(box)\n            cv2.drawContours(img, [box], 0, (255, 255, 255),-1)\n    return img/255.\n\ndef dice(img1, img2):\n    img1 = np.asarray(img1).astype(np.bool)\n    img2 = np.asarray(img2).astype(np.bool)\n\n    intersection = np.logical_and(img1, img2)\n\n    return 2. * intersection.sum() / (img1.sum() + img2.sum())\n\ndef rle_decode(mask_rle, shape=(1400, 2100)):\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, order='F')  # Needed to align to RLE direction","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Blending"},{"metadata":{"trusted":true},"cell_type":"code","source":"# 0.66842\nsub_1 = pd.read_csv('../input/submission-examples/sub66842.csv', keep_default_na=True)\n\nsub_1['ImageId'] = sub_1['Image_Label'].apply(lambda x: x.split('_')[0])\nsub_1['EncodedPixels'].replace({np.nan: ''}, inplace=True)\nsub_1.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 0.67042\nsub_2 = pd.read_csv('../input/submission-examples/sub67042.csv', keep_default_na=True)\n\nsub_2['ImageId'] = sub_2['Image_Label'].apply(lambda x: x.split('_')[0])\nsub_2['EncodedPixels'].replace({np.nan: ''}, inplace=True)\nsub_2.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 0.67291\nsub_3 = pd.read_csv('../input/submission-examples/sub67291.csv', keep_default_na=True)\n\nsub_3['ImageId'] = sub_3['Image_Label'].apply(lambda x: x.split('_')[0])\nsub_3['EncodedPixels'].replace({np.nan: ''}, inplace=True)\nsub_3.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"enc_pixels_list = []\n\nfor index, row in tqdm_notebook(sub_1.iterrows(), total=sub_1.shape[0]):\n\n    mask_rle_1 = row['EncodedPixels']\n    mask_rle_2 = sub_2.loc[index, 'EncodedPixels']\n    mask_rle_3 = sub_3.loc[index, 'EncodedPixels']\n    \n    mask_1 = rle2mask(mask_rle_1, (350, 525, 3))\n    mask_2 = rle2mask(mask_rle_2, (350, 525, 3))\n    mask_3 = rle2mask(mask_rle_3, (350, 525, 3))\n    \n    mask = np.logical_or(mask_1, mask_2, mask_3)\n    enc_pixels_list.append(mask2rle(mask))\n\nsub_2['EncodedPixels'] = enc_pixels_list\nsub_2.drop('ImageId', axis=1, inplace=True)\nsub_2.to_csv('blended_mask.csv', index=None)\nsub_2.head(10)","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":1}