{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.10","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":30892,"databundleVersionId":2715462,"sourceType":"competition"},{"sourceId":7142224,"sourceType":"datasetVersion","datasetId":4122376},{"sourceId":7169157,"sourceType":"datasetVersion","datasetId":4116340,"isSourceIdPinned":true}],"dockerImageVersionId":30512,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install torchmetrics\n!pip install segmentation_models_pytorch\n!pip install albumentations\n!pip install timm\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\nimport glob\n# from glob import glob\nimport cv2\nimport numpy as np\nimport torch.nn.functional as F\nimport torch\nfrom PIL import ImageOps\nfrom PIL.Image import Image\nfrom sympy.physics.control.control_plots import plt\nfrom torch import nn, optim\nfrom torch.utils.data import TensorDataset, DataLoader\nimport torch\nfrom torch.utils.data import Dataset\nfrom torchvision import transforms\nfrom torch.utils.data import Subset\nfrom tqdm import tqdm\nfrom PIL import Image\nimport numpy as np\nimport cv2\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torchmetrics\n# from torchmetrics import Dice, JaccardIndex\n# import segmentation_models_pytorch as smp\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2 # np.array -> torch.tensor\nimport os\nfrom tqdm import tqdm\n\nfrom torchvision.datasets import VOCSegmentation\nimport timm\nimport tqdm\nimport glob\nimport matplotlib.pyplot as plt\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom albumentations.augmentations import transforms\nfrom albumentations.core.composition import Compose, OneOf\nfrom albumentations.augmentations.transforms import RandomGamma\nimport torchmetrics\n# from torchmetrics import Dice, JaccardIndex\nimport segmentation_models_pytorch as smp\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2 # np.array -> torch.tensor\nimport os\nfrom tqdm import tqdm\nimport glob\nfrom torchvision.datasets import VOCSegmentation\nimport timm\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:08:03.830273Z","iopub.execute_input":"2025-05-29T04:08:03.830513Z","iopub.status.idle":"2025-05-29T04:08:52.326056Z","shell.execute_reply.started":"2025-05-29T04:08:03.830492Z","shell.execute_reply":"2025-05-29T04:08:52.325120Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Làm giàu dữ liệu và chuẩn hóa ảnh\ntrainsize = 256\ntrain_transform = A.Compose([\n    A.HorizontalFlip(p=0.5),\n    A.VerticalFlip(p=0.5),\n    A.RandomGamma (gamma_limit=(70, 130), eps=None, always_apply=False, p=0.2),\n    A.RGBShift(p=0.3, r_shift_limit=10, g_shift_limit=10, b_shift_limit=10),\n    A.OneOf([A.Blur(), A.GaussianBlur(), A.GlassBlur(), A.MotionBlur(), A.GaussNoise(), A.Sharpen(), A.MedianBlur(), A.MultiplicativeNoise()], p=0.35),\n    A.CoarseDropout(p=0.2, max_height=15, max_width=15, fill_value=255),\n    A.RandomSnow(snow_point_lower=0.1, snow_point_upper=0.15, brightness_coeff=1.5, p=0.09),\n#     A.RandomShadow(p=0.1),\n    A.ShiftScaleRotate(p=0.15, border_mode=cv2.BORDER_CONSTANT, shift_limit=0.15, scale_limit=0.15),\n    A.RandomCrop(trainsize, trainsize),\n    A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),\n    ToTensorV2(),\n])\n\nval_transform = A.Compose([\n    A.Normalize(mean=(0.485, 0.456, 0.406),std=(0.229, 0.224, 0.225)),\n    ToTensorV2(),\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:09:01.125936Z","iopub.execute_input":"2025-05-29T04:09:01.126751Z","iopub.status.idle":"2025-05-29T04:09:01.133936Z","shell.execute_reply.started":"2025-05-29T04:09:01.126719Z","shell.execute_reply":"2025-05-29T04:09:01.133142Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"# khôi phục ảnh sau khi chuẩn hóa\nclass UnNormalize(object):\n    def __init__(self, mean, std):\n        self.mean = mean\n        self.std = std\n        \n    def __call__(self, tensor):\n        \"\"\"\n        Args:\n            tensor (Tensor): Tensor image of size (C, H, W) to be normalized.\n        Returns:\n            Tensor: Normalized image.\n        \"\"\"\n        for t, m, s in zip(tensor, self.mean, self.std):\n            t.mul_(s).add_(m)\n            # The normalize code -> t.sub_(m).div_(s)\n        return tensor\n    \nunorm = UnNormalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:09:07.325528Z","iopub.execute_input":"2025-05-29T04:09:07.326403Z","iopub.status.idle":"2025-05-29T04:09:07.331465Z","shell.execute_reply.started":"2025-05-29T04:09:07.326370Z","shell.execute_reply":"2025-05-29T04:09:07.330553Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Khởi tạo train dataset\nclass BKpolypDataset(torch.utils.data.Dataset):\n    def __init__(self, dir=\"path/to/data\", transform=None):\n        self.img_path_lst = []\n        self.dir = dir\n        self.transform = transform\n        self.img_path_lst = glob.glob(\"{}/train/train/*\".format(self.dir))\n\n    def __len__(self):\n        return len(self.img_path_lst)\n\n    def read_mask(self, mask_path):\n        image = cv2.imread(mask_path)\n        image = cv2.resize(image, (trainsize, trainsize))\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)\n        # lower boundary RED color range values; Hue (0 - 10)\n        lower1 = np.array([0, 100, 20])\n        upper1 = np.array([10, 255, 255])\n        # upper boundary RED color range values; Hue (160 - 180)\n        lower2 = np.array([160,100,20])\n        upper2 = np.array([179,255,255])\n        lower_mask = cv2.inRange(image, lower1, upper1)\n        upper_mask = cv2.inRange(image, lower2, upper2)\n        red_mask = lower_mask + upper_mask;\n        red_mask[red_mask != 0] = 1\n        # boundary RED color range values; Hue (36 - 70)\n        green_mask = cv2.inRange(image, (36, 25, 25), (70, 255,255))\n        green_mask[green_mask != 0] = 2\n        full_mask = cv2.bitwise_or(red_mask, green_mask)\n        full_mask = full_mask.astype(np.uint8)\n        num_classes = 3\n\n        # Chuyển đổi thành biểu diễn one-hot\n        one_hot_matrix = np.eye(num_classes)[full_mask]\n        return one_hot_matrix\n\n    def __getitem__(self, idx):\n        img_path = self.img_path_lst[idx]\n        image = cv2.imread(img_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        image = cv2.resize(image, (trainsize, trainsize))\n        label_path = img_path.replace(\"train\", \"train_gt\")\n        label = self.read_mask(label_path)\n\n        if self.transform:\n            transformed = self.transform(image=image, mask=label)\n            image = transformed[\"image\"]\n            label = transformed[\"mask\"]\n        return image, label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:09:12.689070Z","iopub.execute_input":"2025-05-29T04:09:12.689442Z","iopub.status.idle":"2025-05-29T04:09:12.698845Z","shell.execute_reply.started":"2025-05-29T04:09:12.689414Z","shell.execute_reply":"2025-05-29T04:09:12.697846Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Đọc test data để submit\nclass Test_Dataset(torch.utils.data.Dataset):\n    def __init__(self, dir=\"path/to/data\", transform=None):\n        self.img_path_lst = []\n        self.dir = dir\n        self.transform = transform\n        self.img_path_lst = glob.glob(\"{}/test/test/*\".format(self.dir))\n\n    def __len__(self):\n        return len(self.img_path_lst)\n    \n\n    def __getitem__(self, idx):\n        img_path = self.img_path_lst[idx]\n        image = cv2.imread(img_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        height, width, channels = image.shape\n        image = cv2.resize(image, (trainsize, trainsize))\n        name =  os.path.basename(img_path)\n        if self.transform:\n            transformed = self.transform(image=image)\n            image = transformed[\"image\"]\n        return image, height, width, name[:-5]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:09:13.602863Z","iopub.execute_input":"2025-05-29T04:09:13.603201Z","iopub.status.idle":"2025-05-29T04:09:13.609327Z","shell.execute_reply.started":"2025-05-29T04:09:13.603174Z","shell.execute_reply":"2025-05-29T04:09:13.608363Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = BKpolypDataset(dir=\"/kaggle/input/bkai-igh-neopolyp\", transform=train_transform)\ntest_dataset_polyp = Test_Dataset(dir=\"/kaggle/input/bkai-igh-neopolyp\", transform=val_transform)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:09:20.640610Z","iopub.execute_input":"2025-05-29T04:09:20.640953Z","iopub.status.idle":"2025-05-29T04:09:21.020768Z","shell.execute_reply.started":"2025-05-29T04:09:20.640924Z","shell.execute_reply":"2025-05-29T04:09:21.020079Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Xem một test data\nimage_test, height, width, name = test_dataset_polyp.__getitem__(3)\nprint(name)\nprint(height)\nprint(width)\nplt.subplot(1,1,1)\nplt.imshow(unorm(image_test).permute(1, 2, 0))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:09:24.154975Z","iopub.execute_input":"2025-05-29T04:09:24.155326Z","iopub.status.idle":"2025-05-29T04:09:24.619955Z","shell.execute_reply.started":"2025-05-29T04:09:24.155297Z","shell.execute_reply":"2025-05-29T04:09:24.619179Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Xem một train data\nimport random\nid_test = random.randint(0, train_dataset.__len__())\nsample1, sample2 = train_dataset.__getitem__(id_test)\nnumpy_array = sample2.numpy()\ncount = (numpy_array == [0., 1., 0.]).all(axis=2).sum()\nprint(count)\nplt.subplot(1,2,1)\nplt.imshow(unorm(sample1).permute(1, 2, 0))\nplt.subplot(1,2,2)\nplt.imshow(sample2.squeeze())\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:09:29.207904Z","iopub.execute_input":"2025-05-29T04:09:29.208268Z","iopub.status.idle":"2025-05-29T04:09:29.601884Z","shell.execute_reply.started":"2025-05-29T04:09:29.208238Z","shell.execute_reply":"2025-05-29T04:09:29.601027Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Tính thành phần các nhãn lớp trong data\ndo = 0\nxanh = 0\ndo_xanh = 0\nfor i in range(0, train_dataset.__len__()):\n    image, mask = train_dataset.__getitem__(i)\n    numpy_array = mask.numpy()\n    count1 = (numpy_array == [0., 1., 0.]).all(axis=2).sum()\n    count2 = (numpy_array == [0., 0., 1.]).all(axis=2).sum()\n    if count1 > 1: \n        do = do + 1\n    if count2 > 1:\n        xanh = xanh + 1\n    if count1 > 1 and count2 >1:\n        do_xanh = do_xanh + 1\n    \nprint(train_dataset.__len__())\nprint(\"đỏ: \", do)\nprint(\"xanh: \", xanh)\nprint(\"đỏ_xanh: \", do_xanh)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:09:39.804622Z","iopub.execute_input":"2025-05-29T04:09:39.804949Z","iopub.status.idle":"2025-05-29T04:10:30.918262Z","shell.execute_reply.started":"2025-05-29T04:09:39.804924Z","shell.execute_reply":"2025-05-29T04:10:30.917356Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_size = 900\ntest_size = 100\ntrain_indices = list(range(train_size))\ntest_indices = list(range(train_size, train_size + test_size))\ntrain_dataset = Subset(BKpolypDataset(dir=\"/kaggle/input/bkai-igh-neopolyp\", transform=train_transform), train_indices)\ntest_dataset = Subset(BKpolypDataset(dir=\"/kaggle/input/bkai-igh-neopolyp\", transform=val_transform), test_indices)\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:10:56.873867Z","iopub.execute_input":"2025-05-29T04:10:56.874322Z","iopub.status.idle":"2025-05-29T04:10:56.884814Z","shell.execute_reply.started":"2025-05-29T04:10:56.874292Z","shell.execute_reply":"2025-05-29T04:10:56.883978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# torch.unique(train_dataset[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:23:00.904682Z","iopub.execute_input":"2025-05-29T04:23:00.905029Z","iopub.status.idle":"2025-05-29T04:23:00.908998Z","shell.execute_reply.started":"2025-05-29T04:23:00.905002Z","shell.execute_reply":"2025-05-29T04:23:00.908075Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DoubleConv(nn.Module):\n    def __init__(self, in_channels, out_channels):\n        super(DoubleConv, self).__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.LeakyReLU(inplace=True),\n            nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),\n            nn.BatchNorm2d(out_channels),\n            nn.LeakyReLU(inplace=True),\n            nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),\n            nn.BatchNorm2d(out_channels),\n            nn.LeakyReLU(inplace=True),\n        )\n\n    def forward(self, x):\n        return self.double_conv(x)\n    \n    \nclass DownBlock(nn.Module):\n    def __init__(self, in_channels, out_channels):\n        super(DownBlock, self).__init__()\n        self.double_conv = DoubleConv(in_channels, out_channels)\n        self.down_sample = nn.MaxPool2d(2)\n\n    def forward(self, x):\n        skip_out = self.double_conv(x)\n        down_out = self.down_sample(skip_out)\n        return (down_out, skip_out)\n\n    \nclass UpBlock(nn.Module):\n    def __init__(self, in_channels, out_channels, up_sample_mode):\n        super(UpBlock, self).__init__()\n        if up_sample_mode == 'conv_transpose':\n            if out_channels*4 == in_channels:\n                self.up_sample = nn.ConvTranspose2d(in_channels-out_channels*2, in_channels-out_channels*2, kernel_size=2, stride=2) \n            else:\n                self.up_sample = nn.ConvTranspose2d(in_channels-out_channels, in_channels-out_channels, kernel_size=2, stride=2)\n        else:\n            self.up_sample = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n        self.double_conv = DoubleConv(in_channels, out_channels)\n\n    def forward(self, down_input, skip_input):\n#         print(\"down\", down_input.shape)\n#         print(\"skip\", skip_input.shape)\n        x = self.up_sample(down_input)\n#         print(\"x\",x.shape)\n        x = torch.cat([x, skip_input], dim=1)\n        return self.double_conv(x)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:22:56.175724Z","iopub.execute_input":"2025-05-29T04:22:56.176084Z","iopub.status.idle":"2025-05-29T04:22:56.186054Z","shell.execute_reply.started":"2025-05-29T04:22:56.176056Z","shell.execute_reply":"2025-05-29T04:22:56.185352Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ResUnet\nclass PolypModel(nn.Module):\n    def __init__(self, out_classes=3, up_sample_mode='conv_transpose'):\n        super().__init__()\n        self.out_classes = out_classes\n        self.backbone = timm.create_model(\"resnet152\", pretrained=True, features_only=True)\n#         self.down_conv1 = DownBlock(3, 64)\n        self.down_conv1 = DownBlock(64, 128)\n        self.down_conv2 = DownBlock(256, 512)\n        self.down_conv3 = DownBlock(512, 1024)\n        self.down_conv4 = DownBlock(1024, 2048)\n        self.up_sample_mode = up_sample_mode\n        self.block_neck = DoubleConv(2048, 1024)\n        self.block_up1 = UpBlock(1024+1024, 512,self.up_sample_mode)\n        self.block_up2 = UpBlock(512+512, 256,self.up_sample_mode)\n        self.block_up3 = UpBlock(256+256, 128,self.up_sample_mode)\n        self.block_up4 = UpBlock(128+64, 64,self.up_sample_mode)\n        self.conv_last = nn.Conv2d(64, out_classes, kernel_size=1)\n        self.upsample = nn.Upsample(scale_factor=2, mode=\"bilinear\")\n        self.final_activation = nn.Softmax(dim=1)\n\n    def forward(self, x):\n        x1, x2, x3, x4, x5 = self.backbone(x)\n        x = self.block_neck(x5) # x (B, 1024, 8, 8)\n        x = self.block_up1(x, x4)\n        x = self.block_up2(x, x3)\n        x = self.block_up3(x, x2)\n        x = self.block_up4(x, x1 )\n        x = self.conv_last(x)\n        x = self.upsample(x)\n        x = self.final_activation(x)\n        return x\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:23:17.904135Z","iopub.execute_input":"2025-05-29T04:23:17.904954Z","iopub.status.idle":"2025-05-29T04:23:17.913070Z","shell.execute_reply.started":"2025-05-29T04:23:17.904923Z","shell.execute_reply":"2025-05-29T04:23:17.911942Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Khởi tạo các tham số\nlearning_rate = 0.0001\nbatch_size = 32\nnum_epochs = 301\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\ncriterion = nn.CrossEntropyLoss()\nmodel_segmentation = PolypModel().to(device)\n# model_colorization = ColorizationModel().to(device)\n# checkpoint = torch.load('/kaggle/working/colorization_model_15.pth')\n# model_segmentation.load_state_dict(checkpoint['model_state_dict'])\n\n\n# model_segmentation.down_conv1.load_state_dict(model_colorization.down_conv1.state_dict())\n# model_segmentation.down_conv2.load_state_dict(model_colorization.down_conv2.state_dict())\n# model_segmentation.down_conv3.load_state_dict(model_colorization.down_conv3.state_dict())\n# model_segmentation.down_conv4.load_state_dict(model_colorization.down_conv4.state_dict())\n# model_segmentation.down_conv1.requires_grad_(False)\n# model_segmentation.down_conv2.requires_grad_(False)\n# model_segmentation.down_conv3.requires_grad_(False)\n# model_segmentation.down_conv4.requires_grad_(False)\n\noptimizer = torch.optim.Adam(model_segmentation.parameters(), lr=learning_rate)\n# L_epoch = checkpoint['epoch']\n# optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:23:26.587864Z","iopub.execute_input":"2025-05-29T04:23:26.588431Z","iopub.status.idle":"2025-05-29T04:23:29.461350Z","shell.execute_reply.started":"2025-05-29T04:23:26.588399Z","shell.execute_reply":"2025-05-29T04:23:29.460639Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Khởi tạo dataloader\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, pin_memory=True)\ntest_loader =  DataLoader(test_dataset, batch_size=batch_size, shuffle=False, pin_memory=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:23:31.791445Z","iopub.execute_input":"2025-05-29T04:23:31.791753Z","iopub.status.idle":"2025-05-29T04:23:31.796381Z","shell.execute_reply.started":"2025-05-29T04:23:31.791729Z","shell.execute_reply":"2025-05-29T04:23:31.795172Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install torchinfo\nfrom torchinfo import summary","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:11:34.233036Z","iopub.execute_input":"2025-05-29T04:11:34.233427Z","iopub.status.idle":"2025-05-29T04:11:42.177335Z","shell.execute_reply.started":"2025-05-29T04:11:34.233391Z","shell.execute_reply":"2025-05-29T04:11:42.176353Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nx = torch.randn(1, 3, 224, 224).to(device) \nsummary(model_segmentation, (1,3,256,256))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:11:44.203656Z","iopub.execute_input":"2025-05-29T04:11:44.204537Z","iopub.status.idle":"2025-05-29T04:11:45.651792Z","shell.execute_reply.started":"2025-05-29T04:11:44.204502Z","shell.execute_reply":"2025-05-29T04:11:45.650782Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"# Hàm chuyển output về mask\ncolor_dict = {0: (0,   0, 0),\n              1: (255, 0,   0),\n              2: (0, 255,   0)}\ndef mask_to_rgb(mask, color_dict):\n    output = np.zeros((mask.shape[0], mask.shape[1], 3))\n#     print(output.shape)\n    for k in color_dict.keys():\n        output[np.round(mask)==k] = color_dict[k]\n\n    return np.uint8(output)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:23:57.875022Z","iopub.execute_input":"2025-05-29T04:23:57.875386Z","iopub.status.idle":"2025-05-29T04:23:57.881074Z","shell.execute_reply.started":"2025-05-29T04:23:57.875359Z","shell.execute_reply":"2025-05-29T04:23:57.880030Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Hàm test model\ndef check_output(path):\n    model = PolypModel()\n    checkpoint = torch.load(path)\n    model.load_state_dict(checkpoint['model_state_dict'])\n    # model.load_state_dict(torch.load('/kaggle/input/model-ver9h/colorization_model_49.pth'))\n    # model.load_state_dict(torch.load('/kaggle/input/model-ver9h/colorization_model_49.pth',map_location=torch.device('cpu')))\n    test_loader = DataLoader(test_dataset, batch_size=1)\n    # test_mask_loader = DataLoader(test_mask_dataset, batch_size=1)\n    # test_loader = DataLoader(train_dataset, batch_size=1)\n    # test_mask_loader = DataLoader(mask_dataset, batch_size=1)\n    model.eval()\n    loop=0\n    i=1\n    with torch.no_grad():\n        for image,mask in test_loader:\n            loop = loop +1\n            if loop == 10:\n                break\n    #         print(AB.shape)\n            # Forward pass\n            outputs = model(image)\n            mask = mask.squeeze()\n#             print(\"mask\", mask.shape)\n#             print(mask)\n            outputs = outputs.squeeze()\n            count = (mask == 0).sum()\n#             print(count)\n#             print(\"outputs\",outputs.shape)\n\n    #         outputs = outputs.astype(np.uint8)\n    #         print(outputs)\n            outputs = np.argmax(outputs, axis=0)\n    #         print(outputs)\n\n    #         print(outputs.shape)\n            outputs = mask_to_rgb(outputs, color_dict)\n            mask=np.argmax(mask, axis=2)\n#             print(mask)\n            mask = mask_to_rgb(mask, color_dict)\n            count1 = (mask == 1).sum()\n#             print(count1)\n    #         print(\"color:\", mask)\n\n\n            plt.figure(figsize=(30,30))\n            plt.subplot(12,12,i)\n            plt.title('output')\n            plt.imshow(outputs)\n            plt.subplot(12,12,i+1)\n            plt.title('real')\n            plt.imshow(mask)\n\n\n            i=i+2\n            plt.xticks([]), plt.yticks([]) # optional line of code, just to hide tick values on X and Y axis if needed\n            plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-29T04:23:58.967710Z","iopub.execute_input":"2025-05-29T04:23:58.968297Z","iopub.status.idle":"2025-05-29T04:23:58.976155Z","shell.execute_reply.started":"2025-05-29T04:23:58.968268Z","shell.execute_reply":"2025-05-29T04:23:58.975162Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # Tiếp tục train\n# checkpoint = torch.load('/kaggle/input/model-polyp/colorization_model.pth')\n# model_segmentation.load_state_dict(checkpoint['model_state_dict'])\n# optimizer.load_state_dict(checkpoint['optimizer_state_dict'])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Train model\nmodel_segmentation.train()\n# for epoch in range(num_epochs):\nfor epoch in range(0, num_epochs):\n    # Train on batches\n    train_loss = 0\n    for image, mask in train_loader:\n        image=image.to(device)\n        mask=mask.to(device)\n        # Zero gradients\n        optimizer.zero_grad()\n        mask = mask.permute(0, 3, 1,2)\n#         print(RGB.shape)\n        # Forward pass\n        outputs = model_segmentation(image)\n#         outputs = F.softmax(outputs, dim=1)\n        outputs = outputs.squeeze()\n#         print(L.shape)\n#         print(outputs.shape)\n#         print(AB.shape)\n#         print(outputs.shape)\n#         print(mask.shape)\n#         print(torch.unique(outputs))\n        # Compute loss\n#         mask = mask.long()\n\n        loss = criterion(outputs, mask)\n\n        # Backward pass and optimize\n        loss.backward()\n        optimizer.step()\n\n        # Update train loss\n        train_loss += loss.item()\n\n    # Compute validation loss\n    val_loss = 0\n    iou=0\n    with torch.no_grad():\n        for image, mask in test_loader:\n            image=image.to(device)\n            mask=mask.to(device)\n            mask = mask.permute(0, 3, 1,2)\n            # Forward pass\n            outputs = model_segmentation(image)\n#             outputs = F.softmax(outputs, dim=1)\n            outputs = outputs.squeeze()\n#             print(\"mask:\",mask.shape)\n#             print(outputs.shape)\n#             mask = mask.long()\n\n            # Compute loss\n            loss = criterion(outputs, mask)\n#             iou += ops.box_iou(outputs, mask).item()\n\n            # Update validation loss\n            val_loss += loss.item()\n\n    # Print loss\n    print(f\"Epoch {epoch+1}/{num_epochs}, Train Loss: {train_loss/len(train_loader):.4f}, Validation Loss: {val_loss/len(test_loader):.4f}\")\n#     print(f\"iou: {iou/len(test_loader):.4f}\")\n    if (epoch+1)%5 ==0:\n        checkpoint = {\n        'epoch': epoch,\n        'model_state_dict': model_segmentation.state_dict(),\n        'optimizer_state_dict': optimizer.state_dict(),\n        'loss': loss,\n        }\n        save_path = 'model.pth'\n\n        torch.save(checkpoint, save_path)\n        check_output(save_path)\n# torch.save(model_segmentation.state_dict(), 'colorization_model.pth')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# check_output(\"/kaggle/working/colorization_model_0.pth\")","metadata":{"execution":{"iopub.status.busy":"2023-12-24T08:00:40.937741Z","iopub.status.idle":"2023-12-24T08:00:40.938119Z","shell.execute_reply.started":"2023-12-24T08:00:40.937940Z","shell.execute_reply":"2023-12-24T08:00:40.937956Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nimport numpy as np\n\n# Đọc ảnh màu\ndef Smoothed_img(image):\n    resized_image = image\n    smoothed_image = cv2.GaussianBlur(resized_image, (15, 15), 0)\n    red_pixels = (smoothed_image[:, :, 2] > 100)\n    green_pixels = (smoothed_image[:, :, 1] > 100)\n    black_pixels = ~(red_pixels | green_pixels)\n    smoothed_image[red_pixels] = [0, 0, 255]\n    smoothed_image[green_pixels] = [0, 255, 0]\n    smoothed_image[black_pixels] = [0, 0, 0]\n\n    pixel_values = np.array(smoothed_image)\n    unique_values = np.unique(pixel_values)\n    print(unique_values)\n    # Hiển thị ảnh gốc và ảnh đã làm mịn\n    return smoothed_image\n\n","metadata":{"execution":{"iopub.status.busy":"2023-12-24T08:00:40.939291Z","iopub.status.idle":"2023-12-24T08:00:40.939654Z","shell.execute_reply.started":"2023-12-24T08:00:40.939460Z","shell.execute_reply":"2023-12-24T08:00:40.939476Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Clear output folder\n# import os\n\n# def remove_folder_contents(folder):\n#     for the_file in os.listdir(folder):\n#         file_path = os.path.join(folder, the_file)\n#         try:\n#             if os.path.isfile(file_path):\n#                 os.unlink(file_path)\n#             elif os.path.isdir(file_path):\n#                 remove_folder_contents(file_path)\n#                 os.rmdir(file_path)\n#         except Exception as e:\n#             print(e)\n\n# folder_path = '/kaggle/working/output'\n# remove_folder_contents(folder_path)\n# os.rmdir(folder_path)\n# %cd /kaggle/working/\nos.mkdir(\"/kaggle/working/output\")","metadata":{"execution":{"iopub.status.busy":"2023-12-24T08:00:40.940716Z","iopub.status.idle":"2023-12-24T08:00:40.941022Z","shell.execute_reply.started":"2023-12-24T08:00:40.940868Z","shell.execute_reply":"2023-12-24T08:00:40.940883Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = PolypModel()\ncheckpoint = torch.load('model.pth')\nmodel.load_state_dict(checkpoint['model_state_dict'])\n# model.load_state_dict(torch.load('/kaggle/input/model-ver9h/colorization_model_49.pth'))\n# model.load_state_dict(torch.load('/kaggle/input/model-ver9h/colorization_model_49.pth',map_location=torch.device('cpu')))\ntest_loader = DataLoader(test_dataset_polyp, batch_size=1)\n# test_mask_loader = DataLoader(test_mask_dataset, batch_size=1)\n# test_loader = DataLoader(train_dataset, batch_size=1)\n# test_mask_loader = DataLoader(mask_dataset, batch_size=1)\nmodel.eval()\nloop=0\ni=1\nwith torch.no_grad():\n    for image, h, w, name in test_loader:\n        loop = loop +1\n        print(loop)\n#         if loop == 60:\n#             break\n#         print(AB.shape)\n        # Forward pass\n        outputs = model(image)\n#         mask = mask.squeeze()\n#         print(\"mask\", mask.shape)\n#         print(mask)\n        outputs = outputs.squeeze()\n#         count = (mask == 0).sum()\n#         print(count)\n#         print(\"outputs\",outputs.shape)\n        \n#         outputs = outputs.astype(np.uint8)\n#         print(outputs)\n        outputs = np.argmax(outputs, axis=0)\n#         print(outputs)\n\n#         print(outputs.shape)\n        outputs = mask_to_rgb(outputs, color_dict)\n#         mask=np.argmax(mask, axis=2)\n#         print(mask)\n#         mask = mask_to_rgb(mask, color_dict)\n#         count1 = (mask == 1).sum()\n#         print(count1)\n#         print(\"color:\", mask)\n        w = w.item()\n        h = h.item()\n#         print(w)\n#         print(h)\n        new_size = (w, h)\n        resized_image = cv2.resize(outputs, new_size, interpolation=cv2.INTER_CUBIC)\n        resized_image = cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB)\n        resized_image = Smoothed_img(resized_image)\n        cv2.imwrite(f\"/kaggle/working/output/{name[0]}.png\", resized_image)\n        \n\n","metadata":{"execution":{"iopub.status.busy":"2023-12-24T08:00:40.942446Z","iopub.status.idle":"2023-12-24T08:00:40.942803Z","shell.execute_reply.started":"2023-12-24T08:00:40.942638Z","shell.execute_reply":"2023-12-24T08:00:40.942654Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Xuất các kết quả thành tệp csv để submit\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport os\n\ndef rle_to_string(runs):\n    return ' '.join(str(x) for x in runs)\n\ndef rle_encode_one_mask(mask):\n    pixels = mask.flatten()\n    pixels[pixels > 0] = 255\n    use_padding = False\n    if pixels[0] or pixels[-1]:\n        use_padding = True\n        pixel_padded = np.zeros([len(pixels) + 2], dtype=pixels.dtype)\n        pixel_padded[1:-1] = pixels\n        pixels = pixel_padded\n    \n    rle = np.where(pixels[1:] != pixels[:-1])[0] + 2\n    if use_padding:\n        rle = rle - 1\n    rle[1::2] = rle[1::2] - rle[:-1:2]\n    return rle_to_string(rle)\n\ndef rle2mask(mask_rle, shape=(3,3)):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (width,height) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape).T\n\ndef mask2string(dir):\n    ## mask --> string\n    strings = []\n    ids = []\n    ws, hs = [[] for i in range(2)]\n    for image_id in os.listdir(dir):\n        id = image_id.split('.')[0]\n        path = os.path.join(dir, image_id)\n        print(path)\n        img = cv2.imread(path)[:,:,::-1]\n        h, w = img.shape[0], img.shape[1]\n        for channel in range(2):\n            ws.append(w)\n            hs.append(h)\n            ids.append(f'{id}_{channel}')\n            string = rle_encode_one_mask(img[:,:,channel])\n            strings.append(string)\n    r = {\n        'ids': ids,\n        'strings': strings,\n    }\n    return r\n\n\nMASK_DIR_PATH = '/kaggle/working/output' # change this to the path to your output mask folder\ndir = MASK_DIR_PATH\nres = mask2string(dir)\ndf = pd.DataFrame(columns=['Id', 'Expected'])\ndf['Id'] = res['ids']\ndf['Expected'] = res['strings']\n\ndf.to_csv(r'output.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-12-24T08:00:40.943968Z","iopub.status.idle":"2023-12-24T08:00:40.944285Z","shell.execute_reply.started":"2023-12-24T08:00:40.944122Z","shell.execute_reply":"2023-12-24T08:00:40.944143Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%cd /kaggle/working/\n!zip output.zip /kaggle/working/output/*.png\n","metadata":{"execution":{"iopub.status.busy":"2023-12-24T08:00:40.946102Z","iopub.status.idle":"2023-12-24T08:00:40.946420Z","shell.execute_reply.started":"2023-12-24T08:00:40.946266Z","shell.execute_reply":"2023-12-24T08:00:40.946281Z"},"trusted":true},"outputs":[],"execution_count":null}]}