{"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":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport json\nimport os\nfrom PIL import Image\nimport random\n# %matplotlib inline","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:11.683503Z","iopub.execute_input":"2023-07-31T13:55:11.683848Z","iopub.status.idle":"2023-07-31T13:55:11.889639Z","shell.execute_reply.started":"2023-07-31T13:55:11.683821Z","shell.execute_reply":"2023-07-31T13:55:11.888658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install --no-index --no-deps /kaggle/input/pycocotools-206/wheels/*.whl","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:11.891472Z","iopub.execute_input":"2023-07-31T13:55:11.891908Z","iopub.status.idle":"2023-07-31T13:55:22.304489Z","shell.execute_reply.started":"2023-07-31T13:55:11.891874Z","shell.execute_reply":"2023-07-31T13:55:22.303223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\" Parts of the U-Net model \"\"\"\n\"\"\"https://github.com/milesial/Pytorch-UNet/blob/master/unet/unet_parts.py\"\"\"\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\n\nclass DoubleConv(nn.Module):\n    \"\"\"(convolution => [BN] => ReLU) * 2\"\"\"\n\n    def __init__(self, in_channels, out_channels):\n        super().__init__()\n        self.double_conv = nn.Sequential(\n            nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(inplace=True)\n        )\n\n    def forward(self, x):\n        return self.double_conv(x)\n\n\nclass Down(nn.Module):\n    \"\"\"Downscaling with maxpool then double conv\"\"\"\n\n    def __init__(self, in_channels, out_channels):\n        super().__init__()\n        self.maxpool_conv = nn.Sequential(\n            nn.MaxPool2d(2),\n            DoubleConv(in_channels, out_channels)\n        )\n\n    def forward(self, x):\n        return self.maxpool_conv(x)\n\n\nclass Up(nn.Module):\n    \"\"\"Upscaling then double conv\"\"\"\n\n    def __init__(self, in_channels, out_channels, bilinear=True):\n        super().__init__()\n\n        # if bilinear, use the normal convolutions to reduce the number of channels\n        if bilinear:\n            self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)#scale_factor=2 将维度扩大为两倍\n        else:\n            self.up = nn.ConvTranspose2d(in_channels//2, in_channels // 2, kernel_size=2, stride=2)  #反卷积后得到的tensor在加上下采样对应的tensor后保持通道数不变 所以要除以2\n\n        self.conv = DoubleConv(in_channels, out_channels)\n\n    def forward(self, x1, x2):\n        x1 = self.up(x1)\n        # input is b*C*H*W\n        diffY = torch.tensor([x2.size()[2] - x1.size()[2]])\n        diffX = torch.tensor([x2.size()[3] - x1.size()[3]])\n\n        x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2,\n                        diffY // 2, diffY - diffY // 2])   #对较小的矩阵进行补0 左右上下各补 相差的一半 最终维度一样可以进行相加操作\n\n        x = torch.cat([x2, x1], dim=1)\n        return self.conv(x)\n\n\nclass OutConv(nn.Module):  #用于最后一层 用通道数进行分类\n    def __init__(self, in_channels, out_channels):\n        super(OutConv, self).__init__()\n        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)\n\n    def forward(self, x):\n        return self.conv(x)","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:22.306409Z","iopub.execute_input":"2023-07-31T13:55:22.306832Z","iopub.status.idle":"2023-07-31T13:55:25.804911Z","shell.execute_reply.started":"2023-07-31T13:55:22.306793Z","shell.execute_reply":"2023-07-31T13:55:25.803811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\" Full assembly of the parts to form the complete network \"\"\"\n\"\"\"Refer https://github.com/milesial/Pytorch-UNet/blob/master/unet/unet_model.py\"\"\"\n\nimport torch.nn.functional as F\n\n# from .unet_parts import *\n\n\nclass Unet(nn.Module):\n    def __init__(self, n_channels=3, n_classes=1, bilinear=True):\n        super(Unet, self).__init__()\n        self.n_channels = n_channels\n        self.n_classes = n_classes\n        self.bilinear = bilinear\n\n        self.inc = DoubleConv(n_channels, 64)\n        self.down1 = Down(64, 128)\n        self.down2 = Down(128, 256)\n        self.down3 = Down(256, 512)\n        self.down4 = Down(512, 512)\n        self.up1 = Up(1024, 256, bilinear)  #输入通道是1024  输出通道是经过了doubelConv之后的通道\n        self.up2 = Up(512, 128, bilinear)\n        self.up3 = Up(256, 64, bilinear)\n        self.up4 = Up(128, 64, bilinear)\n        self.outc = OutConv(64, n_classes)\n        \n        self.sigmoid = torch.sigmoid\n\n    def forward(self, x):\n        x1 = self.inc(x)\n        x2 = self.down1(x1)\n        x3 = self.down2(x2)\n        x4 = self.down3(x3)\n        x5 = self.down4(x4)\n        x = self.up1(x5, x4)\n        x = self.up2(x, x3)\n        x = self.up3(x, x2)\n        x = self.up4(x, x1)\n        logits = self.outc(x)\n        out = self.sigmoid(logits)\n        return out","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:25.807785Z","iopub.execute_input":"2023-07-31T13:55:25.808404Z","iopub.status.idle":"2023-07-31T13:55:25.820534Z","shell.execute_reply.started":"2023-07-31T13:55:25.808366Z","shell.execute_reply":"2023-07-31T13:55:25.819549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import base64\nimport numpy as np\nfrom pycocotools import _mask as coco_mask\nimport typing as t\nimport zlib\nimport os\nimport cv2\nimport matplotlib.pyplot as plt\nimport pandas as pd\n\n\n## Function from https://www.kaggle.com/competitions/hubmap-hacking-the-human-vasculature/overview/evaluation\n\ndef encode_binary_mask(mask: np.ndarray) -> t.Text:\n    \"\"\"Converts a binary mask into OID challenge encoding ascii text.\"\"\"\n\n    # check input mask --\n    if mask.dtype != bool:\n        raise ValueError(\n            \"encode_binary_mask expects a binary mask, received dtype == %s\" %\n            mask.dtype)\n\n    mask = np.squeeze(mask)\n    if len(mask.shape) != 2:\n        raise ValueError(\n            \"encode_binary_mask expects a 2d mask, received shape == %s\" %\n            mask.shape)\n\n    # convert input mask to expected COCO API input --\n    mask_to_encode = mask.reshape(mask.shape[0], mask.shape[1], 1)\n    mask_to_encode = mask_to_encode.astype(np.uint8)\n    mask_to_encode = np.asfortranarray(mask_to_encode)\n\n    # RLE encode mask --\n    encoded_mask = coco_mask.encode(mask_to_encode)[0][\"counts\"]\n\n    # compress and base64 encoding --\n    binary_str = zlib.compress(encoded_mask, zlib.Z_BEST_COMPRESSION)\n    base64_str = base64.b64encode(binary_str)\n    return base64_str","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:25.823278Z","iopub.execute_input":"2023-07-31T13:55:25.823876Z","iopub.status.idle":"2023-07-31T13:55:25.840276Z","shell.execute_reply.started":"2023-07-31T13:55:25.823842Z","shell.execute_reply":"2023-07-31T13:55:25.839333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_pred_string(objs):\n\n    string = \"\"\n    for i, item in enumerate(objs):\n#         print(np.shape(objs))\n#         print(i)\n#         print(np.shape(item))\n        \n        mask = item.astype(bool)\n        encoded_mask = encode_binary_mask(mask).decode(\"utf-8\")\n\n        if i == 0:\n            string += f\"0 1.0 {encoded_mask}\"\n        else:\n            string += f\" 0 1.0 {encoded_mask}\"\n        \n    return string","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:25.841595Z","iopub.execute_input":"2023-07-31T13:55:25.842086Z","iopub.status.idle":"2023-07-31T13:55:25.852302Z","shell.execute_reply.started":"2023-07-31T13:55:25.842053Z","shell.execute_reply":"2023-07-31T13:55:25.851372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def model_predict(model, test_img):\n    mask = None\n    model.eval()\n    with torch.no_grad():\n#         inputs = np.reshape(test_img, (1, 3, 512, 512))\n        inputs = test_img\n        inputs = torch.tensor(inputs).to(torch.float32)\n        inputs = inputs.to(device)\n        mask = model(inputs)\n    return mask","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:25.853696Z","iopub.execute_input":"2023-07-31T13:55:25.854039Z","iopub.status.idle":"2023-07-31T13:55:25.862944Z","shell.execute_reply.started":"2023-07-31T13:55:25.854007Z","shell.execute_reply":"2023-07-31T13:55:25.862062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_instance_list(mask):\n    temp = np.array(mask).astype(np.uint8)\n    num_instances, instance_mask = cv2.connectedComponents(temp)\n\n    # 遍历图像中的每个像素，并根据像素的标识符创建实例掩码\n    instance_masks = []\n    for instance_id in range(1, num_instances):\n        instance_mask_i = (instance_mask == instance_id).astype(np.uint8)\n        instance_masks.append(instance_mask_i)\n    \n    return instance_masks","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:25.864411Z","iopub.execute_input":"2023-07-31T13:55:25.864833Z","iopub.status.idle":"2023-07-31T13:55:25.873945Z","shell.execute_reply.started":"2023-07-31T13:55:25.864795Z","shell.execute_reply":"2023-07-31T13:55:25.872791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_path = \"/kaggle/input/hubmap-hacking-the-human-vasculature/test/\"\nsubmission = pd.DataFrame()\n\ntest_ids = []\nh = []\nw = []\npred_strings = []\nmodel = torch.load(\"/kaggle/input/unetmodel/model-new-100epoch.pth\")\n    \nfor img_id in os.listdir(test_path):\n#     print(img_id)\n    curr_img = cv2.imread(test_path + img_id)\n\n    ## Get id, height, width\n    height, width, channels = curr_img.shape\n    test_ids.append(img_id.split(\".\")[0])\n    h.append(height)\n    w.append(width)\n    \n    ## Get prediction_string\n#     print(curr_img)\n    curr_img = np.transpose(curr_img, (2, 0, 1))\n    curr_img = np.reshape(curr_img, (1, 3, 512, 512))\n    semantic_mask = model_predict(model, curr_img)\n    semantic_mask = semantic_mask.cpu()\n    instance_masks = get_instance_list(semantic_mask[0][0])\n#     print(instance_masks)\n    pred_strings.append(get_pred_string(instance_masks))\n\nsubmission[\"id\"] = test_ids\nsubmission[\"height\"] = h\nsubmission[\"width\"] = w\nsubmission[\"prediction_string\"] = pred_strings\nsubmission.set_index(\"id\", inplace=True)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:25.875360Z","iopub.execute_input":"2023-07-31T13:55:25.875799Z","iopub.status.idle":"2023-07-31T13:55:34.419349Z","shell.execute_reply.started":"2023-07-31T13:55:25.875767Z","shell.execute_reply":"2023-07-31T13:55:34.418366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(semantic_mask[0][0],cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:56:18.494488Z","iopub.execute_input":"2023-07-31T13:56:18.495201Z","iopub.status.idle":"2023-07-31T13:56:18.783437Z","shell.execute_reply.started":"2023-07-31T13:56:18.495165Z","shell.execute_reply":"2023-07-31T13:56:18.782492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_strings","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:34.422506Z","iopub.execute_input":"2023-07-31T13:55:34.423504Z","iopub.status.idle":"2023-07-31T13:55:34.430338Z","shell.execute_reply.started":"2023-07-31T13:55:34.423469Z","shell.execute_reply":"2023-07-31T13:55:34.428831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv(\"submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2023-07-31T13:55:34.432408Z","iopub.execute_input":"2023-07-31T13:55:34.433384Z","iopub.status.idle":"2023-07-31T13:55:34.456148Z","shell.execute_reply.started":"2023-07-31T13:55:34.433314Z","shell.execute_reply":"2023-07-31T13:55:34.453942Z"},"trusted":true},"execution_count":null,"outputs":[]}]}