{"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":"gpu","dataSources":[{"sourceId":61446,"databundleVersionId":6962461,"sourceType":"competition"},{"sourceId":7122490,"sourceType":"datasetVersion","datasetId":4108361},{"sourceId":7141413,"sourceType":"datasetVersion","datasetId":4121860},{"sourceId":7149637,"sourceType":"datasetVersion","datasetId":4127856},{"sourceId":7150171,"sourceType":"datasetVersion","datasetId":4128229},{"sourceId":150248402,"sourceType":"kernelVersion"}],"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Prepare","metadata":{}},{"cell_type":"code","source":"!python -m pip install --no-index --find-links=/kaggle/input/pip-download-for-segmentation-models-pytorch segmentation-models-pytorch","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-12-11T05:03:21.268082Z","iopub.execute_input":"2023-12-11T05:03:21.268353Z","iopub.status.idle":"2023-12-11T05:03:40.193397Z","shell.execute_reply.started":"2023-12-11T05:03:21.268316Z","shell.execute_reply":"2023-12-11T05:03:40.192470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport random\nfrom tqdm import tqdm\nimport pandas as pd\nimport numpy as np\nfrom glob import glob\nimport gc\nimport time\nfrom collections import defaultdict\nimport  matplotlib.pyplot as plt\nfrom matplotlib.patches import Rectangle\nimport copy\nimport cv2\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom torch.optim import lr_scheduler\nfrom torch.cuda import amp\nimport torch.optim as optim\nimport albumentations as A\nimport segmentation_models_pytorch as smp","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:40.195334Z","iopub.execute_input":"2023-12-11T05:03:40.195691Z","iopub.status.idle":"2023-12-11T05:03:47.645399Z","shell.execute_reply.started":"2023-12-11T05:03:40.195662Z","shell.execute_reply":"2023-12-11T05:03:47.644624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_img(path):\n    img = cv2.imread(path, cv2.IMREAD_UNCHANGED)\n    img = np.tile(img[...,None], [1, 1, 3]) # gray to rgb\n    img = img.astype('float32') # original is uint16\n    mx = np.max(img)\n    if mx:\n        img/=mx # scale image to [0, 1]\n    return img\n\ndef load_msk(path):\n    msk = cv2.imread(path, cv2.IMREAD_UNCHANGED)\n    msk = msk.astype('float32')\n    msk/=255.0\n    return msk","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:47.646590Z","iopub.execute_input":"2023-12-11T05:03:47.646857Z","iopub.status.idle":"2023-12-11T05:03:47.652815Z","shell.execute_reply.started":"2023-12-11T05:03:47.646835Z","shell.execute_reply":"2023-12-11T05:03:47.651957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BuildDataset(torch.utils.data.Dataset):\n    def __init__(self, img_paths, msk_paths=[], transforms=None):\n        self.img_paths  = img_paths\n        self.msk_paths  = msk_paths\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.img_paths)\n    \n    def __getitem__(self, index):\n        img_path  = self.img_paths[index]\n        img = load_img(img_path)\n        \n        if len(self.msk_paths)>0:\n            msk_path = self.msk_paths[index]\n            msk = load_msk(msk_path)\n            if self.transforms:\n                data = self.transforms(image=img, mask=msk)\n                img  = data['image']\n                msk  = data['mask']\n            img = np.transpose(img, (2, 0, 1))\n            return torch.tensor(img), torch.tensor(msk)\n        else:\n            orig_size = img.shape\n            if self.transforms:\n                data = self.transforms(image=img)\n                img  = data['image']\n            img = np.transpose(img, (2, 0, 1))\n            return torch.tensor(img), torch.tensor(np.array([orig_size[0], orig_size[1]]))","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:47.654810Z","iopub.execute_input":"2023-12-11T05:03:47.655123Z","iopub.status.idle":"2023-12-11T05:03:47.666929Z","shell.execute_reply.started":"2023-12-11T05:03:47.655096Z","shell.execute_reply":"2023-12-11T05:03:47.666033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATASET_FOLDER = \"/kaggle/input/blood-vessel-segmentation\"\nls_images = glob(os.path.join(DATASET_FOLDER, \"test\", \"*\", \"images\", \"*.tif\"))\nprint(f\"found images: {len(ls_images)}\")\n\n# ===============================================================================\n# /kaggle/input/blood-vessel-segmentation/train/kidney_1_dense\n# /kaggle/input/blood-vessel-segmentation/train/kidney_2\n# sanity check\nbase_path = '/kaggle/input/blood-vessel-segmentation/train'  \ntrain_base_path = '/kaggle/input/patched-sennet-kidney-1-data'\nval_img = \"kidney_2\"#'kidney_3_sparse',kidney_1_dense\nval_mask = \"kidney_2\"#'kidney_3_sparse',kidney_1_dense\n\nimages_val_path = os.path.join(base_path, val_img, 'images')\nlabels_val_path = os.path.join(base_path, val_mask, 'labels')\nimage_val_files = sorted([os.path.join(images_val_path, f) for f in os.listdir(images_val_path) if f.endswith('.tif')])\nlabel_val_files = sorted([os.path.join(labels_val_path, f) for f in os.listdir(labels_val_path) if f.endswith('.tif')])","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:47.668050Z","iopub.execute_input":"2023-12-11T05:03:47.668375Z","iopub.status.idle":"2023-12-11T05:03:47.965973Z","shell.execute_reply.started":"2023-12-11T05:03:47.668343Z","shell.execute_reply":"2023-12-11T05:03:47.965277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = BuildDataset(ls_images, [], transforms=None)\nsanity_dataset = BuildDataset(image_val_files,label_val_files,transforms=None )\nsanity_loader = DataLoader(sanity_dataset, batch_size = 1, num_workers=0, shuffle=False, pin_memory=True)\ntest_loader = DataLoader(test_dataset, batch_size = 1, num_workers=0, shuffle=False, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:47.966880Z","iopub.execute_input":"2023-12-11T05:03:47.967111Z","iopub.status.idle":"2023-12-11T05:03:47.972609Z","shell.execute_reply.started":"2023-12-11T05:03:47.967090Z","shell.execute_reply":"2023-12-11T05:03:47.971706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# resnext50_32x4d\n# resnet50\n\n#/kaggle/input/resnext-800/best_epoch800.bin\n#/kaggle/input/renext-patch-50d/renext_patch.bin\nclass CFG:\n    backbone = \"resnext50_32x4d\"\n    bin_path = '/kaggle/input/resnext-1-2-1-before-final-report/resnext_beforefinalReport_1_2_1.bin'\n    test_batchsize = 1\n    img_size = [800,800]\n    remove_area = 30\n    threshold = 0.9\n    over_lap = 0.1\n    num_classes   = 1\n    patch_size = 800\n    device        = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n#     data_transforms = {\n#         \"train\": A.Compose([\n#             A.Resize(*img_size, interpolation=cv2.INTER_NEAREST),\n#             A.HorizontalFlip(p=0.5),\n#             A.VerticalFlip(p=0.5),\n#         ], p=1.0),\n        \n#         \"valid\": A.Compose([\n#             A.Resize(*img_size, interpolation=cv2.INTER_NEAREST),\n#         ], p=1.0)\n#     }\n    ","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:47.973663Z","iopub.execute_input":"2023-12-11T05:03:47.973954Z","iopub.status.idle":"2023-12-11T05:03:48.007020Z","shell.execute_reply.started":"2023-12-11T05:03:47.973924Z","shell.execute_reply":"2023-12-11T05:03:48.006217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# for new way remember to make batch_size to 1","metadata":{}},{"cell_type":"code","source":"def build_model(backbone, num_classes, device):\n    model = smp.Unet(\n        encoder_name=backbone,      # choose encoder, e.g. mobilenet_v2 or efficientnet-b7\n        encoder_weights=None,     # use `imagenet` pre-trained weights for encoder initialization\n        in_channels=3,                  # model input channels (1 for gray-scale images, 3 for RGB, etc.)\n        classes=num_classes,        # model output channels (number of classes in your dataset)\n        activation=None,\n    )\n    model.to(device)\n    return model\n\ndef load_model(backbone, num_classes, device, path):\n    model = build_model(backbone, num_classes, device)\n    model.load_state_dict(torch.load(path))\n    model.eval()\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:48.008075Z","iopub.execute_input":"2023-12-11T05:03:48.008351Z","iopub.status.idle":"2023-12-11T05:03:48.029868Z","shell.execute_reply.started":"2023-12-11T05:03:48.008329Z","shell.execute_reply":"2023-12-11T05:03:48.029025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel = load_model(CFG.backbone, \n                   1, \n                   CFG.device, \n                   CFG.bin_path)","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:48.030824Z","iopub.execute_input":"2023-12-11T05:03:48.031081Z","iopub.status.idle":"2023-12-11T05:03:53.713014Z","shell.execute_reply.started":"2023-12-11T05:03:48.031059Z","shell.execute_reply":"2023-12-11T05:03:53.712178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = img.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    rle = ' '.join(str(x) for x in runs)\n    if rle == '':\n        rle = '1 0'\n    return rle","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:53.717111Z","iopub.execute_input":"2023-12-11T05:03:53.717711Z","iopub.status.idle":"2023-12-11T05:03:53.724220Z","shell.execute_reply.started":"2023-12-11T05:03:53.717680Z","shell.execute_reply":"2023-12-11T05:03:53.722856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef remove_small_objects(img, min_size):\n    # Find all connected components (labels)\n    num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(img, connectivity=8)\n\n    # Create a mask where small objects are removed\n    new_img = np.zeros_like(img)\n    for label in range(1, num_labels):\n        if stats[label, cv2.CC_STAT_AREA] >= min_size:\n            new_img[labels == label] = 255\n\n    return new_img","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:53.725628Z","iopub.execute_input":"2023-12-11T05:03:53.726306Z","iopub.status.idle":"2023-12-11T05:03:53.745333Z","shell.execute_reply.started":"2023-12-11T05:03:53.726268Z","shell.execute_reply":"2023-12-11T05:03:53.744431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def patch_image(img, patch_size, model = None, over_lap=0.2):\n    \"\"\"\n    Splits the image into patches with overlap.\n\n    \"\"\"\n    shape = img.shape\n\n    height, width = shape[2],shape[3]\n\n    stride = patch_size * (1 - over_lap)\n    num_patches = np.ceil(np.array([height, width]) / stride).astype(np.int64)\n    \n    starts = [np.int64(np.linspace(0, width - patch_size, num_patches[1])),\n              np.int64(np.linspace(0, height - patch_size, num_patches[0]))]\n    patches = []\n    for y in starts[1]:\n        for x in starts[0]:\n            if model != None: \n                patch_img = img[:,:,y:y + patch_size, x:x + patch_size]\n#                 print(type(patch_img),\" and shape is \",patch_img.shape)\n#                 print(f'inside the patch function: size of patched image: {np.shape(patch_img)}')\n                patches.append(patch_img)\n    patches = torch.cat(patches,dim = 0)\n    pred = model(patches)\n    return pred\n\n\ndef combine_patches_torch(patches, original_shape, patch_size, over_lap=0.1):\n    height, width = original_shape[2],original_shape[3]\n    stride = int(patch_size * (1 - over_lap))\n    combined = np.zeros((height, width), dtype=np.float32)\n    weight = np.zeros((height, width), dtype=np.float32)\n\n    num_patches_y = np.ceil(height / stride).astype(np.int64)\n    num_patches_x = np.ceil(width / stride).astype(np.int64)\n\n    starts_y = np.linspace(0, height - patch_size, num_patches_y).astype(np.int64)\n    starts_x = np.linspace(0, width - patch_size, num_patches_x).astype(np.int64)\n\n    patch_idx = 0\n    for y in starts_y:\n        for x in starts_x:\n            \n            patch = patches[patch_idx].detach().cpu()\n            patch = patch.numpy().astype(np.float32)\n#             print(f'inside the combine function: type of combine = {type(combined)}, shape of patches = {np.shape(patch)}')\n            # with torch, I cannot add different sized tensor together \n            combined[y:y + patch_size, x:x + patch_size] += patch.squeeze()\n            weight[y:y + patch_size, x:x + patch_size] += 1.0\n            patch_idx += 1\n\n    # Avoid division by zero\n    weight[weight == 0] = 1.0\n#     combined = combined / weight\n    combined = torch.from_numpy(combined)\n    combined = combined.unsqueeze(0).unsqueeze(0)\n    \n    return combined","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:53.746627Z","iopub.execute_input":"2023-12-11T05:03:53.746913Z","iopub.status.idle":"2023-12-11T05:03:53.761466Z","shell.execute_reply.started":"2023-12-11T05:03:53.746888Z","shell.execute_reply":"2023-12-11T05:03:53.760544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# inference for resize model","metadata":{}},{"cell_type":"code","source":"# rles = []\n# pbar = tqdm(enumerate(test_loader), total=len(test_loader), desc='Inference ')\n# for step, (images, shapes) in pbar:\n# #     print(np.shape(images))\n#     shapes = shapes.numpy()\n#     images = images.to(device, dtype=torch.float)\n#     with torch.no_grad():\n#         preds = model(images)\n#         print(f'shape of raw prediction {np.shape(preds)}')\n# #         preds = (nn.Sigmoid()(preds)>0.5).double()\n#         preds = (preds>CFG.threshold).float()\n#         print(f'shape of prediction after sigmoid {np.shape(preds)}')\n#     preds = preds.cpu().numpy().astype(np.uint8)\n\n#     for pred, shape in zip(preds, shapes):\n#         pred = cv2.resize(pred[0], (shape[1], shape[0]), cv2.INTER_NEAREST)\n#         rle = rle_encode_submission(remove_small_objects(pred,30))\n#         rles.append(rle)","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:53.762713Z","iopub.execute_input":"2023-12-11T05:03:53.763050Z","iopub.status.idle":"2023-12-11T05:03:53.774599Z","shell.execute_reply.started":"2023-12-11T05:03:53.763016Z","shell.execute_reply":"2023-12-11T05:03:53.773708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference for patch model","metadata":{}},{"cell_type":"code","source":"rles = []\npbar = tqdm(enumerate(test_loader), total=len(test_loader), desc='Inference ')\nfor step, (images, shapes) in pbar:\n#     print(np.shape(images))\n    shapes = shapes.numpy()\n    images = images.to(device, dtype=torch.float)\n    with torch.no_grad():\n        ori_shape = images.shape\n#         print(ori_shape)\n#         print(np.shape(images))\n        patches = patch_image(images,patch_size = CFG.patch_size,model = model,over_lap = CFG.over_lap)\n        pred  = combine_patches_torch(patches,ori_shape,patch_size = CFG.patch_size,over_lap = CFG.over_lap )\n        pred = pred.cpu().numpy()\n        pred = ((pred>CFG.threshold)*255).astype(np.uint8)\n    pred = pred.squeeze()\n#     print(f'shape of raw prediction {np.shape(pred)}')\n    rle = rle_encode(remove_small_objects(pred,CFG.remove_area))\n    rles.append(rle)","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:03:53.775946Z","iopub.execute_input":"2023-12-11T05:03:53.776307Z","iopub.status.idle":"2023-12-11T05:04:00.338984Z","shell.execute_reply.started":"2023-12-11T05:03:53.776272Z","shell.execute_reply":"2023-12-11T05:04:00.338015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Sanity check","metadata":{}},{"cell_type":"code","source":"sample_ids = [random.randint(0, len(sanity_dataset)) for _ in range(20)]\nfor id in sample_ids:\n    images, mask = sanity_dataset[id]\n    images = images.to(device, dtype=torch.float)\n    with torch.no_grad():\n        \n        print(np.shape(images))\n        image = images.unsqueeze(0)\n        ori_shape = image.shape\n        patches = patch_image(image,patch_size = CFG.patch_size,model = model,over_lap = CFG.over_lap)\n        print(patches.shape)\n        pred  = combine_patches_torch(patches,ori_shape,patch_size = CFG.patch_size,over_lap = CFG.over_lap )\n        pred = (nn.Sigmoid()(pred)>.5).float()\n        pred = pred.cpu().numpy().astype(np.uint8)\n        plt.figure(figsize=(9, 4))\n        plt.subplot(1,3,1)\n        image = image.cpu().detach().numpy()\n        image = image.squeeze(0)\n        image = np.transpose(image,(1,2,0))\n        plt.imshow(image)\n        plt.subplot(1,3,2)\n        plt.imshow(mask)\n        plt.subplot(1,3,3)\n        pred = pred.squeeze()\n        plt.imshow(pred)\n        plt.show()\n    \n\n# # for images, shapes in test_loader:\n# # #     print(np.shape(images))\n# #     shapes = shapes.numpy()\n# #     images = images.to(device, dtype=torch.float)\n# #     with torch.no_grad():\n# #         ori_shape = images.shape\n# # #         print(ori_shape)\n# #         image = images[0]\n# #         patches = patch_image(images,512,model = model)\n# #         pred  = combine_patches_torch(patches,ori_shape,512)\n# #         pred = (nn.Sigmoid()(pred)>.5).float()\n# #         pred = pred.cpu().numpy().astype(np.uint8)\n# #         plt.figure(figsize=(9, 4))\n# #         plt.subplot(1,2,1)\n# #         image = image.cpu().detach().numpy()\n# #         image = np.transpose(image,(1,2,0))\n# #         plt.imshow(image)\n# #         plt.subplot(1,2,2)\n# #         pred = pred.squeeze()\n# #         plt.imshow(pred)","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:04:00.340416Z","iopub.execute_input":"2023-12-11T05:04:00.340733Z","iopub.status.idle":"2023-12-11T05:04:26.667646Z","shell.execute_reply.started":"2023-12-11T05:04:00.340705Z","shell.execute_reply":"2023-12-11T05:04:26.666644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ids = []\nfor p_img in tqdm(ls_images):\n    path_ = p_img.split(os.path.sep)\n    # parse the submission ID\n    dataset = path_[-3]\n    slice_id, _ = os.path.splitext(path_[-1])\n    ids.append(f\"{dataset}_{slice_id}\")","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:04:26.668984Z","iopub.execute_input":"2023-12-11T05:04:26.669342Z","iopub.status.idle":"2023-12-11T05:04:26.678713Z","shell.execute_reply.started":"2023-12-11T05:04:26.669307Z","shell.execute_reply":"2023-12-11T05:04:26.677887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame.from_dict({\n    \"id\": ids,\n    \"rle\": rles\n})\nsubmission.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:04:26.679968Z","iopub.execute_input":"2023-12-11T05:04:26.680331Z","iopub.status.idle":"2023-12-11T05:04:26.703190Z","shell.execute_reply.started":"2023-12-11T05:04:26.680298Z","shell.execute_reply":"2023-12-11T05:04:26.702374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2023-12-11T05:04:26.704304Z","iopub.execute_input":"2023-12-11T05:04:26.705024Z","iopub.status.idle":"2023-12-11T05:04:26.720446Z","shell.execute_reply.started":"2023-12-11T05:04:26.704989Z","shell.execute_reply":"2023-12-11T05:04:26.719478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}