{"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":"from glob import glob\nimport pandas as pd\nimport json\nfrom torchvision import models\nfrom collections import OrderedDict\nfrom torch.nn.functional import relu\nimport numpy as np\nimport matplotlib as mpl\nimport matplotlib.pyplot as plt\nimport torch\nimport cv2\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision.transforms import transforms\nfrom PIL import Image\nimport os\nfrom skimage.draw import polygon2mask\nfrom matplotlib.patches import Polygon\nimport torch.optim as optim\nimport time\nfrom tqdm import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-08-13T19:18:29.746045Z","iopub.execute_input":"2023-08-13T19:18:29.746450Z","iopub.status.idle":"2023-08-13T19:18:29.755845Z","shell.execute_reply.started":"2023-08-13T19:18:29.746406Z","shell.execute_reply":"2023-08-13T19:18:29.753990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Path Configs ","metadata":{}},{"cell_type":"code","source":"base_path = \"/kaggle/input/hubmap-hacking-the-human-vasculature/\"\nimages_folder = base_path + \"/train/\"\nlabels_path = base_path + \"/polygons.jsonl\"\nmetadata_path = base_path + \"/tile_meta.csv\"","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:18:29.757842Z","iopub.execute_input":"2023-08-13T19:18:29.758695Z","iopub.status.idle":"2023-08-13T19:18:29.770527Z","shell.execute_reply.started":"2023-08-13T19:18:29.758657Z","shell.execute_reply":"2023-08-13T19:18:29.769618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = []\nwith open(labels_path, 'r') as file:\n    for line in file:\n        item = json.loads(line)\n        data.append(item)\n\ndf = pd.DataFrame(data)\ndf.head(1)","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:18:29.773642Z","iopub.execute_input":"2023-08-13T19:18:29.773948Z","iopub.status.idle":"2023-08-13T19:18:33.173870Z","shell.execute_reply.started":"2023-08-13T19:18:29.773925Z","shell.execute_reply":"2023-08-13T19:18:33.172885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset Creation","metadata":{}},{"cell_type":"code","source":"class HubMap_Dataset(Dataset):\n    \n    def is_dataset_1_file(self, metadata_file, file_name):\n        df_tile = pd.read_csv(metadata_file)\n        dataset_1_files = df_tile[df_tile[\"dataset\"]==1]\n        files = dataset_1_files[\"id\"].tolist()\n        if file_name in files:\n            return True\n        else:\n            return False\n    \n    def __init__(self, img_path, labels_file, metadata_file):\n        self.json_labels = []    \n        self.metadata_file = metadata_file\n        self.image_dir = img_path\n        with open(labels_file, 'r') as json_file:\n            for line in json_file:\n                temp = json.loads(line)\n                flag = self.is_dataset_1_file(self.metadata_file, temp[\"id\"])\n                if flag:\n                    self.json_labels.append(json.loads(line))\n                \n    def __len__(self):\n        return len(self.json_labels)\n\n    def __getitem__(self, idx):\n        image_path = self.image_dir + \"/\" + self.json_labels[idx][\"id\"] + \".tif\"\n        img_id = self.json_labels[idx][\"id\"]\n        image = Image.open(image_path)\n        \n        \n        boxes = []\n        labels = []\n        masks = []\n        all_masked = np.zeros((512, 512), dtype=np.float32)\n        all_filled_masks = np.zeros((512, 512), dtype=np.float32)\n        filled_masks = []\n        for annot in self.json_labels[idx][\"annotations\"]:\n            if annot['type'] == \"blood_vessel\":\n                coordinates = np.array(annot[\"coordinates\"])\n                temp_filled_mask = np.zeros((512, 512), dtype=np.float32)\n                all_filled_masks = cv2.fillPoly(all_filled_masks, [coordinates], 1)\n                \n        image = np.array(image)\n        image = torch.tensor(np.array(image/255.0), dtype=torch.float32)\n        \n        return image, all_filled_masks, img_id\n\n","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:18:33.177104Z","iopub.execute_input":"2023-08-13T19:18:33.177387Z","iopub.status.idle":"2023-08-13T19:18:33.190706Z","shell.execute_reply.started":"2023-08-13T19:18:33.177363Z","shell.execute_reply":"2023-08-13T19:18:33.189728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = HubMap_Dataset(img_path=images_folder, labels_file=labels_path, metadata_file=metadata_path)","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:18:51.979328Z","iopub.execute_input":"2023-08-13T19:18:51.979699Z","iopub.status.idle":"2023-08-13T19:19:10.471415Z","shell.execute_reply.started":"2023-08-13T19:18:51.979666Z","shell.execute_reply":"2023-08-13T19:19:10.470222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_set, val_set = torch.utils.data.random_split(dataset, [360, 62])","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:19:10.472854Z","iopub.execute_input":"2023-08-13T19:19:10.473228Z","iopub.status.idle":"2023-08-13T19:19:10.493416Z","shell.execute_reply.started":"2023-08-13T19:19:10.473195Z","shell.execute_reply":"2023-08-13T19:19:10.492529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Random Plots","metadata":{}},{"cell_type":"code","source":"sample = dataset[0]\nall_masks = sample[1]\nimage = sample[0]\nplt.imshow(all_masks)","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:19:10.623817Z","iopub.execute_input":"2023-08-13T19:19:10.624761Z","iopub.status.idle":"2023-08-13T19:19:10.933933Z","shell.execute_reply.started":"2023-08-13T19:19:10.624726Z","shell.execute_reply":"2023-08-13T19:19:10.932959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training Phase","metadata":{}},{"cell_type":"markdown","source":"- ### Model","metadata":{"execution":{"iopub.status.busy":"2023-08-13T18:42:18.419068Z","iopub.execute_input":"2023-08-13T18:42:18.419975Z","iopub.status.idle":"2023-08-13T18:42:18.427271Z","shell.execute_reply.started":"2023-08-13T18:42:18.419928Z","shell.execute_reply":"2023-08-13T18:42:18.425819Z"}}},{"cell_type":"code","source":"class UNet(nn.Module):\n\n    def __init__(self, in_channels=3, out_channels=1, init_features=32):\n        super(UNet, self).__init__()\n\n        features = init_features\n        self.encoder1 = UNet._block(in_channels, features, name=\"enc1\")\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.encoder2 = UNet._block(features, features * 2, name=\"enc2\")\n        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.encoder3 = UNet._block(features * 2, features * 4, name=\"enc3\")\n        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.encoder4 = UNet._block(features * 4, features * 8, name=\"enc4\")\n        self.pool4 = nn.MaxPool2d(kernel_size=2, stride=2)\n\n        self.bottleneck = UNet._block(features * 8, features * 16, name=\"bottleneck\")\n\n        self.upconv4 = nn.ConvTranspose2d(\n            features * 16, features * 8, kernel_size=2, stride=2\n        )\n        self.decoder4 = UNet._block((features * 8) * 2, features * 8, name=\"dec4\")\n        self.upconv3 = nn.ConvTranspose2d(\n            features * 8, features * 4, kernel_size=2, stride=2\n        )\n        self.decoder3 = UNet._block((features * 4) * 2, features * 4, name=\"dec3\")\n        self.upconv2 = nn.ConvTranspose2d(\n            features * 4, features * 2, kernel_size=2, stride=2\n        )\n        self.decoder2 = UNet._block((features * 2) * 2, features * 2, name=\"dec2\")\n        self.upconv1 = nn.ConvTranspose2d(\n            features * 2, features, kernel_size=2, stride=2\n        )\n        self.decoder1 = UNet._block(features * 2, features, name=\"dec1\")\n\n        self.conv = nn.Conv2d(\n            in_channels=features, out_channels=out_channels, kernel_size=1\n        )\n\n    def forward(self, x):\n        enc1 = self.encoder1(x)\n        enc2 = self.encoder2(self.pool1(enc1))\n        enc3 = self.encoder3(self.pool2(enc2))\n        enc4 = self.encoder4(self.pool3(enc3))\n\n        bottleneck = self.bottleneck(self.pool4(enc4))\n\n        dec4 = self.upconv4(bottleneck)\n        dec4 = torch.cat((dec4, enc4), dim=1)\n        dec4 = self.decoder4(dec4)\n        dec3 = self.upconv3(dec4)\n        dec3 = torch.cat((dec3, enc3), dim=1)\n        dec3 = self.decoder3(dec3)\n        dec2 = self.upconv2(dec3)\n        dec2 = torch.cat((dec2, enc2), dim=1)\n        dec2 = self.decoder2(dec2)\n        dec1 = self.upconv1(dec2)\n        dec1 = torch.cat((dec1, enc1), dim=1)\n        dec1 = self.decoder1(dec1)\n        return torch.sigmoid(self.conv(dec1))\n\n    @staticmethod\n    def _block(in_channels, features, name):\n        return nn.Sequential(\n            OrderedDict(\n                [\n                    (\n                        name + \"conv1\",\n                        nn.Conv2d(\n                            in_channels=in_channels,\n                            out_channels=features,\n                            kernel_size=3,\n                            padding=1,\n                            bias=False,\n                        ),\n                    ),\n                    (name + \"norm1\", nn.BatchNorm2d(num_features=features)),\n                    (name + \"relu1\", nn.ReLU(inplace=True)),\n                    (\n                        name + \"conv2\",\n                        nn.Conv2d(\n                            in_channels=features,\n                            out_channels=features,\n                            kernel_size=3,\n                            padding=1,\n                            bias=False,\n                        ),\n                    ),\n                    (name + \"norm2\", nn.BatchNorm2d(num_features=features)),\n                    (name + \"relu2\", nn.ReLU(inplace=True)),\n                ]\n            )\n        )","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:19:59.760891Z","iopub.execute_input":"2023-08-13T19:19:59.761308Z","iopub.status.idle":"2023-08-13T19:19:59.783113Z","shell.execute_reply.started":"2023-08-13T19:19:59.761273Z","shell.execute_reply":"2023-08-13T19:19:59.782041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(device)\n\ntrain_dl = DataLoader(train_set, batch_size=8, shuffle=True)\nval_dl = DataLoader(val_set, batch_size=8, shuffle=True)\ncriterion = nn.BCELoss().to(device)\n\nmodel = UNet()\n# model = smp.Unet()\nparams = [p for p in model.parameters() if p.requires_grad]\noptimizer = optim.Adam(params, lr=0.001)\nnum_epochs = 20\n\nmodel.to(device);","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:20:07.909069Z","iopub.execute_input":"2023-08-13T19:20:07.909919Z","iopub.status.idle":"2023-08-13T19:20:10.771420Z","shell.execute_reply.started":"2023-08-13T19:20:07.909886Z","shell.execute_reply":"2023-08-13T19:20:10.770415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.train()\n# num_epochs = 2\n\nfor epoch in range(num_epochs):\n    running_loss = 0.0\n    \n    for data in tqdm(train_dl):        \n        optimizer.zero_grad()\n\n        images = data[0].permute(0,3,1,2).to(device)\n        masks = data[1].unsqueeze(dim=1).to(device)\n\n        output = model(images)\n        loss = criterion(output, masks)\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item()\n    \n    with torch.no_grad():\n        running_val_loss = 0.0\n\n        for data in tqdm(val_dl):        \n            images = data[0].permute(0,3,1,2).to(device)\n            masks = data[1].unsqueeze(dim=1).to(device)\n\n            output = model(images)\n            loss = criterion(output, masks)\n\n            running_val_loss += loss.item()\n\n    \n    print(\"Training Loss : \", round(running_loss/len(train_dl),3))\n    print(\"Validation Loss : \", round(running_val_loss/len(val_dl),3))\n","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:20:36.724867Z","iopub.execute_input":"2023-08-13T19:20:36.725431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Testing","metadata":{}},{"cell_type":"markdown","source":"- ### Visual Results","metadata":{}},{"cell_type":"code","source":"model.eval()\n\nfor temp in val_set:\n    fig, axs = plt.subplots(nrows=1, ncols=2,)\n    pred = model(temp[0].permute(2,0,1).unsqueeze(0).to(device))\n    mask = pred.squeeze().cpu().detach().numpy()\n    \n    filtered_mask = np.zeros((512,512))\n    indexes= np.where(mask>0.5)\n    filtered_mask[indexes[0],indexes[1]] = 1\n\n    print(temp[-1])\n    \n    axs[0].imshow(temp[1])\n    axs[0].set_title(\"Original\")\n    axs[1].imshow(filtered_mask)\n    axs[1].set_title(\"Predicted\")\n    plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-08-13T19:16:58.515402Z","iopub.execute_input":"2023-08-13T19:16:58.517506Z","iopub.status.idle":"2023-08-13T19:17:24.998603Z","shell.execute_reply.started":"2023-08-13T19:16:58.517444Z","shell.execute_reply":"2023-08-13T19:17:24.997484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}