{"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":7026035,"sourceType":"datasetVersion","datasetId":4011732},{"sourceId":151009453,"sourceType":"kernelVersion"}],"dockerImageVersionId":30588,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!python -m pip install --no-index --find-links=/kaggle/input/pip-download-for-segmentation-models-pytorch segmentation-models-pytorch","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:31:49.359548Z","iopub.execute_input":"2023-11-25T06:31:49.359925Z","iopub.status.idle":"2023-11-25T06:32:10.239149Z","shell.execute_reply.started":"2023-11-25T06:31:49.359895Z","shell.execute_reply":"2023-11-25T06:32:10.238003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:10.241415Z","iopub.execute_input":"2023-11-25T06:32:10.241837Z","iopub.status.idle":"2023-11-25T06:32:13.608492Z","shell.execute_reply.started":"2023-11-25T06:32:10.241802Z","shell.execute_reply":"2023-11-25T06:32:13.607588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.is_available()","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:13.609448Z","iopub.execute_input":"2023-11-25T06:32:13.609879Z","iopub.status.idle":"2023-11-25T06:32:13.690101Z","shell.execute_reply.started":"2023-11-25T06:32:13.609850Z","shell.execute_reply":"2023-11-25T06:32:13.689060Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport cv2\nfrom glob import glob\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport albumentations as A\nimport segmentation_models_pytorch as smp","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:13.692502Z","iopub.execute_input":"2023-11-25T06:32:13.692816Z","iopub.status.idle":"2023-11-25T06:32:18.769456Z","shell.execute_reply.started":"2023-11-25T06:32:13.692789Z","shell.execute_reply":"2023-11-25T06:32:18.768423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CFG:\n    seed          = 42\n    debug         = False # set debug=False for Full Training\n    exp_name      = 'unet_resnet50_1'\n    comment       = 'unet_resnet50_1-512x512'\n    model_name    = 'Unet'\n    backbone      = 'resnet50'\n    ckpt_path     = '/kaggle/input/blood-vessel-segmentation-weight/best_epoch_20_11.bin'\n    valid_bs      = 32\n    img_size      = [512, 512]\n    num_classes   = 1\n    thresh        = 0.996\n    min_size      = 30\n    device        = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n    \n    data_transforms = {\n        \"train\": A.Compose([\n            A.Resize(*img_size, interpolation=cv2.INTER_NEAREST),\n            A.HorizontalFlip(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    }","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:18.770977Z","iopub.execute_input":"2023-11-25T06:32:18.772021Z","iopub.status.idle":"2023-11-25T06:32:18.780384Z","shell.execute_reply.started":"2023-11-25T06:32:18.771979Z","shell.execute_reply":"2023-11-25T06:32:18.779329Z"},"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\n\ndef 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\n\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] = 1\n\n    return new_img","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:18.781632Z","iopub.execute_input":"2023-11-25T06:32:18.782017Z","iopub.status.idle":"2023-11-25T06:32:18.793965Z","shell.execute_reply.started":"2023-11-25T06:32:18.781985Z","shell.execute_reply":"2023-11-25T06:32:18.793096Z"},"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-11-25T06:32:18.795329Z","iopub.execute_input":"2023-11-25T06:32:18.795995Z","iopub.status.idle":"2023-11-25T06:32:18.805924Z","shell.execute_reply.started":"2023-11-25T06:32:18.795961Z","shell.execute_reply":"2023-11-25T06:32:18.805030Z"},"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)}\")","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:18.807044Z","iopub.execute_input":"2023-11-25T06:32:18.807377Z","iopub.status.idle":"2023-11-25T06:32:18.832067Z","shell.execute_reply.started":"2023-11-25T06:32:18.807350Z","shell.execute_reply":"2023-11-25T06:32:18.831229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = BuildDataset(ls_images, [], transforms=CFG.data_transforms['valid'])\ntest_loader = DataLoader(test_dataset, batch_size=CFG.valid_bs, num_workers=0, shuffle=False, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:18.833154Z","iopub.execute_input":"2023-11-25T06:32:18.833499Z","iopub.status.idle":"2023-11-25T06:32:18.838140Z","shell.execute_reply.started":"2023-11-25T06:32:18.833474Z","shell.execute_reply":"2023-11-25T06:32:18.837202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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='sigmoid',\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-11-25T06:32:18.841049Z","iopub.execute_input":"2023-11-25T06:32:18.841615Z","iopub.status.idle":"2023-11-25T06:32:18.848118Z","shell.execute_reply.started":"2023-11-25T06:32:18.841588Z","shell.execute_reply":"2023-11-25T06:32:18.847313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def post_processing(image):\n    # print(torch.max(image))\n    image = image/(torch.max(image) + 1e-6)\n    # print(image)\n    return image","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:18.849092Z","iopub.execute_input":"2023-11-25T06:32:18.849420Z","iopub.status.idle":"2023-11-25T06:32:18.861352Z","shell.execute_reply.started":"2023-11-25T06:32:18.849394Z","shell.execute_reply":"2023-11-25T06:32:18.860403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = load_model(CFG.backbone, CFG.num_classes, CFG.device, CFG.ckpt_path)","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:18.862569Z","iopub.execute_input":"2023-11-25T06:32:18.863425Z","iopub.status.idle":"2023-11-25T06:32:24.998685Z","shell.execute_reply.started":"2023-11-25T06:32:18.863390Z","shell.execute_reply":"2023-11-25T06:32:24.997843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rles = []\nsigmoid_layer = nn.Sigmoid()\npbar = tqdm(enumerate(test_loader), total=len(test_loader), desc='Inference ')\nfor step, (images, shapes) in pbar:\n    shapes = shapes.numpy()\n    images = images.to(CFG.device, dtype=torch.float)\n    with torch.no_grad():\n        preds = model(images)\n        # preds = post_processing(preds)\n        # print(sigmoid_layer(preds))\n        # print(preds)\n        preds = (preds>CFG.thresh).float()\n        # print(preds)  # .double()\n    preds = preds.cpu().numpy().astype(np.uint8)\n\n    for pred, shape in zip(preds, shapes):\n        # pred*=255\n        pred = cv2.resize(pred[0], (shape[1], shape[0]), cv2.INTER_NEAREST)\n        rle = rle_encode(remove_small_objects(pred, CFG.min_size))\n        # rle = rle_encode(pred)\n        rles.append(rle)","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:25.000189Z","iopub.execute_input":"2023-11-25T06:32:25.000595Z","iopub.status.idle":"2023-11-25T06:32:31.454526Z","shell.execute_reply.started":"2023-11-25T06:32:25.000560Z","shell.execute_reply":"2023-11-25T06:32:31.453529Z"},"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-11-25T06:32:31.455881Z","iopub.execute_input":"2023-11-25T06:32:31.456180Z","iopub.status.idle":"2023-11-25T06:32:31.465224Z","shell.execute_reply.started":"2023-11-25T06:32:31.456153Z","shell.execute_reply":"2023-11-25T06:32:31.464218Z"},"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-11-25T06:32:31.466527Z","iopub.execute_input":"2023-11-25T06:32:31.466838Z","iopub.status.idle":"2023-11-25T06:32:31.480892Z","shell.execute_reply.started":"2023-11-25T06:32:31.466813Z","shell.execute_reply":"2023-11-25T06:32:31.479895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"submission","metadata":{}},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2023-11-25T06:32:31.482142Z","iopub.execute_input":"2023-11-25T06:32:31.482446Z","iopub.status.idle":"2023-11-25T06:32:31.501446Z","shell.execute_reply.started":"2023-11-25T06:32:31.482421Z","shell.execute_reply":"2023-11-25T06:32:31.500418Z"},"trusted":true},"execution_count":null,"outputs":[]}]}