{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Carvana Image Masking Challenge","metadata":{}},{"cell_type":"code","source":"IMG_ROWS = 480\nIMG_COLS = 320\n\nTEST_IMG_ROWS = 1918\nTEST_IMG_COLS = 1280","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:40:10.621373Z","iopub.execute_input":"2021-12-17T11:40:10.621861Z","iopub.status.idle":"2021-12-17T11:40:10.626118Z","shell.execute_reply.started":"2021-12-17T11:40:10.621826Z","shell.execute_reply":"2021-12-17T11:40:10.625377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport numpy as np\nimport imageio\nfrom scipy import ndimage\nfrom glob import glob\nimport zipfile\n\nSAMPLE = 1000","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:40:11.572626Z","iopub.execute_input":"2021-12-17T11:40:11.573445Z","iopub.status.idle":"2021-12-17T11:40:12.114074Z","shell.execute_reply.started":"2021-12-17T11:40:11.573398Z","shell.execute_reply":"2021-12-17T11:40:12.113084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path_to_zip_file = \"../input/carvana-image-masking-challenge/train.zip\"\ndirectory_to_extract_to = \"../output/kaggle/working\"\nwith zipfile.ZipFile(path_to_zip_file, 'r') as zip_ref:\n    zip_ref.extractall(directory_to_extract_to)\n    \npath_to_zip_file = \"../input/carvana-image-masking-challenge/train_masks.zip\"\ndirectory_to_extract_to = \"../output/kaggle/working\"\nwith zipfile.ZipFile(path_to_zip_file, 'r') as zip_ref:\n    zip_ref.extractall(directory_to_extract_to)","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:40:13.303935Z","iopub.execute_input":"2021-12-17T11:40:13.304211Z","iopub.status.idle":"2021-12-17T11:40:22.311516Z","shell.execute_reply.started":"2021-12-17T11:40:13.304180Z","shell.execute_reply":"2021-12-17T11:40:22.310743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from subprocess import check_output\nprint(check_output([\"ls\", \"../output/kaggle/working\"]).decode(\"utf8\"))","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:40:22.313037Z","iopub.execute_input":"2021-12-17T11:40:22.313282Z","iopub.status.idle":"2021-12-17T11:40:22.335534Z","shell.execute_reply.started":"2021-12-17T11:40:22.313247Z","shell.execute_reply":"2021-12-17T11:40:22.334395Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_img_paths = sorted(glob('../output/kaggle/working/train/*.jpg'))[:SAMPLE]\ntrain_mask_paths = sorted(glob('../output/kaggle/working/train_masks/*.gif'))[:SAMPLE]","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:40:22.337030Z","iopub.execute_input":"2021-12-17T11:40:22.337531Z","iopub.status.idle":"2021-12-17T11:40:22.487943Z","shell.execute_reply.started":"2021-12-17T11:40:22.337491Z","shell.execute_reply":"2021-12-17T11:40:22.487169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_imgs = np.array([cv2.resize(imageio.imread(path), (IMG_ROWS, IMG_COLS))\n                        for path in train_img_paths])\n\ntrain_masks = np.array([cv2.resize(imageio.imread(path), (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))","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:40:22.490069Z","iopub.execute_input":"2021-12-17T11:40:22.490354Z","iopub.status.idle":"2021-12-17T11:41:28.068694Z","shell.execute_reply.started":"2021-12-17T11:40:22.490305Z","shell.execute_reply":"2021-12-17T11:41:28.067955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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')","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:41:28.069897Z","iopub.execute_input":"2021-12-17T11:41:28.070176Z","iopub.status.idle":"2021-12-17T11:41:28.526011Z","shell.execute_reply.started":"2021-12-17T11:41:28.070140Z","shell.execute_reply":"2021-12-17T11:41:28.525232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Инициализируем архитектуру U-Net","metadata":{}},{"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","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:41:28.527602Z","iopub.execute_input":"2021-12-17T11:41:28.527853Z","iopub.status.idle":"2021-12-17T11:41:33.004714Z","shell.execute_reply.started":"2021-12-17T11:41:28.527812Z","shell.execute_reply":"2021-12-17T11:41:33.003949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inputs = 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])","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:41:33.006187Z","iopub.execute_input":"2021-12-17T11:41:33.006453Z","iopub.status.idle":"2021-12-17T11:41:35.555306Z","shell.execute_reply.started":"2021-12-17T11:41:33.006417Z","shell.execute_reply":"2021-12-17T11:41:35.554626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.python.client import device_lib;print(device_lib.list_local_devices())","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:41:35.556441Z","iopub.execute_input":"2021-12-17T11:41:35.556673Z","iopub.status.idle":"2021-12-17T11:41:35.567741Z","shell.execute_reply.started":"2021-12-17T11:41:35.556640Z","shell.execute_reply":"2021-12-17T11:41:35.567026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:41:35.568789Z","iopub.execute_input":"2021-12-17T11:41:35.569610Z","iopub.status.idle":"2021-12-17T11:41:35.595803Z","shell.execute_reply.started":"2021-12-17T11:41:35.569558Z","shell.execute_reply":"2021-12-17T11:41:35.595142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Задаем функцию потерь","metadata":{}},{"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)","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:41:35.596946Z","iopub.execute_input":"2021-12-17T11:41:35.597263Z","iopub.status.idle":"2021-12-17T11:41:35.603289Z","shell.execute_reply.started":"2021-12-17T11:41:35.597227Z","shell.execute_reply":"2021-12-17T11:41:35.602390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Запускаем процесс обучения","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.optimizers import Adam\nmodel.compile(Adam(lr=1e-4),\n              bce_dice_loss,\n              metrics=[binary_crossentropy, dice_coef])","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:41:35.606126Z","iopub.execute_input":"2021-12-17T11:41:35.606631Z","iopub.status.idle":"2021-12-17T11:41:35.922908Z","shell.execute_reply.started":"2021-12-17T11:41:35.606589Z","shell.execute_reply":"2021-12-17T11:41:35.922158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.fit(train_imgs[50:], train_masks[50:],\n          batch_size=12, epochs=10, \n          validation_data=(train_imgs[:50], train_masks[:50]))","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:41:35.924159Z","iopub.execute_input":"2021-12-17T11:41:35.924588Z","iopub.status.idle":"2021-12-17T11:46:01.160046Z","shell.execute_reply.started":"2021-12-17T11:41:35.924541Z","shell.execute_reply":"2021-12-17T11:46:01.159256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Предсказание модели","metadata":{}},{"cell_type":"code","source":"path_to_zip_file = \"../input/carvana-image-masking-challenge/test.zip\"\ndirectory_to_extract_to = \"../output/kaggle/working\"\nwith zipfile.ZipFile(path_to_zip_file, 'r') as zip_ref:\n    zip_ref.extractall(directory_to_extract_to)","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:46:01.161299Z","iopub.execute_input":"2021-12-17T11:46:01.161657Z","iopub.status.idle":"2021-12-17T11:48:56.264853Z","shell.execute_reply.started":"2021-12-17T11:46:01.161618Z","shell.execute_reply":"2021-12-17T11:48:56.264042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_paths = sorted(glob('../output/kaggle/working/test/*.jpg'))\n\n#test_imgs = np.array([cv2.resize(imageio.imread(path), (IMG_ROWS, IMG_COLS))\n #                       for path in train_img_paths])","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:48:56.268081Z","iopub.execute_input":"2021-12-17T11:48:56.268685Z","iopub.status.idle":"2021-12-17T11:48:56.673096Z","shell.execute_reply.started":"2021-12-17T11:48:56.268652Z","shell.execute_reply":"2021-12-17T11:48:56.672345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"def test_img_generator(test_paths):\n    while True:\n        for path in test_paths:\n            yield np.array([cv2.resize(imageio.imread(path), (IMG_ROWS, IMG_COLS))])","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:48:56.674230Z","iopub.execute_input":"2021-12-17T11:48:56.674484Z","iopub.status.idle":"2021-12-17T11:48:58.548191Z","shell.execute_reply.started":"2021-12-17T11:48:56.674450Z","shell.execute_reply":"2021-12-17T11:48:58.547124Z"}}},{"cell_type":"markdown","source":"pred = model.predict(test_img_generator(test_paths[:10]), len(test_paths[:10]))","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:48:58.549541Z","iopub.execute_input":"2021-12-17T11:48:58.549949Z","iopub.status.idle":"2021-12-17T11:50:38.837461Z","shell.execute_reply.started":"2021-12-17T11:48:58.549912Z","shell.execute_reply":"2021-12-17T11:50:38.836178Z"}}},{"cell_type":"markdown","source":"## Визуализируем результат","metadata":{}},{"cell_type":"markdown","source":"fig = plt.figure(0, figsize=(20, 10))\nk = 5\nfig.add_subplot(2, 2, 1)\nplt.imshow(imageio.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(imageio.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')","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:50:38.838752Z","iopub.status.idle":"2021-12-17T11:50:38.839441Z","shell.execute_reply.started":"2021-12-17T11:50:38.839168Z","shell.execute_reply":"2021-12-17T11:50:38.839194Z"}}},{"cell_type":"markdown","source":"## Подготавливаем данные для отправки","metadata":{}},{"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","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:50:38.840643Z","iopub.status.idle":"2021-12-17T11:50:38.841242Z","shell.execute_reply.started":"2021-12-17T11:50:38.841003Z","shell.execute_reply":"2021-12-17T11:50:38.841026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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(imageio.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))","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:50:38.842405Z","iopub.status.idle":"2021-12-17T11:50:38.842999Z","shell.execute_reply.started":"2021-12-17T11:50:38.842772Z","shell.execute_reply":"2021-12-17T11:50:38.842796Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from subprocess import check_output\nprint(check_output([\"ls\", \"../working\"]).decode(\"utf8\"))","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:50:38.844169Z","iopub.status.idle":"2021-12-17T11:50:38.844775Z","shell.execute_reply.started":"2021-12-17T11:50:38.844549Z","shell.execute_reply":"2021-12-17T11:50:38.844572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import csv\n\nwith open('../working/submit.txt', 'r') as in_file:\n    stripped = (line.strip() for line in in_file)\n    lines = (line.split(\",\") for line in stripped if line)\n    with open('submission.csv', 'w') as out_file:\n        writer = csv.writer(out_file)\n        writer.writerows(lines)","metadata":{"execution":{"iopub.status.busy":"2021-12-17T11:50:38.845903Z","iopub.status.idle":"2021-12-17T11:50:38.846524Z","shell.execute_reply.started":"2021-12-17T11:50:38.846276Z","shell.execute_reply":"2021-12-17T11:50:38.846299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}