{"metadata": {"kernelspec": {"language": "python", "name": "python3", "display_name": "Python 3"}, "language_info": {"codemirror_mode": {"version": 3, "name": "ipython"}, "pygments_lexer": "ipython3", "file_extension": ".py", "mimetype": "text/x-python", "nbconvert_exporter": "python", "version": "3.6.1", "name": "python"}}, "nbformat": 4, "cells": [{"metadata": {"collapsed": true, "_execution_state": "idle", "_uuid": "da289a8da91de630b07363d12be05cd997bd3c08", "_cell_guid": "a7dd7f70-348f-4e49-a7be-b85543df6ec2", "trusted": true}, "outputs": [], "source": "import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom skimage.io import imread\nfrom skimage.transform import downscale_local_mean\nfrom os.path import join\nfrom tqdm import tqdm_notebook\nimport cv2\nfrom sklearn.model_selection import train_test_split\n\ninput_folder = join('..', 'input')\n\ndf_mask = pd.read_csv(join(input_folder, 'train_masks.csv'), usecols=['img'])\nids_train = df_mask['img'].map(lambda s: s.split('_')[0]).unique()\n\nimgs_idx = list(range(1, 17))", "cell_type": "code", "execution_count": 1}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "ec3cbbbc51dbf8d460e1dfe27c0a9d4684e2f417", "_cell_guid": "e2d4c1aa-6632-4ab2-9ebc-4010ae62d4fd", "collapsed": true}, "outputs": [], "source": "load_img = lambda im, idx: imread(join(input_folder, 'train', '{}_{:02d}.jpg'.format(im, idx)))\nload_mask = lambda im, idx: imread(join(input_folder, 'train_masks', '{}_{:02d}_mask.gif'.format(im, idx)))\nresize = lambda im: downscale_local_mean(im, (4,4) if im.ndim==2 else (4,4,1))\nmask_image = lambda im, mask: (im * np.expand_dims(mask, 2))", "cell_type": "code", "execution_count": 2}, {"metadata": {"trusted": true, "_execution_state": "busy", "_uuid": "f7cf80499f3276ad7515cbc4e6beb4b3aa6025b5", "_cell_guid": "a326095e-915d-4010-89d9-e5fdae29557e"}, "outputs": [], "source": "num_train = 32  # len(ids_train)\n\n# Load data for position id=1\nX = np.empty((num_train, 320, 480, 12), dtype=np.float32)\ny = np.empty((num_train, 320, 480, 1), dtype=np.float32)\n\nwith tqdm_notebook(total=num_train) as bar:\n    idx = 1 # Rotation index\n    for i, img_id in enumerate(ids_train[:num_train]):\n        imgs_id = [resize(load_img(img_id, j)) for j in imgs_idx]\n        # Input is image + mean image per channel + std image per channel\n        X[i, ..., :9] = np.concatenate([imgs_id[idx-1], np.mean(imgs_id, axis=0), np.std(imgs_id, axis=0)], axis=2)\n        y[i] = resize(np.expand_dims(load_mask(img_id, idx), 2)) / 255.\n        del imgs_id # Free memory\n        bar.update()", "cell_type": "code", "execution_count": 3}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "1ddd542d69fb2864eb7b249f2725e761dc88fe65", "_cell_guid": "76f63a38-9d44-4f41-bd11-e9de85e7153a", "collapsed": true}, "outputs": [], "source": "X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)", "cell_type": "code", "execution_count": 4}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "d2b36b72192a699865dcf47a86bf1d1cc35a44fe", "_cell_guid": "d1aec6c7-7ac0-48e2-9e15-7ae758c25192", "collapsed": true}, "outputs": [], "source": "# Concat overall y info to X\n# This is important as the kernels of CNN used below has no information of its location\ny_train_mean = y_train.mean(axis=0)\ny_train_std = y_train.std(axis=0)\ny_train_min = y_train.min(axis=0)\n\ny_features = np.concatenate([y_train_mean, y_train_std, y_train_min], axis=2)\n\nX_train[:, ..., -3:] = y_features\nX_val[:, ..., -3:] = y_features", "cell_type": "code", "execution_count": 5}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "04091a9270eaf4a1decfc5c57493118b75b24a79", "_cell_guid": "989df4b5-d155-4353-b4c1-e7dbed04e554", "collapsed": true}, "outputs": [], "source": "# Normalize input and output\nX_mean = X_train.mean(axis=(0,1,2), keepdims=True)\nX_std = X_train.std(axis=(0,1,2), keepdims=True)\n\nX_train -= X_mean\nX_train /= X_std\n\nX_val -= X_mean\nX_val /= X_std", "cell_type": "code", "execution_count": 6}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "a10d2e2d5dda8ca70550548e811bcd045b7cf3fc", "_cell_guid": "0063e2ce-1679-424a-befa-68b82d2c0ab8"}, "outputs": [], "source": "# Create simple model\nfrom keras.layers import Conv2D, MaxPooling2D, Conv2DTranspose, Input, concatenate\nfrom keras.models import Model\nimport keras.backend as K\n\ninp = Input((320, 480, 12))\nconv1 = Conv2D(12, 3, activation='relu', padding='same')(inp)\nmax1 = MaxPooling2D(2)(conv1)\nconv2 = Conv2D(12, 3, activation='relu', padding='same')(max1)\nmax2 = MaxPooling2D(2)(conv2)\nconv3 = Conv2D(12, 3, activation='relu', padding='same')(max2)\n\ndeconv3 = Conv2DTranspose(12, 3, strides=4, activation='relu', padding='same')(conv3)\ndeconv2 = Conv2DTranspose(12, 3, strides=2, activation='relu', padding='same')(conv2)\n\ndeconvs = concatenate([conv1, deconv2, deconv3])\n\nout = Conv2D(1, 7, activation='sigmoid', padding='same')(deconvs)\n\nmodel = Model(inp, out)\nmodel.summary()", "cell_type": "code", "execution_count": 7}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "446deb6830d09d449b9580563566027ca5563afa", "_cell_guid": "32e333e1-e7e7-4764-8fbd-80f1e88c5b70", "collapsed": true}, "outputs": [], "source": "from keras.optimizers import Adam\nfrom keras.losses import binary_crossentropy\n\nsmooth = 1.\n\n# From here: https://github.com/jocicmarko/ultrasound-nerve-segmentation/blob/master/train.py\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)\n\ndef dice_loss(y_true, y_pred):\n    return -dice_coef(y_true, y_pred)\n\nmodel.compile(Adam(lr=1e-3), dice_loss, metrics=['accuracy', dice_coef])", "cell_type": "code", "execution_count": 8}, {"metadata": {"scrolled": true, "trusted": true, "_execution_state": "idle", "_uuid": "337205abca7bdd6064ecccfb612b3fb5cb587a54", "_cell_guid": "166062b9-66fe-4cdb-bb0f-2dbac4fdbafe"}, "outputs": [], "source": "history = model.fit(X_train, y_train, epochs=15, validation_data=(X_val, y_val), batch_size=5, verbose=1)", "cell_type": "code", "execution_count": 9}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "d461bec0b38d15f398f63faf5c5f721634b80546", "_cell_guid": "551591f5-1541-428b-a472-31f8365bc555"}, "outputs": [], "source": "pd.DataFrame(history.history)[['dice_coef', 'val_dice_coef']].plot()", "cell_type": "code", "execution_count": null}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "45c065685f88d6bd1ec33a429c28e3a36cd52588", "_cell_guid": "06b5003e-a4ba-49dd-a488-be92b362975e"}, "outputs": [], "source": "idx = 0\nx = X_val[idx]\n\nfig, ax = plt.subplots(5,3, figsize=(16, 16))\nax = ax.ravel()\n\ncmaps = ['Reds', 'Greens', 'Blues']\nfor i in range(x.shape[-1]):\n    ax[i].imshow(x[...,i], cmap='gray') #cmaps[i%3])\n    ax[i].set_title('channel {}'.format(i))\n\nax[-3].imshow((x[...,:3] * X_std[0,...,:3] + X_mean[0,...,:3]) / 255.)\nax[-3].set_title('X')\n\nax[-2].imshow(y_val[idx,...,0], cmap='gray')\nax[-2].set_title('y')\n\ny_pred = model.predict(x[None]).squeeze()\nax[-1].imshow(y_pred, cmap='gray')\nax[-1].set_title('y_pred')", "cell_type": "code", "execution_count": null}, {"metadata": {"trusted": true, "_execution_state": "idle", "_uuid": "344427a75091f65fdb01ea0b352c436847c47093", "_cell_guid": "cadf3a5c-f63f-4836-8050-9cac33507b12", "collapsed": true}, "outputs": [], "source": "plt.imshow(y_pred > 0.5, cmap='gray')", "cell_type": "code", "execution_count": null}, {"metadata": {"trusted": false, "_execution_state": "idle", "_uuid": "c298fc64a6b516140687f2241d90f75cf0e5f622", "_cell_guid": "e4ff72f4-1a7e-42c0-9e70-c9db615b13fe", "collapsed": true}, "outputs": [], "source": "", "cell_type": "code", "execution_count": null}], "nbformat_minor": 1}