{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Carvana Image Masking Challenge"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"IMG_ROWS = 480\nIMG_COLS = 320\n\nTEST_IMG_ROWS = 1918\nTEST_IMG_COLS = 1280","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\nimport numpy as np\nfrom scipy import ndimage\nfrom glob import glob\n\nSAMPLE = 5000\n\ntrain_img_paths = sorted(glob('/kaggle/input/carvana-image-masking-challenge/train/*.jpg'))[:SAMPLE]\ntrain_mask_paths = sorted(glob('/kaggle/input/carvana-image-masking-challenge/train_masks/*.gif'))[:SAMPLE]\n\ntrain_imgs = np.array([cv2.resize(ndimage.imread(path), (IMG_ROWS, IMG_COLS))\n                        for path in train_img_paths])\n\ntrain_masks = np.array([cv2.resize(ndimage.imread(path, mode = 'L'), (IMG_ROWS, IMG_COLS))\n                        for path in train_mask_paths])\n\ntrain_masks = train_masks.astype(np.float32)\ntrain_masks[train_masks<=127] = 0.\ntrain_masks[train_masks>127] = 1.\ntrain_masks = np.reshape(train_masks, (*train_masks.shape, 1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\nfrom matplotlib import pyplot as plt\nfig = plt.figure(0, figsize=(20, 20))\nfig.add_subplot(1, 2, 1)\nplt.imshow(train_imgs[0])\nfig.add_subplot(1, 2, 2)\nplt.imshow(np.squeeze(train_masks[0]), cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Use U-net"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.layers import Input\nfrom keras.layers import Conv2D\nfrom keras.layers import MaxPooling2D\nfrom keras.layers import Conv2DTranspose\nfrom keras.layers import BatchNormalization\nfrom keras.layers import concatenate\nfrom keras.models import Model\n\ninputs = Input((IMG_COLS, IMG_ROWS, 3))\nbnorm1 = BatchNormalization()(inputs)\nconv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(bnorm1)\nconv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)\npool1 = MaxPooling2D(pool_size=(2, 2))(conv1)\n\nconv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1)\nconv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)\npool2 = MaxPooling2D(pool_size=(2, 2))(conv2)\n\nconv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2)\nconv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)\npool3 = MaxPooling2D(pool_size=(2, 2))(conv3)\n\nconv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(pool3)\nconv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)\npool4 = MaxPooling2D(pool_size=(2, 2))(conv4)\n\nconv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(pool4)\nconv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)\n\nup6 = concatenate([Conv2DTranspose(256, (2, 2), strides=(2, 2), padding='same')(conv5), conv4], axis=3)\nconv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)\nconv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)\n\nup7 = concatenate([Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(conv6), conv3], axis=3)\nconv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)\nconv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)\n\nup8 = concatenate([Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(conv7), conv2], axis=3)\nconv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)\nconv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)\n\nup9 = concatenate([Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(conv8), conv1], axis=3)\nconv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)\nconv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)\n\nconv10 = Conv2D(1, (1, 1), activation='sigmoid')(conv9)\n\nmodel = Model(inputs=[inputs], outputs=[conv10])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Loss function"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import backend as K\nfrom keras.losses import binary_crossentropy\n\nSMOOTH = 1.\n\ndef dice_coef(y_true, y_pred):\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 bce_dice_loss(y_true, y_pred):\n    return 0.5 * binary_crossentropy(y_true, y_pred) - dice_coef(y_true, y_pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.optimizers import Adam\nmodel.compile(Adam(lr=1e-4),\n              bce_dice_loss,\n              metrics=[binary_crossentropy, dice_coef])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.fit(train_imgs[50:], train_masks[50:],\n          batch_size=12, epochs=20, \n          validation_data=(train_imgs[:50], train_masks[:50]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_paths = sorted(glob('/kaggle/input/carvana-image-masking-challenge/test/*.jpg'))\n\ndef test_img_generator(test_paths):\n    while True:\n        for path in test_paths:\n            yield np.array([cv2.resize(ndimage.imread(path), (IMG_ROWS, IMG_COLS))])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = model.predict_generator(test_img_generator(test_paths[:10]), len(test_paths[:10]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(0, figsize=(20, 10))\nk = 5\nfig.add_subplot(2, 2, 1)\nplt.imshow(ndimage.imread(test_paths[k]))\nfig.add_subplot(2, 2, 2)\nplt.imshow(np.squeeze(cv2.resize(pred[k], (TEST_IMG_ROWS, TEST_IMG_COLS))), cmap='gray')\nfig.add_subplot(2, 2, 3)\nplt.imshow(ndimage.imread(test_paths[k+1]))\nfig.add_subplot(2, 2, 4)\nplt.imshow(np.squeeze(cv2.resize(pred[k+1], (TEST_IMG_ROWS, TEST_IMG_COLS))), cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def rle_encode(mask):\n    pixels = mask.flatten()\n    pixels[0] = 0\n    pixels[-1] = 0\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 2\n    runs[1::2] = runs[1::2] - runs[:-1:2]\n    return runs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with open('submit.txt', 'w') as dst:\n    dst.write('img,rle_mask\\n')\n    for path in test_paths:\n        img = np.array([cv2.resize(ndimage.imread(path), (IMG_ROWS, IMG_COLS))])\n        pred_mask = model.predict(img)[0]\n        bin_mask = 255. * cv2.resize(pred_mask, (TEST_IMG_ROWS, TEST_IMG_COLS))\n        bin_mask[bin_mask<=127] = 0\n        bin_mask[bin_mask>127] = 1\n        rle = rle_encode(bin_mask.astype(np.uint8))\n        rle = ' '.join(str(x) for x in rle)\n        dst.write('%s,%s\\n' % (path.split('/')[-1], rle))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 20 epochs\n# loss: -0.9891 - binary_crossentropy: 0.0077 - dice_coef: 0.9930\n# val_loss: -0.9889 - val_binary_crossentropy: 0.0085 - val_dice_coef: 0.9932\n# kaggle: 0.9926","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}