{"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":"# 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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-06T04:28:16.571062Z","iopub.execute_input":"2023-06-06T04:28:16.571488Z","iopub.status.idle":"2023-06-06T04:28:16.627131Z","shell.execute_reply.started":"2023-06-06T04:28:16.571453Z","shell.execute_reply":"2023-06-06T04:28:16.626077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#install pytorch segmentation models offline\n#https://www.kaggle.com/code/raghaw/offline-install-segmentation-model-pytorch/notebook\n!pip install --no-index --find-links=\"/kaggle/input/segmentation-models-pytorch/\" segmentation-models-pytorch","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:16.62885Z","iopub.execute_input":"2023-06-06T04:28:16.62975Z","iopub.status.idle":"2023-06-06T04:28:39.805683Z","shell.execute_reply.started":"2023-06-06T04:28:16.62971Z","shell.execute_reply":"2023-06-06T04:28:39.803928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import segmentation_models_pytorch as smp","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:39.808465Z","iopub.execute_input":"2023-06-06T04:28:39.809036Z","iopub.status.idle":"2023-06-06T04:28:48.864977Z","shell.execute_reply.started":"2023-06-06T04:28:39.808981Z","shell.execute_reply":"2023-06-06T04:28:48.863617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport math\nimport PIL.Image as Image\nimport torch\nfrom torch.utils.data import DataLoader\nimport torch.nn as nn\nfrom torch.optim import AdamW\nfrom torch.utils.data import DataLoader, Dataset, random_split\nimport torchvision.transforms as T\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nimport torch.backends.cudnn as cudnn\nimport torchvision\nimport time\nimport copy\nimport gc\nfrom tqdm.notebook import tqdm\nfrom tqdm import tqdm, trange\nfrom tqdm.auto import tqdm\n\ncudnn.benchmark = True\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nprint(torch.__version__)","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:48.868435Z","iopub.execute_input":"2023-06-06T04:28:48.868965Z","iopub.status.idle":"2023-06-06T04:28:51.163373Z","shell.execute_reply.started":"2023-06-06T04:28:48.868929Z","shell.execute_reply":"2023-06-06T04:28:51.161974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#config\nSUBMIT = True #if set to False, evaluate labels accuracy\nTILE_SIZE = 224\nSIZE = TILE_SIZE\nSTRIDE = TILE_SIZE// 2\n\n#specify scan images to load start / end (algorithm will find best positions automatically)\nSTART_SCAN = 28\nEND_SCAN = 36\nINPUT_CHANNELS = END_SCAN - START_SCAN + 1\n\nLR = 0.0001\nLOSS_FUNCTION = torch.nn.BCEWithLogitsLoss()\nTHRESHOLD = 0.45","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.164894Z","iopub.execute_input":"2023-06-06T04:28:51.165387Z","iopub.status.idle":"2023-06-06T04:28:51.172847Z","shell.execute_reply.started":"2023-06-06T04:28:51.16534Z","shell.execute_reply":"2023-06-06T04:28:51.171408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_image(path):\n    images = []\n\n    slideids = range(START_SCAN, END_SCAN + 1)\n    \n    for i in slideids:\n        #read images specified by start_scan and end_scan numbers\n        image = cv2.imread(path + f\"/surface_volume/{i:02}.tif\", 0)\n        \n        pad0 = (TILE_SIZE- image.shape[0] % TILE_SIZE)\n        pad1 = (TILE_SIZE- image.shape[1] % TILE_SIZE)\n        \n        #increase borders to match tile size\n        image = np.pad(image, [(0, pad0), (0, pad1)], constant_values=0)\n        \n        images.append(image)\n        del image\n        gc.collect()\n    #stack images (2D arrays) on axis 2\n    images = np.stack(images, axis=2)\n    \n    return images\n    ","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.175111Z","iopub.execute_input":"2023-06-06T04:28:51.176235Z","iopub.status.idle":"2023-06-06T04:28:51.20355Z","shell.execute_reply.started":"2023-06-06T04:28:51.176189Z","shell.execute_reply":"2023-06-06T04:28:51.20223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self, images, transform = None):\n        self.images = images\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, idx):\n        image = self.images[idx]\n        if self.transform:\n            data = self.transform(image = image)\n            image = data['image']\n\n        return image","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.205304Z","iopub.execute_input":"2023-06-06T04:28:51.205798Z","iopub.status.idle":"2023-06-06T04:28:51.223147Z","shell.execute_reply.started":"2023-06-06T04:28:51.205759Z","shell.execute_reply":"2023-06-06T04:28:51.221895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_dataset(paths):\n    \n    images_list = []\n    xyxys = []\n    \n    for path in paths:\n        imageset = read_image(path)\n        print(\"Input images - amount:\" + str(imageset.shape[2]) + \" height: \" + str(imageset.shape[0]) + \" width: \" + str(imageset.shape[1]))\n\n        #split images into multiple smaller images (TILE_SIZE)\n        x1_list = list(range(0, imageset.shape[1] - TILE_SIZE+ 1, TILE_SIZE))\n        y1_list = list(range(0, imageset.shape[0] - TILE_SIZE+ 1, TILE_SIZE))\n\n        for y1 in tqdm(y1_list,desc=\"Building dataset \"):\n            for x1 in x1_list:\n                y2 = y1 + TILE_SIZE\n                x2 = x1 + TILE_SIZE\n                images_list.append(imageset[y1:y2, x1:x2,:])\n                xyxys.append((x1, y1, x2, y2))                 \n                \n    xyxys = np.stack(xyxys)\n    image_dataset = CustomDataset(images = images_list,transform=getTransforms())\n    print(\"Dataset includes \" + str(len(images_list)) + \" - \" + str(TILE_SIZE) + \"x\"  + str(TILE_SIZE) + \" images\")\n\n    return image_dataset, xyxys","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.22485Z","iopub.execute_input":"2023-06-06T04:28:51.22527Z","iopub.status.idle":"2023-06-06T04:28:51.24146Z","shell.execute_reply.started":"2023-06-06T04:28:51.225236Z","shell.execute_reply":"2023-06-06T04:28:51.240419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#trained different pretrained models and selected different architectures to build an average prediction\n#this function is used to create specified models and load the stored weights\ndef createModel(modelnr):\n    if modelnr == 1: #Unet++ with better augmentation\n        model = smp.UnetPlusPlus(\n            encoder_name='resnext50_32x4d', \n            encoder_weights=None, \n            classes=1, \n            in_channels=INPUT_CHANNELS,\n            activation=None)\n        optimizer = optim.Adam(model.parameters(), lr=LR) \n        model = model.to(device)\n        optimizer_ft = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n        # Decay LR by a factor of 0.1 every 7 EPOCHS\n        exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)\n        model.load_state_dict(torch.load(\"/kaggle/input/trained-models/best-unetpp-resnext50_32x4d.pth\",map_location=torch.device(device)))\n        \n    elif modelnr == 2: #stride 3 Unet\n        model = smp.Unet(\n            encoder_name='resnext50_32x4d', \n            encoder_weights=None, \n            classes=1, \n            in_channels=INPUT_CHANNELS,\n            activation=None)\n        optimizer = optim.Adam(model.parameters(), lr=LR) \n        model = model.to(device)\n        optimizer_ft = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n        # Decay LR by a factor of 0.1 every 7 EPOCHS\n        exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)\n        model.load_state_dict(torch.load(\"/kaggle/input/trained-models/best-unet-resnext50_32x4d.pth\",map_location=torch.device(device)))\n        \n    elif modelnr == 3: #stride 3 Linknet\n        model = smp.Linknet(\n            encoder_name='resnet34', \n            encoder_weights=None, \n            classes=1, \n            in_channels=INPUT_CHANNELS,\n            activation=None)\n        optimizer = optim.Adam(model.parameters(), lr=LR) \n        model = model.to(device)\n        optimizer_ft = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n        # Decay LR by a factor of 0.1 every 7 EPOCHS\n        exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)\n        model.load_state_dict(torch.load(\"/kaggle/input/trained-models/best-linknet-resnet34.pth\",map_location=torch.device(device)))\n        \n    elif modelnr == 4: #stride 3 FPN\n        model = smp.FPN(\n            encoder_name='resnet34', \n            encoder_weights=None, \n            classes=1, \n            in_channels=INPUT_CHANNELS,\n            activation=None)\n        optimizer = optim.Adam(model.parameters(), lr=LR) \n        model = model.to(device)\n        optimizer_ft = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n        # Decay LR by a factor of 0.1 every 7 EPOCHS\n        exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)\n        model.load_state_dict(torch.load(\"/kaggle/input/trained-models/best-fpn-resnet34.pth\",map_location=torch.device(device)))\n    \n    return model ,optimizer","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.243221Z","iopub.execute_input":"2023-06-06T04:28:51.243955Z","iopub.status.idle":"2023-06-06T04:28:51.268454Z","shell.execute_reply.started":"2023-06-06T04:28:51.243918Z","shell.execute_reply":"2023-06-06T04:28:51.267093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def getTransforms():\n    #to apply normalization\n    augList = [A.Normalize(mean= [0] * INPUT_CHANNELS,std= [1] * INPUT_CHANNELS),ToTensorV2(transpose_mask=True),]\n    aug = A.Compose(augList)\n    return aug","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.273567Z","iopub.execute_input":"2023-06-06T04:28:51.273991Z","iopub.status.idle":"2023-06-06T04:28:51.288394Z","shell.execute_reply.started":"2023-06-06T04:28:51.273955Z","shell.execute_reply":"2023-06-06T04:28:51.287224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predictTest(model,x):\n    yMask = []\n    #set model to evaluation mode\n    model.eval()\n\n    #turn off gradient tracking\n    with torch.no_grad():\n        for i in tqdm(range(len(x)), desc = \"Predict \" + str(model.name)):\n\n            xPart = x[i]\n            xPart = xPart.unsqueeze(0)\n            yPred = model(xPart)\n            \n            predMask = yPred.squeeze()\n            predMask = torch.sigmoid(predMask)            \n\n            #append predictions to list\n            yMask.append(predMask.cpu().numpy())\n            \n    #convert list to array\n    yMask = np.array(yMask)\n   \n    return yMask","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.29087Z","iopub.execute_input":"2023-06-06T04:28:51.291388Z","iopub.status.idle":"2023-06-06T04:28:51.307899Z","shell.execute_reply.started":"2023-06-06T04:28:51.291354Z","shell.execute_reply":"2023-06-06T04:28:51.306885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Adapted from https://www.kaggle.com/code/stainsby/fast-tested-rle/notebook\n# and https://www.kaggle.com/code/kotaiizuka/faster-rle/notebook\ndef rle(output):\n    #pixels = np.where(output.flatten().cpu() > THRESHOLD, 1, 0).astype(np.uint8)\n    pixels = np.where(output.flatten() > THRESHOLD, 1, 0).astype(np.uint8)\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 ' '.join(str(x) for x in runs)","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.309503Z","iopub.execute_input":"2023-06-06T04:28:51.31019Z","iopub.status.idle":"2023-06-06T04:28:51.322159Z","shell.execute_reply.started":"2023-06-06T04:28:51.310157Z","shell.execute_reply":"2023-06-06T04:28:51.32111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#best accuracy models 6,7,8,9 with different architectures \n\nmodel1, _ = createModel(1) #unet++\nmodel2, _ = createModel(2) #unet\nmodel3, _ = createModel(3) #Linknet\nmodel4, _ = createModel(4) #FPN","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:51.323753Z","iopub.execute_input":"2023-06-06T04:28:51.324158Z","iopub.status.idle":"2023-06-06T04:28:59.458344Z","shell.execute_reply.started":"2023-06-06T04:28:51.324127Z","shell.execute_reply":"2023-06-06T04:28:59.456833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preparePlot(predMaskAvg, predMask1, predMask2, predMask3, predMask4, labelMask = None, threshold = 0.45):\n\n    #initialize our figure\n    cols = 6\n    if labelMask is None:\n        cols -= 1\n    figure, ax = plt.subplots(nrows=1, ncols=cols, figsize=(10, 10))\n    \n    \n    #plot \n    ax[0].imshow((predMaskAvg > threshold) * 255)\n    ax[1].imshow((predMask1 > threshold) * 255)\n    ax[2].imshow((predMask2 > threshold) * 255)\n    ax[3].imshow((predMask3 > threshold) * 255)\n    ax[4].imshow((predMask4 > threshold) * 255)\n    if labelMask is not None:\n        ax[5].imshow((labelMask * 255).astype('int8'))\n        \n    #set the titles of the subplots\n    ax[0].set_title(\"Pred Avg \" + str(threshold))\n    ax[1].set_title(\"Unet++ \"  + str(threshold))\n    ax[2].set_title(\"Unet \"  + str(threshold))\n    ax[3].set_title(\"Linknet \"  + str(threshold))\n    ax[4].set_title(\"FPN \"  + str(threshold))\n    \n    if labelMask is not None:\n        ax[5].set_title(\"Label\")\n\n    figure.tight_layout()\n \n    figure.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:59.460257Z","iopub.execute_input":"2023-06-06T04:28:59.460655Z","iopub.status.idle":"2023-06-06T04:28:59.476258Z","shell.execute_reply.started":"2023-06-06T04:28:59.46062Z","shell.execute_reply":"2023-06-06T04:28:59.474543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def unpackImage(imageList,pad_h,pad_w):\n    #assemble predicted image parts to one big image\n    image = np.zeros(shape=(pad_h, pad_w))\n    \n    len_h = pad_h / TILE_SIZE\n    len_w = pad_w / TILE_SIZE\n    \n    h = 0\n    w = 0\n\n    #fill predicted image with partial predictions\n    for i in range(len(imageList)):\n        image[h:h + TILE_SIZE,w:w + TILE_SIZE] = imageList[i,:,:]\n        w += TILE_SIZE\n        if w >= pad_w:\n            h += TILE_SIZE\n            w = 0\n    \n    return image","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:59.478502Z","iopub.execute_input":"2023-06-06T04:28:59.479049Z","iopub.status.idle":"2023-06-06T04:28:59.502533Z","shell.execute_reply.started":"2023-06-06T04:28:59.478999Z","shell.execute_reply":"2023-06-06T04:28:59.501204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predictFolder(path):\n    startTime = time.time()\n    #predict for submission\n    TILE_SIZE= 224\n    SIZE= TILE_SIZE\n    \n    #record accuracies\n    acTreshold = []\n    acAvg = []\n    acUnetpp = []\n    acUnet = []\n    acLink = []\n    acFdn = []\n    \n    #first testset\n    paths = []\n    paths.append(path)\n    \n    if os.path.isfile(path + \"/inklabels.png\"):\n        labelExist = True\n        labelPath = path + \"/inklabels.png\"\n        label_mask = cv2.imread(labelPath, 0)\n        labelImage = label_mask\n        label_mask = (label_mask / 255).astype('float32')\n    else:\n        label_mask = None\n        labelImage = label_mask\n        labelExist = False\n\n    test_set, _ = create_dataset(paths)\n\n    yMask1 = predictTest(model1,test_set) #unet++\n    yMask2 = predictTest(model2,test_set) #unet\n    yMask3 = predictTest(model3,test_set) #linknet\n    yMask4 = predictTest(model4,test_set) #fdn\n    \n    #build average prediction  \n    yMask = (yMask1 + yMask2 + yMask3 + yMask4) /4\n\n    print(\"Predicted mask shape :\" + str(yMask.shape) )\n\n    binary_mask = cv2.imread(path + \"/mask.png\", 0)\n    binary_mask = (binary_mask / 255).astype('float32')\n\n    #original size\n    ori_h = binary_mask.shape[0]\n    ori_w = binary_mask.shape[1]\n\n    #padding again to fit with our tile size\n    pad0 = (TILE_SIZE - binary_mask.shape[0] % TILE_SIZE)\n    pad1 = (TILE_SIZE - binary_mask.shape[1] % TILE_SIZE)\n\n    binary_mask_padded = np.pad(binary_mask, [(0, pad0), (0, pad1)], constant_values=0)\n\n    pad_h = binary_mask_padded.shape[0]\n    pad_w = binary_mask_padded.shape[1]\n    \n    #assemble predicted image parts to big image\n    yPred = unpackImage(yMask,pad_h,pad_w)\n    yPred1 = unpackImage(yMask1,pad_h,pad_w)\n    yPred2 = unpackImage(yMask2,pad_h,pad_w)\n    yPred3 = unpackImage(yMask3,pad_h,pad_w)\n    yPred4 = unpackImage(yMask4,pad_h,pad_w)\n    \n    del yMask1\n    del yMask2\n    del yMask3\n    del yMask4\n\n    gc.collect()\n\n    #back to original size\n    yPred = yPred[:ori_h, :ori_w] \n    yPred1 = yPred1[:ori_h, :ori_w] \n    yPred2 = yPred2[:ori_h, :ori_w]\n    yPred3 = yPred3[:ori_h, :ori_w] \n    yPred4 = yPred4[:ori_h, :ori_w] \n\n    #multiply with mask to set predictions to zero if corresponding mask is zero\n    yPred = np.multiply(binary_mask, yPred)\n    yPred1 = np.multiply(binary_mask, yPred1)\n    yPred2 = np.multiply(binary_mask, yPred2)\n    yPred3 = np.multiply(binary_mask, yPred3)\n    yPred4 = np.multiply(binary_mask, yPred4)\n\n    #show predictions \n    preparePlot(yPred, yPred1, yPred2, yPred3, yPred4, labelImage, 0.5)\n\n\n    \n    #if labels exist, display accuracy for multiple thresholds\n    if labelExist == True:\n        for t in range(20,70,5):\n            tact = t/100\n            \n            accAvg = ((((yPred > tact) * 1 == label_mask).astype('float32').sum())/label_mask.size) * 100\n            acc1 = ((((yPred1 > tact) * 1 == label_mask).astype('float32').sum())/label_mask.size) * 100\n            acc2 = ((((yPred2 > tact) * 1 == label_mask).astype('float32').sum())/label_mask.size) * 100\n            acc3 = ((((yPred3 > tact) * 1 == label_mask).astype('float32').sum())/label_mask.size) * 100\n            acc4 = ((((yPred4 > tact) * 1 == label_mask).astype('float32').sum())/label_mask.size) * 100\n            \n            acTreshold.append(tact)\n            acAvg.append(accAvg)\n            acUnetpp.append(acc1)\n            acUnet.append(acc2)\n            acLink.append(acc3)\n            acFdn.append(acc4)           \n            \n            #print(\"Average Accuracy: {:.2f} threshold: {:.2f}\".format(accAvg,tact))\n            #print(\"Accuracy Unet: {:.2f} threshold: {:.2f}\".format(acc2,tact))\n            #print(\"Accuracy Linknet: {:.2f} threshold: {:.2f}\".format(acc3,tact))\n            #print(\"Accuracy FPN: {:.2f} threshold: {:.2f}\".format(acc4,tact))\n            #print(\"*************************************************************\")\n            \n        #plot accuracy \n        plt.figure(2,(15,15))\n        plt.subplot(111)\n        plt.plot(acTreshold, acAvg, label=\"Average\")\n        plt.plot(acTreshold, acUnetpp, label=\"Unet++\")\n        plt.plot(acTreshold, acUnet, label=\"Unet\")\n        plt.plot(acTreshold, acLink, label=\"LinkNet\")\n        plt.plot(acTreshold, acFdn, label=\"FDN\")\n\n        plt.xlabel(\"Activation threshold\")\n        plt.ylabel(\"Accuracy\")\n\n        plt.title(\"Accuracy/Activation\")\n\n        plt.legend()\n\n        plt.show()\n            \n    #multiply with 1 to receive 0,1 values instead of True, False values\n    yPred = (yPred > THRESHOLD) * 1\n    yPred1 = (yPred1 > THRESHOLD) * 1\n    yPred2 = (yPred2 > THRESHOLD) * 1\n    yPred3 = (yPred3 > THRESHOLD) * 1\n    yPred4 = (yPred4 > THRESHOLD) * 1\n\n    #some statistics to compare data structure\n    print(\"yPrediction:\" + \" min: \" + str(yPred.min()) + \" max: \" + str(yPred.max()) + \" shape: \" + str(yPred.shape)  + \" size: \" + str(yPred.size))\n    print(\"Binary Mask:\" + \" min: \" + str(binary_mask.min()) + \" max: \" + str(binary_mask.max()) + \" shape: \" + str(binary_mask.shape) + \" size: \" + str(binary_mask.size))\n    if labelExist == True:\n        print(\"Label Mask:\" + \" min: \" + str(label_mask.min()) + \" max: \" + str(label_mask.max()) + \" shape: \" + str(label_mask.shape) + \" size: \" + str(label_mask.size))\n    print(\"**************************************************************************************************\")\n    #use the average predictions for submission\n    rleOutput = rle(yPred)\n\n    endTime = time.time()\n    totalTime = endTime - startTime\n    print(\"Total time: {:.2f} seconds\".format(totalTime))\n    \n\n    \n    return rleOutput","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:59.504394Z","iopub.execute_input":"2023-06-06T04:28:59.504922Z","iopub.status.idle":"2023-06-06T04:28:59.542307Z","shell.execute_reply.started":"2023-06-06T04:28:59.504882Z","shell.execute_reply":"2023-06-06T04:28:59.540872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if SUBMIT == False:\n    _ = predictFolder(\"/kaggle/input/vesuvius-challenge-ink-detection/train/1\")","metadata":{"execution":{"iopub.status.busy":"2023-06-06T04:28:59.544224Z","iopub.execute_input":"2023-06-06T04:28:59.545079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if SUBMIT == False:\n    _ = predictFolder(\"/kaggle/input/vesuvius-challenge-ink-detection/train/2\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if SUBMIT == False:\n    _ = predictFolder(\"/kaggle/input/vesuvius-challenge-ink-detection/train/3\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rleOutput1 = predictFolder(\"/kaggle/input/vesuvius-challenge-ink-detection/test/a\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rleOutput2 = predictFolder(\"/kaggle/input/vesuvius-challenge-ink-detection/test/b\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = []\nresults.append(('a',rleOutput1))\nresults.append(('b',rleOutput2))\nsubmission = pd.DataFrame(results, columns=['Id', 'Predicted'])\nsubmission","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}