{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":61446,"databundleVersionId":6962461,"sourceType":"competition"},{"sourceId":7187369,"sourceType":"datasetVersion","datasetId":4087873},{"sourceId":7312958,"sourceType":"datasetVersion","datasetId":4229452},{"sourceId":7317236,"sourceType":"datasetVersion","datasetId":4243245},{"sourceId":7322239,"sourceType":"datasetVersion","datasetId":4249424,"isSourceIdPinned":true},{"sourceId":7336367,"sourceType":"datasetVersion","datasetId":4250312,"isSourceIdPinned":true},{"sourceId":7348703,"sourceType":"datasetVersion","datasetId":4265818,"isSourceIdPinned":true},{"sourceId":7358606,"sourceType":"datasetVersion","datasetId":4267714,"isSourceIdPinned":true},{"sourceId":7501814,"sourceType":"datasetVersion","datasetId":4368429},{"sourceId":7545275,"sourceType":"datasetVersion","datasetId":4394075},{"sourceId":7546656,"sourceType":"datasetVersion","datasetId":4395056},{"sourceId":7552187,"sourceType":"datasetVersion","datasetId":4398628},{"sourceId":150248402,"sourceType":"kernelVersion"},{"sourceId":156694315,"sourceType":"kernelVersion"}],"dockerImageVersionId":30636,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# <center style=\"font-family: consolas; font-size: 32px; font-weight: bold;\">🩺 SenNet + HOA - Hacking the Human Vasculature in 3D</center>\n<p><center style=\"color:#949494; font-family: consolas; font-size: 20px;\">Clean Code 📚| Weighted Ensemble </center></p>\n***","metadata":{}},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Import Libraries</div> ","metadata":{}},{"cell_type":"code","source":"# Importing PyTorch library \nimport torch as tc \n# Importing neural network module from PyTorch\nimport torch.nn as nn\n# Importing automatic mixed precision (AMP) for faster training on GPU\nfrom torch.cuda.amp import autocast\n# Importing Dataset and DataLoader classes for handling data in PyTorch\nfrom torch.utils.data import Dataset, DataLoader\n# Importing DataParallel for parallel processing in PyTorch\nfrom torch.nn.parallel import DataParallel\n\n\n# Importing NumPy \nimport numpy as np\n# Importing tqdm for displaying progress bars\nfrom tqdm import tqdm\n\n# Importing OpenCV library\nimport cv2\n# Importing os and sys modules for interacting with the operating system\nimport os\nimport sys\n# Importing the glob module for searching directories with wildcard patterns\nfrom glob import glob\n# Importing matplotlib \nimport matplotlib.pyplot as plt\n# Importing pandas \nimport pandas as pd\n\n# Installing segmentation Models\n!python -m pip install --no-index --find-links=/kaggle/input/pip-download-for-segmentation-models-pytorch segmentation-models-pytorch -q\n# Importing the segmentation_models_pytorch library \nimport segmentation_models_pytorch as smp\n\n# Importing load_dotenv for loading environment variables\nfrom dotenv import load_dotenv","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-02-05T04:24:40.322872Z","iopub.execute_input":"2024-02-05T04:24:40.323544Z","iopub.status.idle":"2024-02-05T04:25:07.100553Z","shell.execute_reply.started":"2024-02-05T04:24:40.323508Z","shell.execute_reply":"2024-02-05T04:25:07.099716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Config</div> ","metadata":{}},{"cell_type":"code","source":"# Defining variables to specify model paths\nmodel_path_i = 15 # [1024]\nmodel_path_i9 = 16 # [512]\n\n# Configuration class containing various model and training parameters\nclass CFG:\n    # Model configuration\n    model_name = 'Unet'\n    backbone = 'se_resnext50_32x4d'\n    in_chans = 1\n    image_size = 1024\n    input_size = 1024\n    tile_size = image_size\n    stride = tile_size // 4\n    drop_egde_pixel = 0\n    target_size = 1\n    chopping_percentile = 1e-3\n\n    # Fold and validation configuration\n    valid_id = 1\n    batch = 16\n    th_percentile = 0.0014109\n    axis_w = [0.328800989, 0.336629584, 0.334569427]\n    axis_second_model = 0\n\n    # Model paths for different folds\n    model_path = [\n        \"/kaggle/input/2-5d-cutting-model-baseline-training/se_resnext50_32x4d_19_loss0.12_score0.79_val_loss0.25_val_score0.79.pt\",\n        \"/kaggle/input/training-6-512/se_resnext50_32x4d_19_loss0.09_score0.83_val_loss0.28_val_score0.83.pt\",\n        \"/kaggle/input/training-6-512/se_resnext50_32x4d_19_loss0.05_score0.90_val_loss0.25_val_score0.86.pt\",\n        \"/kaggle/input/training-6-512/se_resnext50_32x4d_19_loss0.05_score0.89_val_loss0.24_val_score0.86_midd.pt\",\n        \"/kaggle/input/training-6-512/se_resnext50_32x4d_24_loss0.05_score0.90_val_loss0.23_val_score0.88_midd.pt\",\n        \"/kaggle/input/training-6-512/se_resnext50_32x4d_24_loss0.04_score0.91_val_loss0.23_val_score0.88_midd.pt\",  # 25 025 rot 512 center\n        \"/kaggle/input/blood-vessel-model-1024/se_resnext50_32x4d_24_loss0.10_score0.90_val_loss0.16_val_score0.85_midd_1024.pt\",\n        \"/kaggle/input/blood-vessel-model-1024/se_resnext50_32x4d_24_loss0.10_score0.90_val_loss0.12_val_score0.88_midd_1024.pt\",  # lr = 8e-5\n        \"/kaggle/input/blood-vessel-model-1024/se_resnext50_32x4d_24_loss0.91_score0.09_val_loss0.91_val_score0.09_midd_1024.pt\",  # 60e-5 \n        \"/kaggle/input/sn-hoa-8e-5-27-rot0-5/se_resnext50_32x4d_26_loss0.10_score0.90_val_loss0.12_val_score0.88_midd_1024.pt\",  # 8e-5-27-rot0-5\n        \"/kaggle/input/sn-hoa-8e-5-27-rot0-5/se_resnext50_32x4d_30_loss0.10_score0.90_val_loss0.13_val_score0.88_midd_1024.pt\",\n        \"/kaggle/input/sennet-kidney-1-and-3/model_real_23.pt\",  # 31 8e 05\n        \"/kaggle/input/hoa-alef-d-001-x1024-unet-se-resnext50-32x4d-hpexp/model_real_199.pt\", #[12] val-->loss:0.0421,score:0.9723\n        \"/kaggle/input/hoa-alef-e-003-1of3-x1024-unet-se-resnext50-32x4d/se_resnext50_32x4d_21_loss0.10_score0.90_val_loss0.11_val_score0.89_midd_1024.pt\",\n        \"/kaggle/input/hoa-alef-e-003-1of3-x1024-unet-se-resnext50-32x4d/se_resnext50_32x4d_86_loss0.07_score0.93_val_loss0.12_val_score0.88_midd_1024.pt\",\n        \"/kaggle/input/hoa-alef-e-003-1of3-x1024-unet-se-resnext50-32x4d/se_resnext50_32x4d_88_loss0.07_score0.93_val_loss0.14_val_score0.86_midd_1024.pt\",\n        \"/kaggle/input/alef-b-124-x512-unet-se-resnext50-32x4d-e45/model_real_40.pt\",\n    ]","metadata":{"execution":{"iopub.status.busy":"2024-02-05T04:25:07.102107Z","iopub.execute_input":"2024-02-05T04:25:07.102418Z","iopub.status.idle":"2024-02-05T04:25:07.110940Z","shell.execute_reply.started":"2024-02-05T04:25:07.102391Z","shell.execute_reply":"2024-02-05T04:25:07.110118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"-\"*50)\nprint(\"- UseModel(x1024):\",CFG.model_path[model_path_i])\nprint(\"- UseModel(x512) :\",CFG.model_path[model_path_i9])\nprint(\"-\"*50)","metadata":{"execution":{"iopub.status.busy":"2024-02-05T04:25:07.112499Z","iopub.execute_input":"2024-02-05T04:25:07.112809Z","iopub.status.idle":"2024-02-05T04:25:07.128232Z","shell.execute_reply.started":"2024-02-05T04:25:07.112784Z","shell.execute_reply":"2024-02-05T04:25:07.127445Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Model </div> ","metadata":{}},{"cell_type":"code","source":"# Custom model class definition\nclass CustomModel(nn.Module):\n    def __init__(self, CFG, weight=None):\n        super().__init__()\n        \n        # Storing configuration parameters within the model\n        self.CFG = CFG\n        \n        # Creating an instance of the Unet model from segmentation_models_pytorch\n        self.model = smp.Unet(\n            encoder_name=CFG.backbone, \n            encoder_weights=weight,\n            in_channels=CFG.in_chans,\n            classes=CFG.target_size,\n            activation=None,\n        )\n        \n        # Setting batch size from the configuration\n        self.batch = CFG.batch\n\n    def forward_(self, image):\n        # Forward pass through the model\n        output = self.model(image)\n        # Extracting the first channel from the output\n        return output[:, 0]\n\n    def forward(self, x: tc.Tensor):\n        # Converting input tensor to float32\n        x = x.to(tc.float32)\n        \n        # Normalizing the input tensor using a custom function 'norm_with_clip'\n        x = norm_with_clip(x.reshape(-1, *x.shape[2:])).reshape(x.shape)\n        \n        # Interpolating the input tensor if input size is not equal to image size\n        if CFG.input_size != CFG.image_size:\n            x = nn.functional.interpolate(x, size=(CFG.input_size, CFG.input_size), mode='bilinear', align_corners=True)\n        \n        # Performing data augmentation by rotating the input tensor\n        shape = x.shape\n        x = [tc.rot90(x, k=i, dims=(-2, -1)) for i in range(4)]\n        x = tc.cat(x, dim=0)\n        \n        # Using autocast for mixed precision training and no_grad to disable gradient computation\n        with autocast():\n            with tc.no_grad():\n                # Forward pass for each rotated batch\n                x = [self.forward_(x[i * self.batch:(i + 1) * self.batch]) for i in range(x.shape[0] // self.batch + 1)]\n                # Concatenating the results along the batch dimension\n                x = tc.cat(x, dim=0)\n        \n        # Applying sigmoid activation and reshaping the tensor\n        x = x.sigmoid()\n        x = x.reshape(4, shape[0], *shape[2:])\n        \n        # Rotating the tensor back to the original orientation\n        x = [tc.rot90(x[i], k=-i, dims=(-2, -1)) for i in range(4)]\n        # Stacking along a new dimension and taking the mean\n        x = tc.stack(x, dim=0).mean(0)\n        \n        # Interpolating the output tensor if input size is not equal to image size\n        if CFG.input_size != CFG.image_size:\n            x = nn.functional.interpolate(x[None], size=(CFG.image_size, CFG.image_size), mode='bilinear', align_corners=True)[0]\n        \n        return x\n\n# Function to build the model\ndef build_model(weight=None):\n    # Loading environment variables using dotenv\n    load_dotenv()\n\n    # Printing model name and backbone information\n    print('model_name', CFG.model_name)\n    print('backbone', CFG.backbone)\n\n    # Creating an instance of the CustomModel with specified weight\n    model = CustomModel(CFG, weight)\n\n    # Moving the model to the GPU\n    return model.cuda()","metadata":{"execution":{"iopub.status.busy":"2024-02-03T11:06:04.248997Z","iopub.execute_input":"2024-02-03T11:06:04.249843Z","iopub.status.idle":"2024-02-03T11:06:04.264401Z","shell.execute_reply.started":"2024-02-03T11:06:04.249802Z","shell.execute_reply":"2024-02-03T11:06:04.263544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Image Size </div> ","metadata":{}},{"cell_type":"code","source":"# Function to resize image to 1024x1024 with rotation\ndef to_1024(img, image_size=1024):\n    if image_size > img.shape[1]:\n        # Rotate image 90 degrees\n        img = np.rot90(img)\n        \n        # Calculate padding for top and bottom\n        start1 = (CFG.image_size - img.shape[0]) // 2\n        top = img[0: start1, 0: img.shape[1]]\n        bottom = img[img.shape[0] - start1: img.shape[0], 0: img.shape[1]]\n        \n        # Concatenate top, rotated image, and bottom\n        img_result = np.concatenate((top, img, bottom), axis=0)\n        \n        # Rotate image back to the original orientation\n        img_result = np.rot90(img_result)\n        img_result = np.rot90(img_result)\n        img_result = np.rot90(img_result)\n    else:\n        img_result = img\n    \n    return img_result\n\n# Function to resize image to 1024x1024 without rotation\ndef to_1024_no_rot(img, image_size=1024):\n    if image_size > img.shape[0]:\n        # Calculate padding for top and bottom\n        start1 = (image_size - img.shape[0]) // 2\n        top = img[0: start1, 0: img.shape[1]]\n        bottom = img[img.shape[0] - start1: img.shape[0], 0: img.shape[1]]\n        \n        # Concatenate top, image, and bottom\n        img_result = np.concatenate((top, img, bottom), axis=0)\n    else:\n        img_result = img\n    \n    return img_result\n\n# Function to resize image to 1024x1024 using to_1024 function\ndef to_1024_1024(img, image_size=1024):\n    img_result = to_1024(img, image_size)\n    return img_result\n\n# Function to resize image back to original size\ndef to_original(im_after, img, image_size=1024):\n    top_ = 0\n    left_ = 0\n    \n    # Calculate padding for top\n    if im_after.shape[0] > img.shape[0]:\n        top_ = (image_size - img.shape[0]) // 2\n    \n    # Calculate padding for left\n    if im_after.shape[1] > img.shape[1]:\n        left_ = (image_size - img.shape[1]) // 2\n    \n    # Extract the region of interest from the resized image\n    if (top_ > 0) or (left_ > 0):\n        img_result = im_after[top_: img.shape[0] + top_, left_: img.shape[1] + left_]\n    else:\n        img_result = im_after\n    \n    return img_result","metadata":{"execution":{"iopub.status.busy":"2024-02-03T11:06:04.489517Z","iopub.execute_input":"2024-02-03T11:06:04.489799Z","iopub.status.idle":"2024-02-03T11:06:04.502886Z","shell.execute_reply.started":"2024-02-03T11:06:04.489774Z","shell.execute_reply":"2024-02-03T11:06:04.501791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Helper Functions </div> ","metadata":{}},{"cell_type":"code","source":"# Function to encode a binary mask using Run-Length Encoding (RLE)\ndef rle_encode(mask):\n    pixel = mask.flatten()\n    pixel = np.concatenate([[0], pixel, [0]])\n    run = np.where(pixel[1:] != pixel[:-1])[0] + 1\n    run[1::2] -= run[::2]\n    rle = ' '.join(str(r) for r in run)\n    if rle == '':\n        rle = '1 0'\n    return rle\n\n# Function for min-max normalization of a PyTorch tensor\ndef min_max_normalization(x: tc.Tensor) -> tc.Tensor:\n    \"\"\"input.shape=(batch,f1,...)\"\"\"\n    shape = x.shape\n    if x.ndim > 2:\n        x = x.reshape(x.shape[0], -1)\n\n    min_ = x.min(dim=-1, keepdim=True)[0]\n    max_ = x.max(dim=-1, keepdim=True)[0]\n    if min_.mean() == 0 and max_.mean() == 1:\n        return x.reshape(shape)\n\n    x = (x - min_) / (max_ - min_ + 1e-9)\n    return x.reshape(shape)\n\n# Function for normalization with clipping of a PyTorch tensor\ndef norm_with_clip(x: tc.Tensor, smooth=1e-5):\n    dim = list(range(1, x.ndim))\n    mean = x.mean(dim=dim, keepdim=True)\n    std = x.std(dim=dim, keepdim=True)\n    x = (x - mean) / (std + smooth)\n    x[x > 5] = (x[x > 5] - 5) * 1e-3 + 5\n    x[x < -3] = (x[x < -3] + 3) * 1e-3 - 3\n    return x\n\n# Function to add an edge to an image tensor\ndef add_edge(x: tc.Tensor, edge: int):\n    # x=(C,H,W)\n    # output=(C,H+2*edge,W+2*edge)\n    mean_ = int(x.to(tc.float32).mean())\n    x = tc.cat([x, tc.ones([x.shape[0], edge, x.shape[2]], dtype=x.dtype, device=x.device) * mean_], dim=1)\n    x = tc.cat([x, tc.ones([x.shape[0], x.shape[1], edge], dtype=x.dtype, device=x.device) * mean_], dim=2)\n    x = tc.cat([tc.ones([x.shape[0], edge, x.shape[2]], dtype=x.dtype, device=x.device) * mean_, x], dim=1)\n    x = tc.cat([tc.ones([x.shape[0], x.shape[1], edge], dtype=x.dtype, device=x.device) * mean_, x], dim=2)\n    return x\n","metadata":{"execution":{"iopub.status.busy":"2024-02-03T11:06:04.742193Z","iopub.execute_input":"2024-02-03T11:06:04.742511Z","iopub.status.idle":"2024-02-03T11:06:04.758982Z","shell.execute_reply.started":"2024-02-03T11:06:04.742486Z","shell.execute_reply":"2024-02-03T11:06:04.758015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Data Loader </div> ","metadata":{}},{"cell_type":"code","source":"# Dataset class for loading images\nclass Data_loader(Dataset):\n    def __init__(self, path, s=\"/images/\"):\n        self.paths = glob(path + f\"{s}*.tif\")\n        self.paths.sort()\n        self.bool = s == \"/labels/\"\n\n    def __len__(self):\n        return len(self.paths)\n\n    def __getitem__(self, index):\n        img = cv2.imread(self.paths[index], cv2.IMREAD_GRAYSCALE)\n        img = to_1024_1024(img, image_size=CFG.image_size)\n\n        img = tc.from_numpy(img.copy())\n        if self.bool:\n            img = img.to(tc.bool)\n        else:\n            img = img.to(tc.uint8)\n        return img\n\n# Function to load data using Data_loader and perform normalization\ndef load_data(path, s):\n    data_loader = Data_loader(path, s)\n    data_loader = DataLoader(data_loader, batch_size=16, num_workers=2)\n    data = []\n    for x in tqdm(data_loader):\n        data.append(x)\n    x = tc.cat(data, dim=0)\n    \n    # Chopping values above and below a certain percentile\n    TH = x.reshape(-1).numpy()\n    index = -int(len(TH) * CFG.chopping_percentile)\n    TH: int = np.partition(TH, index)[index]\n    x[x > TH] = int(TH)\n    \n    TH = x.reshape(-1).numpy()\n    index = -int(len(TH) * CFG.chopping_percentile)\n    TH: int = np.partition(TH, -index)[-index]\n    x[x < TH] = int(TH)\n    \n    return x\n\n# Dataset class for pipeline processing\nclass Pipeline_Dataset(Dataset):\n    def __init__(self, x, path):\n        self.img_paths = glob(path + \"/images/*\")\n        self.img_paths.sort()\n        self.in_chan = CFG.in_chans\n        z = tc.zeros(self.in_chan // 2, *x.shape[1:], dtype=x.dtype)\n        self.x = tc.cat((z, x, z), dim=0)\n\n    def __len__(self):\n        return self.x.shape[0] - self.in_chan + 1\n\n    def __getitem__(self, index):\n        x = self.x[index:index + self.in_chan]\n        return x, index\n\n    def get_mark(self, index):\n        id = self.img_paths[index].split(\"/\")[-3:]\n        id.pop(1)\n        id = \"_\".join(id)\n        return id[:-4]\n\n    def get_marks(self):\n        ids = []\n        for index in range(len(self)):\n            ids.append(self.get_mark(index))\n        return ids","metadata":{"execution":{"iopub.status.busy":"2024-02-03T11:06:04.998705Z","iopub.execute_input":"2024-02-03T11:06:04.999005Z","iopub.status.idle":"2024-02-03T11:06:05.146536Z","shell.execute_reply.started":"2024-02-03T11:06:04.99898Z","shell.execute_reply":"2024-02-03T11:06:05.14556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Buiding Models </div> ","metadata":{}},{"cell_type":"code","source":"# Building and loading the 1024 x 1024 Image Model\nmodel = build_model()  # Creating an instance of the model\nmodel.load_state_dict(tc.load(CFG.model_path[model_path_i], \"cpu\"))  # Loading the pre-trained weights\nmodel.eval()  # Setting the model to evaluation mode\nmodel = DataParallel(model)  # Using DataParallel for parallel processing\n\n# Building and loading the 512 x 512 Image Model\nmodel9 = build_model()  # Creating an instance of the model\nmodel9.load_state_dict(tc.load(CFG.model_path[model_path_i9], \"cpu\"))  # Loading the pre-trained weights\nmodel9.eval()  # Setting the model to evaluation mode\nmodel9 = DataParallel(model9)  # Using DataParallel for parallel processing\n","metadata":{"execution":{"iopub.status.busy":"2024-02-03T11:06:05.223084Z","iopub.execute_input":"2024-02-03T11:06:05.223907Z","iopub.status.idle":"2024-02-03T11:06:09.304768Z","shell.execute_reply.started":"2024-02-03T11:06:05.223864Z","shell.execute_reply":"2024-02-03T11:06:09.303808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Prediction & Weighted Ensemble </div> ","metadata":{}},{"cell_type":"code","source":"# Function to get segmentation outputs\ndef get_output(debug=False):\n    outputs = []\n\n    # Specify paths for testing\n    if debug:\n        paths = [\"/kaggle/input/blood-vessel-segmentation/train/kidney_2\"]\n    else:\n        paths = glob(\"/kaggle/input/blood-vessel-segmentation/test/*\")\n\n    outputs = [[], []]\n\n    # Loop through each path\n    for path in paths:\n        # Load data and initialize labels\n        x = load_data(path, \"/images/\")\n        labels = tc.zeros_like(x, dtype=tc.uint8)\n        mark = Pipeline_Dataset(x, path).get_marks()\n\n        # Loop through each axis\n        for axis in [0, 1, 2]:\n            debug_count = 0\n\n            # Rotate input data based on the current axis\n            if axis == 0:\n                x_ = x\n                labels_ = labels\n            elif axis == 1:\n                x_ = x.permute(1, 2, 0)\n                labels_ = labels.permute(1, 2, 0)\n            elif axis == 2:\n                x_ = x.permute(2, 0, 1)\n                labels_ = labels.permute(2, 0, 1)\n\n            # Skip if the input data is RGB and the axis is not 0\n            if x.shape[0] == 3 and axis != 0:\n                break\n\n            # Create dataset and dataloader for processing\n            dataset = Pipeline_Dataset(x_, path)\n            dataloader = DataLoader(dataset, batch_size=1, shuffle=False, num_workers=1)\n            shape = dataset.x.shape[-2:]\n\n            # Generate indices for processing tiles\n            x1_list = np.arange(0, shape[0] + CFG.tile_size - CFG.tile_size + 1, CFG.stride)\n            y1_list = np.arange(0, shape[1] + CFG.tile_size - CFG.tile_size + 1, CFG.stride)\n\n            # Loop through each image in the dataloader\n            for img, index in tqdm(dataloader):\n                # img=(1,C,H,W)\n                img = img.to(\"cuda:0\")\n                img = add_edge(img[0], CFG.tile_size // 2)[None]\n\n                mask_pred = tc.zeros_like(img[:, 0], dtype=tc.float32, device=img.device)\n                mask_count = tc.zeros_like(img[:, 0], dtype=tc.float32, device=img.device)\n\n                indexs = []\n                chip = []\n                \n                # Loop through each tile\n                for y1 in y1_list:\n                    for x1 in x1_list:\n                        x2 = x1 + CFG.tile_size\n                        y2 = y1 + CFG.tile_size\n                        indexs.append([x1 + CFG.drop_egde_pixel, x2 - CFG.drop_egde_pixel,\n                                       y1 + CFG.drop_egde_pixel, y2 - CFG.drop_egde_pixel])\n                        chip.append(img[..., x1:x2, y1:y2])\n\n                # Get predictions from the model\n                y_preds = model.forward(tc.cat(chip)).to(device=0)\n\n                # Weighted Ensemble\n                if axis == CFG.axis_second_model:\n                    y_preds = (0.70 * y_preds + 0.30 * model9.forward(tc.cat(chip)).to(device=0))\n\n                # Adjust for drop_edge_pixel\n                if CFG.drop_egde_pixel:\n                    y_preds = y_preds[..., CFG.drop_egde_pixel:-CFG.drop_egde_pixel,\n                                        CFG.drop_egde_pixel:-CFG.drop_egde_pixel]\n                \n                # Aggregate predictions over tiles\n                for i, (x1, x2, y1, y2) in enumerate(indexs):\n                    mask_pred[..., x1:x2, y1:y2] += y_preds[i]\n                    mask_count[..., x1:x2, y1:y2] += 1\n\n                mask_pred /= mask_count\n\n                # Recover the region after processing\n                mask_pred = mask_pred[..., CFG.tile_size // 2:-CFG.tile_size // 2, CFG.tile_size // 2:-CFG.tile_size // 2]\n\n                # Update labels with the processed mask\n                labels_[index] += (mask_pred[0] * 255 * CFG.axis_w[axis]).to(tc.uint8).cpu()\n\n                # Display debug images if enabled\n                if debug:\n                    debug_count += 1\n                    plt.subplot(121)\n                    plt.imshow(img[0, CFG.in_chans // 2].cpu().detach().numpy())\n                    plt.subplot(122)\n                    plt.imshow(mask_pred[0].cpu().detach().numpy())\n                    plt.show()\n                    if debug_count > 3:\n                        break\n        \n        # Append the labels and marks to the outputs list\n        outputs[0].append(labels)\n        outputs[1].extend(mark)\n    \n    return outputs\n","metadata":{"execution":{"iopub.status.busy":"2024-02-03T11:06:09.30678Z","iopub.execute_input":"2024-02-03T11:06:09.307155Z","iopub.status.idle":"2024-02-03T11:06:09.329108Z","shell.execute_reply.started":"2024-02-03T11:06:09.30712Z","shell.execute_reply":"2024-02-03T11:06:09.328208Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <div style= \"font-family: Cambria; font-weight:bold; letter-spacing: 0px; color:black; font-size:120%; text-align:center;padding:5.0px; background: #FFE2E2; border: 4px solid #a2a8d3\"> Submission </div> ","metadata":{}},{"cell_type":"code","source":"# Check if it's for submission based on the presence of test images\nis_submit = len(glob(\"/kaggle/input/blood-vessel-segmentation/test/kidney_5/images/*.tif\")) != 3\n\n# Get segmentation output and associated ids\noutput, ids = get_output(not is_submit)\n\n# Calculate threshold for binary predictions\nTH = [x.flatten().numpy() for x in output]\nTH = np.concatenate(TH)\nindex = -int(len(TH) * CFG.th_percentile)\nTH: int = np.partition(TH, index)[index]\nprint(TH)\n\n# Read an example image for visualization\nimg = cv2.imread(\"/kaggle/input/blood-vessel-segmentation/test/kidney_5/images/0001.tif\", cv2.IMREAD_GRAYSCALE)\n\n# Initialize a list for submission dataframe\nsubmission_df = []\ndebug_count = 0\n\n# Loop through each prediction and generate RLE encoding\nfor index in range(len(ids)):\n    id = ids[index]\n    i = 0\n\n    # Find the corresponding output based on the index\n    for x in output:\n        if index >= len(x):\n            index -= len(x)\n            i += 1\n        else:\n            break\n\n    # Extract the binary mask based on the threshold\n    mask_pred = (output[i][index] > TH).numpy()\n\n    # Convert the binary mask to the original size\n    mask_pred2 = to_original(mask_pred, img, image_size=1024)\n    mask_pred = mask_pred2.copy()\n\n    # Visualization (if not for submission)\n    if not is_submit:\n        plt.subplot(121)\n        plt.imshow(mask_pred)\n        plt.show()\n        debug_count += 1\n        if debug_count > 6:\n            break\n\n    # Encode the binary mask using Run-Length Encoding\n    rle = rle_encode(mask_pred)\n\n    # Append information to the submission dataframe\n    submission_df.append(\n        pd.DataFrame(data={\n            'id': id,\n            'rle': rle,\n        }, index=[0])\n    )\n\n# Concatenate the submission dataframes and save to a CSV file\nsubmission_df = pd.concat(submission_df)\nsubmission_df.to_csv('submission.csv', index=False)\nsubmission_df.head(6)\n","metadata":{"execution":{"iopub.status.busy":"2024-02-03T11:06:09.330401Z","iopub.execute_input":"2024-02-03T11:06:09.330694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}