{"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":"# TL;DR\n\nThe goal is to detecting ink from 3D X-ray scans and reading the contents. <br>\nDue to the heat of the volcano, the scrolls were carbonized, and are now impossible to open without breaking them.<br>\nWe will try to find the best model to get the maximum accuracy.\n\nUriel Malka - www.kaggle.com/urielmalka <br>\nDori Rosen - www.kaggle.com/dorirosen","metadata":{}},{"cell_type":"markdown","source":"# Imports","metadata":{}},{"cell_type":"code","source":"import csv\nfrom torch import nn\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nimport numpy as np\nimport random\nfrom random import randrange, shuffle\nfrom matplotlib import pyplot as plt\nimport matplotlib.patches as patches\nfrom torchvision import transforms\nfrom torchvision.transforms.functional import rotate\nimport torchvision\nimport cv2\nimport time, glob\nimport PIL\nimport os\nimport gc\nimport pandas as pd \nimport torch.utils.data as data\nfrom tqdm import tqdm\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nROOT_DIR = f\"/kaggle/input/vesuvius-challenge-ink-detection\"","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:51:27.054236Z","iopub.execute_input":"2023-06-04T12:51:27.054637Z","iopub.status.idle":"2023-06-04T12:51:32.668827Z","shell.execute_reply.started":"2023-06-04T12:51:27.054594Z","shell.execute_reply":"2023-06-04T12:51:32.667893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\nsys.path.append('/kaggle/input/pretrainedmodels/pretrainedmodels-0.7.4')\nsys.path.append('/kaggle/input/efficientnet-pytorch/EfficientNet-PyTorch-master')\nsys.path.append('/kaggle/input/timm-pytorch-image-models/pytorch-image-models-master')\nsys.path.append('/kaggle/input/segmentation-models-pytorch/segmentation_models.pytorch-master')","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:51:32.670909Z","iopub.execute_input":"2023-06-04T12:51:32.671291Z","iopub.status.idle":"2023-06-04T12:51:32.677638Z","shell.execute_reply.started":"2023-06-04T12:51:32.671257Z","shell.execute_reply":"2023-06-04T12:51:32.676351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# The scrolls\n- Show data from train (images and shape).","metadata":{}},{"cell_type":"code","source":"\"\"\" Show data from train folder \"\"\"\n\ndef show_image(path):\n    fig, axs = plt.subplots(1, 3,figsize=(12, 6))\n    count = 0\n    for img in glob.glob(f\"{path}/*\"):\n\n        if \".png\" not in img:\n            continue\n        image = PIL.Image.open(img)\n        label = img.split(\"/\")[-1]\n        image_array = np.array(image)\n        axs[count].imshow(image_array, cmap=\"gray\")\n        axs[count].set_xlabel(f\"File = {label}\")\n        count += 1\n    for ax in axs.flat:\n      ax.set(xticks=[], yticks=[], ylabel='')\n\n\nshow_image(f\"{ROOT_DIR}/train/1\")\nshow_image(f\"{ROOT_DIR}/train/2\")\nshow_image(f\"{ROOT_DIR}/train/3\")","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:51:32.679199Z","iopub.execute_input":"2023-06-04T12:51:32.679890Z","iopub.status.idle":"2023-06-04T12:51:59.267824Z","shell.execute_reply.started":"2023-06-04T12:51:32.679856Z","shell.execute_reply":"2023-06-04T12:51:59.266950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Layers\n\nTo ensure accurate testing, it is advisable to focus on the inner layers of the sample rather than the outer layers.<br>\nThe outer layers may contain volcanic ash, which could potentially interfere with the test results. <br>\nTherefore, it is recommended to exclude the outer layers from the testing process to maintain the reliability and validity of the tests.<br><br>\n\n<strong>We will take for training the layers from X_START to (X_END - 1) </strong> <br><br>","metadata":{}},{"cell_type":"markdown","source":"![slices.png](attachment:ead05af8-5a06-4abc-8813-0ea5a72bb9e0.png)","metadata":{},"attachments":{"ead05af8-5a06-4abc-8813-0ea5a72bb9e0.png":{"image/png":"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"}}},{"cell_type":"code","source":"X_START = 20\nX_END = 40\nLAYERS_SIZE = X_END - X_START","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:51:59.270231Z","iopub.execute_input":"2023-06-04T12:51:59.271085Z","iopub.status.idle":"2023-06-04T12:51:59.276030Z","shell.execute_reply.started":"2023-06-04T12:51:59.271052Z","shell.execute_reply":"2023-06-04T12:51:59.275180Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataSet","metadata":{}},{"cell_type":"code","source":"class VesuviusDataset(data.Dataset):\n\n    def __init__(self, \n                 slice_imgs:list[str],\n                 mask_path:str,\n                 label_path:str = None,\n                 validation_rectangle: tuple[4] = None,\n                 validation:bool =False,\n                 voxels:tuple[3]= (224,224,LAYERS_SIZE)):\n        super(VesuviusDataset).__init__()\n        self.slice_imgs = slice_imgs\n        self.mask_path = mask_path\n        self.label_path = label_path\n        self.validation = validation\n        self.voxels = voxels\n        self.validation_rectangle = validation_rectangle\n        \n        self.z = voxels[2]\n        \n        self.load_label()\n        self.load_slices()\n        self.crate_pixels(validation_rectangle)\n\n    def load_label(self):\n        self.mask = torch.from_numpy(np.array(PIL.Image.open(self.mask_path))).gt(0).float().bool()\n        if self.label_path:\n            \"\"\" If True that mean this DataSet for train or validation because we don't have label for test \"\"\"\n            self.label = torch.from_numpy(np.array(PIL.Image.open(self.label_path))).gt(0).float()\n\n\n        self.shape = self.mask.shape\n\n        self.x = self.shape[0]\n        self.y = self.shape[1]\n        \n\n\n    def crate_pixels(self,validation_rectangle: tuple[4]):\n\n        if not validation_rectangle:\n            \"\"\" If True that mean this DataSet for test \"\"\"\n            self.pixels = [(x,y) for x in range(self.x) for y in range(self.y) if self.mask[x][y]]\n            return\n\n        \"\"\"\n            The next line in this function is for train and validation.\n        \"\"\"\n\n        x0,y0,x1,y1 = validation_rectangle\n\n        def check_area(x,y):\n            \"\"\"\n                self.mask[x][y]] is False mean we out of the correct area\n                self.mask[x][y] is True  mean we in the correct area\n            \"\"\"\n\n\n            if self.validation:\n                \"\"\" This return us all pixles in the rectangle area \"\"\"\n                return x0 < x < x1 and y0 < y < y1 and self.mask[x][y]\n             \n            \"\"\" This return us all pixles out of the rectangle area \"\"\"\n            return not (x0 < x < x1 and y0 < y < y1) and self.mask[x][y]\n\n        \"\"\" (x,y) = [z0,z1, .. , z64] \"\"\"\n        self.pixels = [(x,y) for x in range(self.x) for y in range(self.y) if check_area(x, y)]\n\n    def get_3D_voxels(self,x,y):\n        \n        new_image_3d = np.zeros(self.voxels)\n\n        x_range = self.voxels[0] // 2\n        y_range = self.voxels[1] // 2\n\n        x0 = x - x_range\n        y0 = y - y_range\n        x1 = x0 + self.voxels[0]\n        y1 = y0 + self.voxels[1]\n\n        x_count = 0\n        y_count = 0\n\n        for xd in range(x0,x1):\n            y_count = 0\n            for yd in range(y0,y1):\n                if yd >= 0 and xd >= 0:\n                    z = self.image_stack[xd][yd]\n                    new_image_3d[x_count][y_count] = z\n                    \n                y_count+= 1\n            x_count += 1\n\n        return new_image_3d\n    \n    \n    def get_2D_mask(self,x,y):\n        \n        new_mask_2d = np.zeros((self.voxels[0],self.voxels[1]))\n        x_range = self.voxels[0] // 2\n        y_range = self.voxels[1] // 2\n\n        x0 = x - x_range\n        y0 = y - y_range\n        x1 = x + x_range\n        y1 = y + y_range\n\n        x_count = 0\n        y_count = 0\n\n        for xd in range(x0,x1): \n            y_count = 0\n            for yd in range(y0,y1):\n                if yd >= 0 and xd >= 0:\n                    new_mask_2d[x_count][y_count] = self.label[xd][yd]\n                y_count+= 1\n            x_count += 1\n\n        return new_mask_2d\n        \n\n    def load_slices(self):\n        images = [np.array(PIL.Image.open(filename), dtype=np.float32)/65535.0 for filename in tqdm(self.slice_imgs)]\n        self.image_stack = torch.stack([torch.from_numpy(image) for image in images], dim=2)\n\n    def __len__(self):\n        return len(self.pixels)\n    \n    def get_z_slide(self):\n        x, y = self.pixels[randrange(self.__len__())]\n        z = self.image_stack[x][y]\n\n        if self.label_path:\n            l = self.label[x][y]\n        else:\n            \"\"\" l = None only for test \"\"\"\n            l = None \n\n        return z , l ,(x,y)\n\n\n\n    def __getitem__(self, index):\n        x, y = self.pixels[index]\n        img3d = self.get_3D_voxels(x,y)\n\n        if self.label_path:\n            l = self.get_2D_mask(x,y)\n        else:\n            \"\"\" l = None only for test \"\"\"\n            l = None \n\n        \"\"\"\n        return values:\n            img3d - list of z dimention \n            l - label if 1 is ink if 0 is noink\n            (x,y) - location from the image \n        \"\"\"\n        return img3d , l \n    \n    def getranditem(self,):\n        x, y = self.pixels[randrange(self.__len__())]\n        img3d = self.get_3D_voxels(x,y)\n\n        if self.label_path:\n            l = self.get_2D_mask(x,y)\n        else:\n            \"\"\" l = None only for test \"\"\"\n            l = None \n\n        \"\"\"\n        return values:\n            img3d - list of z dimention \n            l - label if 1 is ink if 0 is noink\n            (x,y) - location from the image \n        \"\"\"\n        return img3d , l ,(x,y)\n    \n\n    \"\"\" Show validation rectangle \"\"\"\n    def show_validation_rectangle(self):\n        if self.validation_rectangle:\n            array_2d = self.label\n            fig, ax = plt.subplots()\n            ax.imshow(array_2d, cmap='gray')\n            rectangle = self.validation_rectangle\n            rectangle_x = self.validation_rectangle[0]\n            rectangle_y = self.validation_rectangle[1]\n            rectangle_width = self.validation_rectangle[2]\n            rectangle_height = self.validation_rectangle[3]\n            rectangle = patches.Rectangle((rectangle_x, rectangle_y), rectangle_width, rectangle_height, linewidth=2, edgecolor='r', facecolor='none')\n            ax.add_patch(rectangle)\n            plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:51:59.277584Z","iopub.execute_input":"2023-06-04T12:51:59.277933Z","iopub.status.idle":"2023-06-04T12:51:59.309286Z","shell.execute_reply.started":"2023-06-04T12:51:59.277901Z","shell.execute_reply":"2023-06-04T12:51:59.308228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val1 = list(glob.glob(f\"{ROOT_DIR}/train/1/surface_volume/*\"))[X_START:X_END]\nlabel = f\"{ROOT_DIR}/train/1/inklabels.png\"\nmask = f\"{ROOT_DIR}/train/1/mask.png\"\n\ntrain_VesuviusDataset = VesuviusDataset(slice_imgs=val1,\n                                        mask_path=mask,\n                                       label_path=label,\n                                        validation_rectangle = (1500,1500,2000,2000))","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:51:59.310913Z","iopub.execute_input":"2023-06-04T12:51:59.311272Z","iopub.status.idle":"2023-06-04T12:57:16.688473Z","shell.execute_reply.started":"2023-06-04T12:51:59.311239Z","shell.execute_reply":"2023-06-04T12:57:16.687380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Show slices from Z dimention\n\n-  There is a resize in the image from (1 x LAYERS_SIZE) to (20 x LAYERS_SIZE) to make it more visually clear.","metadata":{}},{"cell_type":"code","source":"def show_dataset(dataset:VesuviusDataset):\n    fig, axs = plt.subplots(1, 10,figsize=(12, 6))\n\n    for count in range(10):\n        new_image = np.zeros((LAYERS_SIZE,20))\n        z , l ,(x,y) =  dataset.get_z_slide()\n\n        for slice in range(LAYERS_SIZE):\n            new_image[slice] = z[slice]\n        \n        axs[count].imshow(new_image, cmap=\"gray\")\n        axs[count].set_xlabel(f\"Ink = {l.bool()}\")\n        count += 1\n    for ax in axs.flat:\n        ax.set(xticks=[], yticks=[], ylabel='')\n\n\n#show_dataset(train_VesuviusDataset)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:57:16.689806Z","iopub.execute_input":"2023-06-04T12:57:16.691666Z","iopub.status.idle":"2023-06-04T12:57:16.700397Z","shell.execute_reply.started":"2023-06-04T12:57:16.691629Z","shell.execute_reply":"2023-06-04T12:57:16.699392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Show 3D segmentation ","metadata":{}},{"cell_type":"code","source":"def show_3d_dataset(dataset:VesuviusDataset):\n    global X_START\n    \n    \n    fig, axs = plt.subplots(2, 2,figsize=(8, 10))\n    for img_indx in range(2):\n        while True:\n            array_3d , mask_label, (x,y)  =  dataset.getranditem()\n            if np.any(mask_label == 1):\n                break\n        z_layer = randrange(LAYERS_SIZE)\n        slice_2d = array_3d[:, :, z_layer]\n        \n        axs[img_indx][0].imshow(slice_2d, cmap=\"gray\")\n        axs[img_indx][0].set_xlabel(f\"3D Input (x,y) = {(x,y)}\\nShape = {slice_2d.shape}\")\n        axs[img_indx][1].imshow(mask_label, cmap=\"gray\")\n        axs[img_indx][1].set_xlabel(f\"Mask\")\n    for ax in axs.flat:\n        ax.set(xticks=[], yticks=[], ylabel='')\n\nshow_3d_dataset(train_VesuviusDataset)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:57:16.701772Z","iopub.execute_input":"2023-06-04T12:57:16.702757Z","iopub.status.idle":"2023-06-04T12:57:21.610335Z","shell.execute_reply.started":"2023-06-04T12:57:16.702716Z","shell.execute_reply":"2023-06-04T12:57:21.609459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataSet and fucntions for test","metadata":{}},{"cell_type":"code","source":"class CFG:\n    # ============== comp exp name =============\n    comp_name = 'vesuvius'\n    comp_dir_path = '/kaggle/input/'\n    comp_folder_name = 'vesuvius-challenge-ink-detection'\n    comp_dataset_path = f'{comp_dir_path}{comp_folder_name}/'\n    \n    # ============== pred target =============\n    target_size = 1\n\n    # ============== model cfg =============\n    model_name = 'Unet'\n    backbone= 'densenet161'\n\n    in_chans = 13\n    # ============== training cfg =============\n    size = 224\n    tile_size = 224\n    stride = 224 // 4\n\n    train_batch_size = 128 \n    valid_batch_size = train_batch_size * 2\n\n    epochs = 15 # 30\n\n    warmup_factor = 10\n    lr = 1e-4 / warmup_factor\n    # ============== fold =============\n    valid_id = 1\n    metric_direction = 'maximize' \n\n    # ============== fixed =============\n    pretrained = True\n    inf_weight = 'best'  # 'best'\n\n    min_lr = 1e-6\n    weight_decay = 1e-6\n    max_grad_norm = 1000\n\n    print_freq = 50\n    num_workers = 0\n\n    seed = 42\n    #'''\n    # ============== set dataset path =============\n    print('set dataset path')\n    exp_name = 'exp_name'\n    outputs_path = f'/kaggle/working/outputs/{comp_name}/{exp_name}/'\n\n    submission_dir = outputs_path + 'submissions/'\n    submission_path = submission_dir + f'submission_{exp_name}.csv'\n\n    model_dir = outputs_path + \\\n        f'{comp_name}-models/'\n\n    figures_dir = outputs_path + 'figures/'\n\n    log_dir = outputs_path + 'logs/'\n    log_path = log_dir + f'{exp_name}.txt'\n    #'''\n    # ============== augmentation =============\n    \n    train_aug_list = [\n        A.RandomBrightnessContrast(p=0.25),\n        A.RandomGridShuffle(grid=(3, 3), always_apply=False, p=0.4),\n        A.OneOf([\n                A.GaussNoise(var_limit=[10, 50]),\n                A.GaussianBlur(),\n                A.MotionBlur(),\n                ], p=0.4),\n        A.GridDistortion(num_steps=5, distort_limit=0.3, p=0.5),\n        A.CoarseDropout(max_holes=1, max_width=int(size * 0.3), max_height=int(size * 0.3), \n                        mask_fill_value=0, p=0.5),\n        A.Normalize(mean= [0] * in_chans, std= [1] * in_chans),\n        ToTensorV2(transpose_mask=True)\n    ]\n\n    valid_aug_list = [\n        A.OneOf([\n                A.GaussNoise(var_limit=[10, 50]),\n                A.GaussianBlur(),\n                A.MotionBlur(),\n                ], p=0.4),\n        A.RandomGridShuffle(grid=(3, 3), always_apply=False, p=0.4),\n        A.Normalize(mean= [0] * in_chans, std= [1] * in_chans),\n        ToTensorV2(transpose_mask=True)\n    ]\n\n\nclass InkDetectionDatasetTest(Dataset):\n    def __init__(self, images, cfg, labels=None, transform=None):\n        self.images = images\n        self.cfg = cfg\n        self.labels = labels\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        \n        label = np.zeros_like(image)\n\n        if self.transform:\n            data = self.transform(image=image, mask=label)\n            image = data['image']\n            label = data['mask']\n        \n        return image\n\ndef read_image_mask(fragment_id):\n     \n    images = []\n    start = 22\n    end = 35\n    idxs = range(start, end)\n\n    for i in tqdm(idxs):\n        ForStringNumber = str(\"{:02d}\".format(i))\n        tpath = CFG.comp_dataset_path + f\"test/{fragment_id}/surface_volume/{ForStringNumber}.tif\"\n        image = cv2.imread(tpath,0)\n        \n        pad0 = (CFG.tile_size - image.shape[0] % CFG.tile_size)\n        pad1 = (CFG.tile_size - image.shape[1] % CFG.tile_size)\n\n        image = np.pad(image, [(0, pad0), (0, pad1)], constant_values=0)\n\n        images.append(image)\n    images = np.stack(images, axis=2)\n    \n    return images\n    \n    \ndef rle(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = img.flatten()\n    # pixels = (pixels >= thr).astype(int)\n    \n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef make_test_dataset(fragment_id):\n    test_images = read_image_mask(fragment_id)\n    \n    x1_list = list(range(0, test_images.shape[1]-CFG.tile_size+1,CFG.stride//4))\n    y1_list = list(range(0, test_images.shape[0]-CFG.tile_size+1, CFG.stride//4))\n    \n    test_images_list = []\n    xyxys = []\n    for y1 in y1_list:\n        for x1 in x1_list:\n            y2 = y1 + CFG.tile_size\n            x2 = x1 + CFG.tile_size\n            \n            test_images_list.append(test_images[y1:y2, x1:x2])\n            xyxys.append((x1, y1, x2, y2))\n    xyxys = np.stack(xyxys)\n            \n    test_dataset = InkDetectionDatasetTest(test_images_list, CFG, transform=A.Compose(CFG.valid_aug_list))\n    \n    test_loader = DataLoader(test_dataset,\n                          batch_size=CFG.train_batch_size,\n                          shuffle=False,\n                          num_workers=CFG.num_workers, pin_memory=True, drop_last=False)\n    \n    return test_loader, xyxys","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:57:21.611848Z","iopub.execute_input":"2023-06-04T12:57:21.612404Z","iopub.status.idle":"2023-06-04T12:57:21.677831Z","shell.execute_reply.started":"2023-06-04T12:57:21.612369Z","shell.execute_reply":"2023-06-04T12:57:21.674258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test: Unet - ResNet18  \n    - Tanh\n    ","metadata":{}},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\nmodel = torch.load(\"/kaggle/input/resnet18-tanh-x/u-resnet18_tanhadamW_best_model_lr0.00001.pth\", map_location=device)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:57:21.679340Z","iopub.status.idle":"2023-06-04T12:57:21.679900Z","shell.execute_reply.started":"2023-06-04T12:57:21.679637Z","shell.execute_reply":"2023-06-04T12:57:21.679660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TH = 0.4\nfragment_ids = sorted(os.listdir(CFG.comp_dataset_path + \"test\"))","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:57:21.700672Z","iopub.status.idle":"2023-06-04T12:57:21.701148Z","shell.execute_reply.started":"2023-06-04T12:57:21.700901Z","shell.execute_reply":"2023-06-04T12:57:21.700924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = []\nfor fragment_id in fragment_ids:\n    \n    test_loader, xyxys = make_test_dataset(fragment_id)\n    \n    \n    binary_mask = cv2.imread(CFG.comp_dataset_path + f\"test/{fragment_id}/mask.png\", 0)\n    binary_mask = (binary_mask / 255).astype(int)\n    \n    ori_h = binary_mask.shape[0]\n    ori_w = binary_mask.shape[1]\n    # mask = mask / 255\n\n    pad0 = (CFG.tile_size - binary_mask.shape[0] % CFG.tile_size)\n    pad1 = (CFG.tile_size - binary_mask.shape[1] % CFG.tile_size)\n\n    binary_mask = np.pad(binary_mask, [(0, pad0), (0, pad1)], constant_values=0)\n    \n    mask_pred = np.zeros(binary_mask.shape)\n    mask_count = np.zeros(binary_mask.shape)\n\n    for step, (images) in tqdm(enumerate(test_loader), total=len(test_loader)):\n        images = images.to(device)\n        batch_size = images.size(0)\n\n        with torch.no_grad():\n            y_preds = model(images)\n\n        start_idx = step*CFG.train_batch_size\n        end_idx = start_idx + batch_size\n        for i, (x1, y1, x2, y2) in enumerate(xyxys[start_idx:end_idx]):\n            mask_pred[y1:y2, x1:x2] += y_preds[i].squeeze(0).cpu().detach().numpy()\n            mask_count[y1:y2, x1:x2] += np.ones((CFG.tile_size, CFG.tile_size))            \n    \n    #plt.imshow(mask_count)\n    #plt.show()\n    \n    print(f'mask_count_min: {mask_count.min()}')\n    mask_pred /= mask_count\n    \n    mask_pred = mask_pred[:ori_h, :ori_w]\n    binary_mask = binary_mask[:ori_h, :ori_w]\n    \n    mask_pred = (mask_pred >= TH).astype(int)\n    mask_pred *= binary_mask\n    \n    mask_pred = np.resize(mask_pred, (ori_h, ori_w))\n    \n    plt.imshow(mask_pred,cmap=\"gray\")\n    plt.show()\n    \n    inklabels_rle = rle(mask_pred)\n    \n    results.append((fragment_id, inklabels_rle))\n    \n\n    del mask_pred, mask_count\n    del test_loader\n    \n    gc.collect()\n    torch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:57:21.706128Z","iopub.status.idle":"2023-06-04T12:57:21.706581Z","shell.execute_reply.started":"2023-06-04T12:57:21.706349Z","shell.execute_reply":"2023-06-04T12:57:21.706370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"print(\"Start sunmission\")\nsub = pd.DataFrame(results, columns=['Id', 'Predicted'])\nsample_sub = pd.read_csv(CFG.comp_dataset_path + 'sample_submission.csv')\nsample_sub = pd.merge(sample_sub[['Id']], sub, on='Id', how='left')\nsample_sub.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T12:57:21.708581Z","iopub.status.idle":"2023-06-04T12:57:21.709043Z","shell.execute_reply.started":"2023-06-04T12:57:21.708801Z","shell.execute_reply":"2023-06-04T12:57:21.708822Z"},"trusted":true},"execution_count":null,"outputs":[]}]}