{"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":"code","source":"!pip install ../input/keras-applications/Keras_Applications-1.0.8/ -f ./ --no-index\n!pip install ../input/image-classifiers/image_classifiers-1.0.0/ -f ./ --no-index\n!pip install ../input/efficientnet-1-0-0/efficientnet-1.0.0/ -f ./ --no-index\n!pip install ../input/segmentation-models/segmentation_models-1.0.1/ -f ./ --no-index","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"%env SM_FRAMEWORK=tf.keras","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore')\nimport os\nimport gc\nimport cv2\nimport sys\nimport json\nimport time\nimport pickle\nimport shutil\nimport numba\nimport numpy as np\nimport pandas as pd \nimport tifffile as tiff\nimport rasterio\nfrom rasterio.windows import Window\nimport tensorflow as tf\nimport tensorflow_addons as tfa\nimport matplotlib.pyplot as plt\nimport tensorflow.keras.backend as K\nfrom tensorflow.keras import Model, Sequential\nfrom tensorflow.keras.models import load_model\nfrom tensorflow.keras.utils import Sequence\nfrom tensorflow.keras.losses import binary_crossentropy\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.optimizers import Adam, SGD\nfrom tensorflow.keras.callbacks import *\nimport segmentation_models as sm\nfrom segmentation_models import Unet, FPN\nfrom segmentation_models.losses import bce_jaccard_loss\nfrom tqdm import tqdm\nprint('tensorflow version:', tf.__version__)\nos.environ['CUDA_VISIBLE_DEVICES'] = '0'\ngpu_devices = tf.config.experimental.list_physical_devices('GPU')\nif gpu_devices:\n    for gpu_device in gpu_devices:\n        print('device available:', gpu_device)\npd.set_option('display.max_columns', None)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST = True\nKAGGLE = True\nVER = 'v24'\nif KAGGLE:\n    DATA_PATH = '../input/hubmap-kidney-segmentation'\n    MDLS_PATH = f'../input/kidney-models-{VER}'\nelse:\n    DATA_PATH = './data'\n    MDLS_PATH = f'./models_{VER}'\nTHRESHOLD = .4\nVOTERS = 1\nTTAS = [0]\nFOLDS = [0, 1, 2, 3]\nEXPAND = 4\nMIN_OVERLAP = 256\nIDNT = rasterio.Affine(1, 0, 0, 0, 1, 0)\nSTRATEGY = tf.distribute.get_strategy() \nSUB_PATH = f'{DATA_PATH}/test' if TEST else f'{DATA_PATH}/train'\nTARGET_IMG = 'afa5e8098.tiff'\nY_SHFT = -40\nX_SHFT = -24\n\nstart_time = time.time()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open(f'{MDLS_PATH}/params.json') as file:\n    params = json.load(file)\nif 'umodel' not in params.keys(): params['umodel'] = 'unet'\nprint('loaded params:', params)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def enc2mask(encs, shape):\n    img = np.zeros(shape[0] * shape[1], dtype=np.uint8)\n    for m, enc in enumerate(encs):\n        if isinstance(enc, np.float) and np.isnan(enc): continue\n        s = enc.split()\n        for i in range(len(s) // 2):\n            start = int(s[2 * i]) - 1\n            length = int(s[2 * i + 1])\n            img[start : start + length] = 1 + m\n    return img.reshape(shape).T\n\ndef rle_encode_less_memory(img):\n    pixels = img.T.flatten()\n    pixels[0] = 0\n    pixels[-1] = 0\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 2\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef global_shift_mask(maskpred1, y_shift, x_shift):\n    \"\"\"\n    applies a global shift to a mask by \n    padding one side and cropping from the other\n    \"\"\"\n    if y_shift < 0 and x_shift >=0:\n        maskpred2 = np.pad(maskpred1, \n                           [(0,abs(y_shift)), (abs(x_shift), 0)], \n                           mode='constant', constant_values=0)\n        maskpred3 = maskpred2[abs(y_shift):, :maskpred1.shape[1]]\n    elif y_shift >=0 and x_shift <0:\n        maskpred2 = np.pad(maskpred1, \n                           [(abs(y_shift),0), (0, abs(x_shift))], \n                           mode='constant', constant_values=0)\n        maskpred3 = maskpred2[:maskpred1.shape[0], abs(x_shift):]\n    elif y_shift >=0 and x_shift >=0:\n        maskpred2 = np.pad(maskpred1,\n                           [(abs(y_shift),0), (abs(x_shift), 0)], \n                           mode='constant', constant_values=0)\n        maskpred3 = maskpred2[:maskpred1.shape[0], :maskpred1.shape[1]]\n    elif y_shift < 0 and x_shift < 0:\n        maskpred2 = np.pad(maskpred1, \n                           [(0, abs(y_shift)), (0, abs(x_shift))], \n                           mode='constant', constant_values=0)\n        maskpred3 = maskpred2[abs(y_shift):, abs(x_shift):]\n    return maskpred3","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def 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, smooth=1):\n    return (1 - dice_coef(y_true, y_pred, smooth))\n\ndef bce_dice_loss(y_true, y_pred):\n    return params['bce_weight'] * binary_crossentropy(y_true, y_pred) + \\\n        (1 - params['bce_weight']) * dice_loss(y_true, y_pred)\n\ndef get_model(backbone, input_shape, loss_type='bce_dice', \n              umodel='unet', classes=1, lr=.001):\n    if backbone == 'efficientnetb0':\n        weights = f'{MDLS_PATH}/efficientnet-b0_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5'\n    elif backbone == 'efficientnetb1':\n        weights = f'{MDLS_PATH}/efficientnet-b1_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5'\n    elif backbone == 'efficientnetb2':\n        weights = f'{MDLS_PATH}/efficientnet-b2_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5'\n    elif backbone == 'efficientnetb3':\n        weights = f'{MDLS_PATH}/efficientnet-b3_weights_tf_dim_ordering_tf_kernels_autoaugment_notop.h5'\n    elif backbone == 'resnet34':\n        weights = f'{MDLS_PATH}/resnet34_imagenet_1000_no_top.h5'\n    else:\n        raise AttributeError('mode parameter error')\n    with STRATEGY.scope():\n        if loss_type == 'bce_dice': \n            loss = bce_dice_loss\n        elif loss_type == 'bce_jaccard_loss':\n            loss = bce_jaccard_loss\n        else:\n            raise AttributeError('loss mode parameter error')\n        if umodel == 'unet':\n            model = Unet(backbone_name=backbone, encoder_weights=weights,\n                         input_shape=input_shape,\n                         classes=classes, activation='sigmoid')\n        elif umodel == 'fpn':\n            model = FPN(backbone_name=backbone, encoder_weights=weights,\n                        input_shape=input_shape,\n                        classes=classes, activation='sigmoid')\n        else:\n            raise AttributeError('umodel mode parameter error')\n        model.compile(\n            optimizer=tfa.optimizers.Lookahead(\n                tf.keras.optimizers.Adam(learning_rate=lr)\n            ),\n            loss=loss, \n            metrics=[dice_coef]\n        )\n    return model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_grid(shape, window=256, min_overlap=32):\n    x, y = shape\n    nx = x // (window - min_overlap) + 1\n    x1 = np.linspace(0, x, num=nx, endpoint=False, dtype=np.int64)\n    x1[-1] = x - window\n    x2 = (x1 + window).clip(0, x)\n    ny = y // (window - min_overlap) + 1\n    y1 = np.linspace(0, y, num=ny, endpoint=False, dtype=np.int64)\n    y1[-1] = y - window\n    y2 = (y1 + window).clip(0, y)\n    slices = np.zeros((nx, ny, 4), dtype=np.int64) \n    for i in range(nx):\n        for j in range(ny):\n            slices[i, j] = x1[i], x2[i], y1[j], y2[j]    \n    return slices.reshape(nx * ny, 4)\n\ndef flip(img, axis=0):\n    if axis == 1:\n        return img[::-1, :, ]\n    elif axis == 2:\n        return img[:, ::-1, ]\n    elif axis == 3:\n        return img[::-1, ::-1, ]\n    else:\n        return img","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_files = [x for x in os.listdir(SUB_PATH) if '.tiff' in x]\nprint('images idxs:', img_files)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subm = {}\nfor i_img, img_file in enumerate(img_files):\n    print('-' * 20, img_file, '-' * 20)\n    img_data = rasterio.open(os.path.join(SUB_PATH, img_file), transform=IDNT)\n    print('img shape:', img_data.shape)\n    if img_data.count != 3:\n        print('img file with subdatasets as channels')\n        layers = [rasterio.open(subd) for subd in img_data.subdatasets]\n    img_preds = np.zeros(img_data.shape, dtype=np.uint8)\n    tile_size = int(params['img_size'] * EXPAND)\n    tile_resized = int(tile_size * params['resize'])\n    slices = make_grid(\n        img_data.shape, \n        window=tile_resized, \n        min_overlap=MIN_OVERLAP\n    )\n    models = []\n    folds = FOLDS\n    for n_fold in folds:\n        checkpoint_path = f'{MDLS_PATH}/model_{n_fold}.hdf5'\n        model = get_model(\n            params['backbone'], \n            input_shape=(tile_size, tile_size, 3),\n            loss_type=params['loss'],\n            umodel=params['umodel']\n        )\n        model.load_weights(checkpoint_path)\n        models.append(model)\n        print('model loaded:', checkpoint_path)\n    for (x1, x2, y1, y2) in tqdm(slices, desc=f'{img_file}'):\n        if img_data.count == 3: # normal\n            img = img_data.read(\n                [1, 2, 3], \n                window=Window.from_slices((x1, x2), (y1, y2))\n            )\n            img = np.moveaxis(img, 0, -1)\n        else: # with subdatasets/layers\n            img = np.zeros((tile_resized, tile_resized, 3), dtype=np.uint8)\n            for fl in range(3):\n                img[:, :, fl] = layers[fl].read(\n                    window=Window.from_slices((x1, x2), (y1, y2))\n                )\n        img = cv2.resize(img, (tile_size, tile_size))\n        img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)\n        pred = np.zeros((tile_size, tile_size), dtype=np.float32)\n        for tta_mode in TTAS:\n            img_aug = flip(img, axis=tta_mode)\n            img_aug = np.expand_dims(img_aug, 0)\n            img_aug = img_aug.astype(np.float32) / 255\n            pred_aug = np.zeros((tile_size, tile_size), dtype=np.float32)\n            for model in models:\n                pred_aug += np.squeeze(model.predict(img_aug)) / len(models)\n            pred += flip(pred_aug, axis=tta_mode) / len(TTAS)\n        pred = cv2.resize(pred, (tile_resized, tile_resized))\n        img_preds[x1:x2, y1:y2] = img_preds[x1:x2, y1:y2] + \\\n            (pred > THRESHOLD).astype(np.uint8)\n    del model, models, img, pred, img_aug, pred_aug; gc.collect()\n    print('img max:', np.max(img_preds), '| voters:', VOTERS)\n    if img_file == TARGET_IMG:\n        print('global shift')\n        img_preds = (img_preds >= VOTERS).astype(np.uint8)\n        img_preds = global_shift_mask(img_preds, Y_SHFT, X_SHFT)\n    else:\n        img_preds = (img_preds >= VOTERS).astype(np.uint8)\n    rle_pred = rle_encode_less_memory(img_preds)\n    subm[i_img] = {'id':img_file.replace('.tiff', ''), 'predicted': rle_pred}\n    del img_preds, img_data, rle_pred; gc.collect()\n\nelapsed_time = time.time() - start_time\nprint(f'time elapsed: {elapsed_time // 60:.0f} min {elapsed_time % 60:.0f} sec')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub = pd.DataFrame(subm).T\ndf_sub","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Create Submission file","metadata":{}},{"cell_type":"code","source":"df_sub.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}