{"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":"# Libs","metadata":{}},{"cell_type":"code","source":"%%time\n\nimport os\nimport imageio\n\nimport pandas as pd\nimport numpy as np\n\nimport tensorflow as tf\nfrom tensorflow.keras import layers\n\nimport matplotlib.pyplot as plt\nfrom IPython import display","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:30:46.994809Z","iopub.execute_input":"2021-12-07T02:30:46.9954Z","iopub.status.idle":"2021-12-07T02:30:52.08263Z","shell.execute_reply.started":"2021-12-07T02:30:46.995327Z","shell.execute_reply":"2021-12-07T02:30:52.081128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Base variables\n\nPaths to files","metadata":{}},{"cell_type":"code","source":"TRAIN_DIR = '../input/sartorius-cell-instance-segmentation/train/'\nTRAIN_CSV = '../input/sartorius-cell-instance-segmentation/train.csv'\n\nTEST_DIR = '../input/sartorius-cell-instance-segmentation/test/'","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:30:52.084301Z","iopub.execute_input":"2021-12-07T02:30:52.084671Z","iopub.status.idle":"2021-12-07T02:30:52.089009Z","shell.execute_reply.started":"2021-12-07T02:30:52.084627Z","shell.execute_reply":"2021-12-07T02:30:52.088077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"variables from _train_df_","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv(TRAIN_CSV)\n\nTRAIN_IDS = train_df['id'].unique()\nWIDTH, HEIGHT = train_df.loc[0, ['width', 'height']]","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:30:52.091118Z","iopub.execute_input":"2021-12-07T02:30:52.091632Z","iopub.status.idle":"2021-12-07T02:30:52.62726Z","shell.execute_reply.started":"2021-12-07T02:30:52.091597Z","shell.execute_reply":"2021-12-07T02:30:52.626553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Get images","metadata":{}},{"cell_type":"code","source":"def get_mask(df: str, idx: str) -> np.ndarray:\n    \"\"\"get mask for image from dataframe\n    \n    params: \n        df:  dataframe from which the mask will be taken\n        idx: mask index from dataframe\"\"\"\n    \n    parts = df[df['id'] == idx]\n    \n    mask = np.zeros(WIDTH * HEIGHT)\n    \n    for part in parts['annotation']:\n        part = part.split()\n        part = np.array(part, dtype=np.uint)\n        part = part.reshape(-1, 2)\n        part[:, 0] -=1\n        \n        for i in range(len(part)):\n            \n            part_row = part[i]\n            part_row = np.arange(part_row[0], part_row[0]+part_row[1])\n            part_row = part_row.astype(np.uint)\n            mask[part_row] = 1\n            \n    mask = mask.reshape(HEIGHT, WIDTH)\n            \n    return mask\n\ndef get_image(path: str) -> np.ndarray:\n    \"\"\"get image from the paved path\n    \n    params:\n        path: path to image\"\"\"\n    \n    img = imageio.imread(path)\n    img = np.array(img)\n    \n    return img","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:30:52.629323Z","iopub.execute_input":"2021-12-07T02:30:52.629734Z","iopub.status.idle":"2021-12-07T02:30:52.638619Z","shell.execute_reply.started":"2021-12-07T02:30:52.629685Z","shell.execute_reply":"2021-12-07T02:30:52.637648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\ntrain_imgs = np.array([get_image(TRAIN_DIR + idx + '.png') for idx in TRAIN_IDS])\ntrain_masks = np.array([get_mask(train_df, idx) for idx in TRAIN_IDS])\n\nprint('train shape:', train_imgs.shape)\nprint('mask shape:', train_masks.shape)\n\nplt.figure(figsize=(10, 10))\nplt.imshow(train_imgs[0], cmap=\"binary\")\nplt.imshow(train_masks[0], cmap=\"gnuplot\", alpha=0.3)","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:30:52.639964Z","iopub.execute_input":"2021-12-07T02:30:52.640226Z","iopub.status.idle":"2021-12-07T02:31:44.464542Z","shell.execute_reply.started":"2021-12-07T02:30:52.640191Z","shell.execute_reply":"2021-12-07T02:31:44.463934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Total 606 images in 704х520 size.<br>\nLet's break these images into parts, this will increase the number of examples, and will also allow using less video memory when training the model.","metadata":{}},{"cell_type":"code","source":"def split_img(img: np.ndarray, \n              size: int = 128, \n              excess: bool = True) -> np.ndarray:\n    \"\"\"get image and split it on size\n    \n    params:\n        img:  original image\n        size: size of results\"\"\"\n    \n    h_offsets = HEIGHT // size\n    w_offsets = WIDTH // size\n    \n    if excess:\n        h_excess = HEIGHT % size\n        w_excess = WIDTH % size\n    \n        h_offsets += 1 if h_excess else 0\n        w_offsets += 1 if h_excess else 0\n    \n    arr_imgs = []\n    for i in range(h_offsets):\n        for j in range(w_offsets):\n            \n            w_start, w_end = j*size, (j+1)*size\n            \n            if j == w_offsets-1 and excess:\n                w_start += w_excess - size\n                w_end += w_excess - size\n            \n            h_start, h_end = i*size, (i+1)*size\n            \n            if i == h_offsets-1 and excess:\n                h_start += h_excess - size\n                h_end += h_excess - size\n            \n            piese = img[h_start: h_end,\n                        w_start: w_end]\n        \n            arr_imgs.append(piese)\n    \n    arr_imgs = np.array(arr_imgs)[..., None]\n    \n    return arr_imgs\n\ndef view_splitimg_imgs(pieces: np.ndarray, \n                       masks: np.ndarray = np.array([]), \n                       excess: bool = True) -> None:\n    \"\"\"Show original image from its parts in the form of a grid\n    \n    params:\n        pieces: array of images that are part of a original image\n        masks:  array of masks that are part of a original mask\n        excess: allocate space for excesses\"\"\"\n    \n    size = pieces.shape[1] # 128\n    \n    cols = WIDTH // size\n    rows = HEIGHT // size\n    \n    if excess:\n        w_excess = WIDTH % size\n        h_excess = HEIGHT % size\n    \n        cols += 1 if w_excess else 0\n        rows += 1 if h_excess else 0\n\n    fig, ax = plt.subplots(rows, cols, figsize=(12, 10))\n\n    for i in range(rows):\n        for j in range(cols):\n\n            idx = j + i*cols\n\n            ax[i, j].imshow(pieces[idx], cmap=\"binary\")\n            if len(masks) > 0:\n                ax[i, j].imshow(masks[idx], cmap=\"gnuplot\", alpha=0.3)\n            ax[i, j].axis(\"off\")\n\n    plt.subplots_adjust(wspace=0.01, hspace=0.01)","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:44.465469Z","iopub.execute_input":"2021-12-07T02:31:44.465732Z","iopub.status.idle":"2021-12-07T02:31:44.483905Z","shell.execute_reply.started":"2021-12-07T02:31:44.465676Z","shell.execute_reply":"2021-12-07T02:31:44.483248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\ntrain_imgs = np.concatenate([split_img(train_imgs[i], excess=False) for i in range(len(train_imgs))], axis=0)\ntrain_masks = np.concatenate([split_img(train_masks[i], excess=False) for i in range(len(train_masks))], axis=0)\n\nprint(train_imgs.shape, train_masks.shape)\n\nview_splitimg_imgs(train_imgs, train_masks, excess=False)","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:44.48533Z","iopub.execute_input":"2021-12-07T02:31:44.485628Z","iopub.status.idle":"2021-12-07T02:31:47.428101Z","shell.execute_reply.started":"2021-12-07T02:31:44.485592Z","shell.execute_reply":"2021-12-07T02:31:47.427516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepocess data\n\nsplit on train & test","metadata":{}},{"cell_type":"code","source":"split_by = len(train_imgs) // 10\n\ntrain_imgs, valid_imgs = train_imgs[split_by:], train_imgs[:split_by]\ntrain_masks, valid_masks = train_masks[split_by:], train_masks[:split_by]\n\nprint('train_imgs shape:', train_imgs.shape)\nprint('train_masks shape:', train_masks.shape)\n\nprint('valid_imgs shape:', valid_imgs.shape)\nprint('valid_masks shape:', valid_masks.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:47.429452Z","iopub.execute_input":"2021-12-07T02:31:47.429906Z","iopub.status.idle":"2021-12-07T02:31:47.437709Z","shell.execute_reply.started":"2021-12-07T02:31:47.429871Z","shell.execute_reply":"2021-12-07T02:31:47.436762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"arrays in datasets","metadata":{}},{"cell_type":"code","source":"%%time\n\ntrain_ds = tf.data.Dataset.from_tensor_slices((train_imgs, train_masks))\nvalid_ds = tf.data.Dataset.from_tensor_slices((valid_imgs, valid_masks))","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:47.43944Z","iopub.execute_input":"2021-12-07T02:31:47.439727Z","iopub.status.idle":"2021-12-07T02:31:52.880649Z","shell.execute_reply.started":"2021-12-07T02:31:47.439652Z","shell.execute_reply":"2021-12-07T02:31:52.879917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"preprocess datasets","metadata":{}},{"cell_type":"code","source":"BATCH_SIZE = 1\n\ndef prep_data(img: np.ndarray, \n              mask: np.ndarray) -> tuple:\n    \"\"\"normalize pixel array -> retype pixel array\n    \n    params:\n        img:  image array\n        mask: mask array\"\"\"\n    \n    img /= 255\n    \n    img = tf.cast(img, tf.float32)\n    mask = tf.cast(mask, tf.float32)\n    \n    return img, mask\n\ndef pipline(ds):\n    \"\"\"cache -> suffle -> preprocess -> split on batchs -> prefetch\n    \n    params:\n        ds: dataset to pipline\"\"\"\n    \n    ds = ds.cache()\n    ds = ds.shuffle(1000)\n    ds = ds.map(prep_data)\n    ds = ds.batch(BATCH_SIZE)\n    ds = ds.prefetch(tf.data.AUTOTUNE)\n    \n    return ds\n\ntrain_ds = pipline(train_ds)\nvalid_ds = valid_ds.map(prep_data).batch(BATCH_SIZE)","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:52.883837Z","iopub.execute_input":"2021-12-07T02:31:52.88405Z","iopub.status.idle":"2021-12-07T02:31:52.985805Z","shell.execute_reply.started":"2021-12-07T02:31:52.884024Z","shell.execute_reply":"2021-12-07T02:31:52.985063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class UNet(tf.keras.Model):\n    \n    def __init__(self):\n        super().__init__()\n        \n        # encoder\n        self.conv_enc64_1 = layers.Conv2D(64, (3, 3), padding='same', activation='relu')\n        self.conv_enc64_2 = layers.Conv2D(64, (3, 3), padding='same', activation='relu')\n        \n        self.conv_enc128_1 = layers.Conv2D(128, (3, 3), padding='same', activation='relu')\n        self.conv_enc128_2 = layers.Conv2D(128, (3, 3), padding='same', activation='relu')\n        \n        self.conv_enc256_1 = layers.Conv2D(256, (3, 3), padding='same', activation='relu')\n        self.conv_enc256_2 = layers.Conv2D(256, (3, 3), padding='same', activation='relu')\n        \n        self.conv_enc512_1 = layers.Conv2D(512, (3, 3), padding='same', activation='relu')\n        self.conv_enc512_2 = layers.Conv2D(512, (3, 3), padding='same', activation='relu')\n        \n        self.maxpool = layers.MaxPooling2D((2, 2), (2, 2), padding='same')\n        \n        # decoder\n        self.conv_dec1024_1 = layers.Conv2D(1024, (3, 3), padding='same', activation='relu')\n        self.conv_dec1024_2 = layers.Conv2D(1024, (3, 3), padding='same', activation='relu')\n        self.conv_transp_512 = layers.Conv2DTranspose(512, (3, 3), strides=(2, 2), padding='same', activation='relu')\n        \n        self.conv_dec512_1 = layers.Conv2D(512, (3, 3), padding='same', activation='relu')\n        self.conv_dec512_2 = layers.Conv2D(512, (3, 3), padding='same', activation='relu')\n        self.conv_transp_256 = layers.Conv2DTranspose(256, (3, 3), strides=(2, 2), padding='same', activation='relu')\n        \n        self.conv_dec256_1 = layers.Conv2D(256, (3, 3), padding='same', activation='relu')\n        self.conv_dec256_2 = layers.Conv2D(256, (3, 3), padding='same', activation='relu')\n        self.conv_transp_128 = layers.Conv2DTranspose(128, (3, 3), strides=(2, 2), padding='same', activation='relu')\n        \n        self.conv_dec128_1 = layers.Conv2D(128, (3, 3), padding='same', activation='relu')\n        self.conv_dec128_2 = layers.Conv2D(128, (3, 3), padding='same', activation='relu')\n        self.conv_transp_64 = layers.Conv2DTranspose(64, (3, 3), strides=(2, 2), padding='same', activation='relu')\n        \n        self.conv_dec64_1 = layers.Conv2D(64, (3, 3), padding='same', activation='relu')\n        self.conv_dec64_2 = layers.Conv2D(64, (3, 3), padding='same', activation='relu')\n        \n        self.conv_final = layers.Conv2D(1, (3, 3), padding='same', activation='sigmoid')\n        \n    def call(self, x):\n        \n        # encoder\n        out = self.conv_enc64_1(x)\n        out1 = self.conv_enc64_2(out)\n        out = self.maxpool(out1)\n        \n        out = self.conv_enc128_1(out)\n        out2 = self.conv_enc128_2(out)\n        out = self.maxpool(out2)\n        \n        out = self.conv_enc256_1(out)\n        out3 = self.conv_enc256_2(out)\n        out = self.maxpool(out3)\n        \n        out = self.conv_enc512_1(out)\n        out4 = self.conv_enc512_2(out)\n        out = self.maxpool(out4)\n        \n        # decoder\n        out = self.conv_dec1024_1(out)\n        out = self.conv_dec1024_2(out)\n        out = self.conv_transp_512(out)\n        out = tf.concat([out4, out], axis=3)\n        \n        out = self.conv_dec512_1(out)\n        out = self.conv_dec512_2(out)\n        out = self.conv_transp_256(out)\n        out = tf.concat([out3, out], axis=3)\n        \n        out = self.conv_dec256_1(out)\n        out = self.conv_dec256_2(out)\n        out = self.conv_transp_128(out)\n        out = tf.concat([out2, out], axis=3)\n        \n        out = self.conv_dec128_1(out)\n        out = self.conv_dec128_2(out)\n        out = self.conv_transp_64(out)\n        out = tf.concat([out1, out], axis=3)\n        \n        out = self.conv_dec64_1(out)\n        out = self.conv_dec64_2(out)\n        \n        out = self.conv_final(out)\n        \n        return out","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:52.987229Z","iopub.execute_input":"2021-12-07T02:31:52.987496Z","iopub.status.idle":"2021-12-07T02:31:53.011811Z","shell.execute_reply.started":"2021-12-07T02:31:52.987452Z","shell.execute_reply":"2021-12-07T02:31:53.010727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## init training objects","metadata":{}},{"cell_type":"code","source":"model = UNet()\n\noptimizer = tf.keras.optimizers.Adam()\naccuracy = tf.keras.metrics.SparseCategoricalAccuracy()\n\nloss_obj = tf.keras.losses.BinaryCrossentropy()\nloss = tf.keras.metrics.Mean()","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:53.013324Z","iopub.execute_input":"2021-12-07T02:31:53.01367Z","iopub.status.idle":"2021-12-07T02:31:53.082628Z","shell.execute_reply.started":"2021-12-07T02:31:53.013633Z","shell.execute_reply":"2021-12-07T02:31:53.081986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## checkpoint","metadata":{}},{"cell_type":"code","source":"checkpoint_path = \"./checkpoints/trainUnet\"\n\nckpt = tf.train.Checkpoint(\n    model=model,\n    optimizer=optimizer\n)\nckpt_manager = tf.train.CheckpointManager(ckpt, checkpoint_path, max_to_keep=1)\n\nif ckpt_manager.latest_checkpoint:\n    ckpt.restore(ckpt_manager.latest_checkpoint)\n    print ('Latest checkpoint restored!')","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:53.083859Z","iopub.execute_input":"2021-12-07T02:31:53.084118Z","iopub.status.idle":"2021-12-07T02:31:53.090779Z","shell.execute_reply.started":"2021-12-07T02:31:53.084083Z","shell.execute_reply":"2021-12-07T02:31:53.089923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## variables for training","metadata":{}},{"cell_type":"code","source":"EPOCHS = 10\n\ntrain_loss, train_accuracy = [], []\nvalid_loss, valid_accuracy = [], []\n\nvalid_batch_img, valid_batch_mask = next(valid_ds.as_numpy_iterator())","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:53.092437Z","iopub.execute_input":"2021-12-07T02:31:53.092761Z","iopub.status.idle":"2021-12-07T02:31:53.277167Z","shell.execute_reply.started":"2021-12-07T02:31:53.092725Z","shell.execute_reply":"2021-12-07T02:31:53.276371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## training","metadata":{}},{"cell_type":"code","source":"def plot_process(train_values, valid_values, figsize=(16, 4)):\n    \"\"\"plot loss or accuracy\n    \n    params:\n        train_values: array for train\n        valid_values: array for valid\n        figsize:      size of plots\"\"\"\n    \n    plt.figure(figsize=figsize)\n    plt.plot(train_values, label='train')\n    plt.plot(valid_values, label='valid')\n    plt.legend()\n    plt.show()\n    \ndef view_masks(img, mask, pred_mask, figsize=(14, 8)):\n    \"\"\"view result of training\n    \n    params:\n        img:       array of original image\n        mask:      array of original mask\n        pred_mask: array of predicted mask\n        figsize:   size of image\"\"\"\n    \n    fig, ax = plt.subplots(1, 2, figsize=figsize)\n\n    ax[0].set_title('true')\n    ax[0].imshow(img, cmap='binary')\n    ax[0].imshow(mask, cmap='gnuplot', alpha=0.3)\n\n    ax[1].set_title('pred')\n    ax[1].imshow(img, cmap='binary')\n    ax[1].imshow(pred_mask, cmap='gnuplot', alpha=0.3)\n    \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:53.278681Z","iopub.execute_input":"2021-12-07T02:31:53.278937Z","iopub.status.idle":"2021-12-07T02:31:53.286333Z","shell.execute_reply.started":"2021-12-07T02:31:53.278901Z","shell.execute_reply":"2021-12-07T02:31:53.285605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nfor epoch in range(EPOCHS):\n    print(epoch)\n    \n    for i, (train_batch_img, train_batch_mask) in enumerate(train_ds):\n\n        with tf.GradientTape() as tape:\n            train_batch_mask_pred = model(train_batch_img)\n            train_loss_value = loss_obj(train_batch_mask, train_batch_mask_pred)\n\n        gradients = tape.gradient(train_loss_value, model.trainable_variables)\n        optimizer.apply_gradients(zip(gradients, model.trainable_variables))\n\n        loss(train_loss_value)\n        accuracy(train_batch_mask, train_batch_mask_pred)\n        \n        if i % 100 == 0:\n            valid_batch_mask_pred = model(valid_batch_img)\n\n            valid_loss_value = loss_obj(valid_batch_mask, valid_batch_mask_pred)\n\n            valid_accuracy_value = accuracy(valid_batch_mask, valid_batch_mask_pred)\n            train_accuracy_value = accuracy(train_batch_mask, train_batch_mask_pred)\n\n            print(f'{i}\\ttrain loss: {train_loss_value:.4f} | train accuracy: {train_accuracy_value:.4f} |',\n                  f'valid loss: {valid_loss_value:.4f} | valid accuracy: {valid_accuracy_value:.4f}')\n\n            train_loss.append(train_loss_value)\n            valid_loss.append(valid_loss_value)\n\n            train_accuracy.append(train_accuracy_value)\n            valid_accuracy.append(valid_accuracy_value)\n            \n        if i % 1000 == 0:\n            display.clear_output(wait=False)\n            \n            plot_process(train_accuracy, valid_accuracy, figsize=(16, 3))\n            plot_process(train_loss, valid_loss, figsize=(16, 3))\n            \n            view_masks(\n                img=valid_batch_img[0, ..., 0],\n                mask=valid_batch_mask[0, ...],\n                pred_mask=(valid_batch_mask_pred[0, ... ,0] > 0.5).numpy().astype(np.float32), \n                figsize=(12, 8)\n            )\n            \n            ckpt_manager.save()\n            print(\"checkpoint was saved\")","metadata":{"execution":{"iopub.status.busy":"2021-12-07T02:31:53.287705Z","iopub.execute_input":"2021-12-07T02:31:53.288088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test images\n\n## Get test images","metadata":{}},{"cell_type":"code","source":"def prediction_test(img: np.ndarray, \n                    batch: int = 4) -> np.ndarray:\n    \n    \"\"\"predicts masks for image pieces\n    \n    params:\n        img:   array of image pieces\n        batch: number of images in batch\"\"\"\n    \n    batch_excess = len(img) % batch\n    \n    batch_count = len(img) // batch\n    batch_count += 1 if batch_excess else 0\n    \n    test_mask_preds = []\n    \n    for i in range(batch_count):\n        \n        test_batch_mask_pred = model(img[i*batch: (i+1)*batch] / 255)\n        test_batch_mask_pred = test_batch_mask_pred.numpy() > 0.5\n        test_batch_mask_pred = test_batch_mask_pred.astype(np.uint)\n        \n        for mask in test_batch_mask_pred:\n            test_mask_preds.append(mask)\n            \n    test_mask_preds = np.array(test_mask_preds)\n    \n    return test_mask_preds","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"View test images","metadata":{}},{"cell_type":"code","source":"test_imgs = os.listdir(TEST_DIR)\n\ntest_img0 = np.array([get_image(TEST_DIR + test_imgs[0])])\ntest_img1 = np.array([get_image(TEST_DIR + test_imgs[1])])\ntest_img2 = np.array([get_image(TEST_DIR + test_imgs[2])])\n\nprint('test_imgs:', test_img0.shape)\n\nfig, ax = plt.subplots(1, 3, figsize=(18, 16))\n\ndef add_imshow(img: np.ndarray, idx: int, name: str) -> None:\n    ax[idx].set_title(name)\n    ax[idx].imshow(img, cmap=\"binary\")\n    ax[idx].axis(\"off\")\n    \nadd_imshow(test_img0[0], 0, test_imgs[0])\nadd_imshow(test_img1[0], 1, test_imgs[1])\nadd_imshow(test_img2[0], 2, test_imgs[2])\n\nplt.subplots_adjust(wspace=0.05, hspace=0.01)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preprocess test\n\nSplit original image on pieces","metadata":{}},{"cell_type":"code","source":"test_img0 = split_img(test_img0[0], excess=True)\ntest_img1 = split_img(test_img1[0], excess=True)\ntest_img2 = split_img(test_img2[0], excess=True)\n\nprint(test_img0.shape)\n\nview_splitimg_imgs(test_img0, excess=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prediction test mask","metadata":{}},{"cell_type":"code","source":"test_mask_preds0 = prediction_test(test_img0)\n\nprint(test_mask_preds0.shape)\n\nview_splitimg_imgs(test_img0, test_mask_preds0)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_mask_preds1 = prediction_test(test_img1)\n\nprint(test_mask_preds1.shape)\n\nview_splitimg_imgs(test_img1, test_mask_preds1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_mask_preds2 = prediction_test(test_img2)\n\nprint(test_mask_preds2.shape)\n\nview_splitimg_imgs(test_img2, test_mask_preds2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Concatenate results","metadata":{}},{"cell_type":"code","source":"def concat_img(pieces: np.ndarray):\n    \"\"\"Concatinate parts of image into original image\n    \n    params:\n        pieces: array of images that are part of a original image\"\"\"\n    \n    size = pieces.shape[1] # 128\n    \n    w_excess = WIDTH % size\n    h_excess = HEIGHT % size\n    \n    cols = WIDTH // size\n    rows = HEIGHT // size\n    \n    cols += 1 if w_excess else 0\n    rows += 1 if h_excess else 0\n    \n    result = []\n    for i in range(rows):\n    \n        row = pieces[i*cols:(i+1)*cols]\n\n        if w_excess:\n            half1 = np.concatenate(row[:cols-1], axis=1)\n            half2 = row[cols-1, :, size-w_excess:]\n            row = np.concatenate([half1, half2], axis=1)\n        \n        if h_excess and i == rows-1:\n            row = row[size-h_excess:]\n        \n        result.append(row)\n        \n    result = np.concatenate(result)\n    \n    return result","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_img0 = concat_img(test_img0[..., 0])\ntest_mask_preds0 = concat_img(test_mask_preds0[..., 0])\n\nprint(test_img0.shape, test_mask_preds0.shape)\n\nplt.figure(figsize=(13, 11))\nplt.imshow(test_img0, cmap=\"gray\")\nplt.imshow(test_mask_preds0, cmap=\"gnuplot\", alpha=0.3)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_img1 = concat_img(test_img1[..., 0])\ntest_mask_preds1 = concat_img(test_mask_preds1[..., 0])\n\nprint(test_img1.shape, test_mask_preds1.shape)\n\nplt.figure(figsize=(13, 11))\nplt.imshow(test_img1, cmap=\"gray\")\nplt.imshow(test_mask_preds1, cmap=\"gnuplot\", alpha=0.3)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_img2 = concat_img(test_img2[..., 0])\ntest_mask_preds2 = concat_img(test_mask_preds2[..., 0])\n\nprint(test_img2.shape, test_mask_preds2.shape)\n\nplt.figure(figsize=(13, 11))\nplt.imshow(test_img2, cmap=\"gray\")\nplt.imshow(test_mask_preds2, cmap=\"gnuplot\", alpha=0.3)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Mask encoding","metadata":{}},{"cell_type":"code","source":"def recoding_mask(mask: np.ndarray) -> np.ndarray:\n    \"\"\"params:\n        mask: original mask\"\"\"\n    \n    mask_idx = mask.reshape(1, -1)[0]\n    mask_idx = np.nonzero(mask_idx)[0]\n    \n    result = []\n    \n    idx = 0\n    while idx < len(mask_idx):\n\n        num = mask_idx[idx]\n        lenght = 1\n\n        next_num = num + 1\n        idx += 1\n\n        while idx < len(mask_idx) and next_num == mask_idx[idx]:\n            lenght += 1\n\n            next_num += 1\n            idx += 1\n\n        result.append(num)\n        result.append(lenght)\n        \n    result = np.array(result)\n    \n    return result","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_mask_preds0 = recoding_mask(test_mask_preds0)\ntest_mask_preds1 = recoding_mask(test_mask_preds1)\ntest_mask_preds2 = recoding_mask(test_mask_preds2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submition","metadata":{}},{"cell_type":"code","source":"submition = pd.DataFrame(columns=[\"id\", \"predicted\"])\nsubmition.loc[0] = [test_imgs[0][:-4], \" \".join(test_mask_preds0.astype(str))]\nsubmition.loc[1] = [test_imgs[1][:-4], \" \".join(test_mask_preds1.astype(str))]\nsubmition.loc[2] = [test_imgs[2][:-4], \" \".join(test_mask_preds2.astype(str))]\nsubmition","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submition.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}