{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","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"}],"dockerImageVersionId":30699,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import cv2\nimport torch\nfrom torch.utils.data import Dataset, DataLoader\nimport numpy as np\nimport torch.nn as nn3\nfrom torchvision.models import resnet50\nimport pandas as pd\nimport os\nfrom torch.cuda.amp import GradScaler, autocast\nfrom glob import glob\nimport torch.nn.functional as F\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport torch.nn as nn\n\n\n\nprint(\"IMPORT OK !!!\")","metadata":{"execution":{"iopub.status.busy":"2024-05-29T10:46:08.011795Z","iopub.execute_input":"2024-05-29T10:46:08.012672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to decode RLE\ndef rle_decode(mask_rle, shape=(512, 512)):\n    s = list(map(int, 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  # Needed to align to RLE direction\n\n\nimport cv2\nimport torch\nfrom torch.utils.data import Dataset\nimport os\n\nclass MyDataset(Dataset):\n    def __init__(self, meta, image_size=(512, 512)):\n        self.meta = meta\n        self.image_size = image_size\n\n    def __len__(self):\n        return len(self.meta)\n\n    def __getitem__(self, index):\n        f = self.meta[index]\n        if f is None:\n            raise ValueError(\"File path not found in metadata\")\n        \n        # Load image\n        image = cv2.imread(f, cv2.IMREAD_GRAYSCALE)\n        image = cv2.resize(image, self.image_size)\n        image = torch.from_numpy(image).float().unsqueeze(0)  # Convert to tensor and add channel dimension\n        image = norm_by_percentile(image)\n\n        \n        \n        # Load mask\n        maskfile = f.replace('images', 'labels')\n        if os.path.exists(maskfile):\n            mask = cv2.imread(maskfile, cv2.IMREAD_GRAYSCALE)\n            mask = cv2.resize(mask, self.image_size)\n            mask = torch.from_numpy(mask).float().unsqueeze(0)  # Convert to tensor and add channel dimension\n            mask = norm_by_percentile(mask)\n\n        else:\n            mask = torch.zeros_like(image)  # Create a zero mask with same shape as image\n        \n        return image, mask\n    \n   \n\n\nclass DotDict(dict):\n    \"\"\"dot.notation access to dictionary attributes\"\"\"\n    def __getattr__(self, attr):\n        return self.get(attr)\n    \n    __setattr__= dict.__setitem__\n    __delattr__= dict.__delitem__\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_images(images, masks, n=5):\n    \"\"\"\n    Display a batch of images and their corresponding masks.\n    \n    Args:\n    - images (torch.Tensor): Batch of images.\n    - masks (torch.Tensor): Batch of masks.\n    - n (int): Number of images to display. Default is 5.\n    \"\"\"\n    images = images.cpu().numpy()\n    masks = masks.cpu().numpy()\n    \n    batch_size = images.shape[0]\n    n = min(n, batch_size)  # Ensure n does not exceed batch size\n\n    plt.figure(figsize=(15, 10))\n    for i in range(n):\n        plt.subplot(n, 2, 2 * i + 1)\n        plt.imshow(images[i, 0], cmap='gray')\n        plt.title('Image')\n        plt.axis('off')\n        \n        plt.subplot(n, 2, 2 * i + 2)\n        plt.imshow(masks[i, 0], cmap='gray')\n        plt.title('Mask')\n        plt.axis('off')\n    plt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def norm_by_percentile(x, low=10, high=99.8, alpha=0.01):\n    xmin = np.percentile(x, low)\n    xmax = np.percentile(x, high)\n    x = (x - xmin) / (xmax - xmin + 1e-5)  # Avoid division by zero\n    x = np.clip(x, 0, 1)  # Ensure values are in the range [0, 1]\n    if 1:\n        x[x > 1] = (x[x > 1] - 1) * alpha + 1\n        x[x < 0] = x[x < 0] * alpha\n    return x\n    #return x / 65536.0","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_checkpoint(epoch, model, optimizer, loss, file_path):\n    torch.save({\n        'epoch': epoch,\n        'model_state_dict': model.state_dict(),\n        'optimizer_state_dict': optimizer.state_dict(),\n        'loss': loss,\n    }, file_path)\n\ndef load_checkpoint(file_path, model, optimizer):\n    checkpoint = torch.load(file_path)\n    model.load_state_dict(checkpoint['model_state_dict'])\n    optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n    epoch = checkpoint['epoch']\n    loss = checkpoint['loss']\n    return epoch, model, optimizer, loss","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def init_weights(m):\n    if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):\n        nn.init.kaiming_normal_(m.weight, nonlinearity='relu')\n        if m.bias is not None:\n            nn.init.constant_(m.bias, 0)\n\n#net.apply(init_weights)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Net(nn.Module):\n    def __init__(self, pretrained=True):\n        super(Net, self).__init__()\n        \n        self.backbone = resnet50(pretrained=pretrained)\n        \n\n        self.backbone.conv1 = nn.Conv2d(1, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)\n        \n        self.encoder = nn.Sequential(*list(self.backbone.children())[:-2])\n        \n        self.upconv1 = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n        self.conv1 = nn.Conv2d(2048 + 1024, 1024, kernel_size=3, padding=1)\n        \n        self.upconv2 = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n        self.conv2 = nn.Conv2d(1024 + 512, 512, kernel_size=3, padding=1)\n        \n        self.upconv3 = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n        self.conv3 = nn.Conv2d(512 + 256, 256, kernel_size=3, padding=1)\n        \n        self.upconv4 = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n        self.conv4 = nn.Conv2d(256 + 64, 64, kernel_size=3, padding=1)\n        \n        self.upconv5 = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n        self.conv5 = nn.Conv2d(64, 32, kernel_size=3, padding=1)\n        \n        self.vessel_out = nn.Conv2d(32, 1, kernel_size=1)\n        self.kidney_out = nn.Conv2d(32, 1, kernel_size=1)\n    \n    def forward(self, x):\n        # Encoder\n        enc1 = self.backbone.conv1(x)\n        enc1 = self.backbone.bn1(enc1)\n        enc1 = self.backbone.relu(enc1)\n        enc1 = self.backbone.maxpool(enc1)\n        \n        enc2 = self.backbone.layer1(enc1)\n        enc3 = self.backbone.layer2(enc2)\n        enc4 = self.backbone.layer3(enc3)\n        enc5 = self.backbone.layer4(enc4)\n        \n        # Decoder with debugging prints\n        dec1 = self.upconv1(enc5)\n        #print(f\"dec1: {dec1.size()}, enc4: {enc4.size()}\")\n        if dec1.size()[2:] != enc4.size()[2:]:\n            dec1 = F.interpolate(dec1, size=enc4.shape[2:], mode='bilinear', align_corners=True)\n        dec1 = torch.cat((dec1, enc4), dim=1)\n        #print(f\"After cat dec1: {dec1.size()}\")\n        dec1 = self.conv1(dec1)\n        \n        dec2 = self.upconv2(dec1)\n        #print(f\"dec2: {dec2.size()}, enc3: {enc3.size()}\")\n        if dec2.size()[2:] != enc3.size()[2:]:\n            dec2 = F.interpolate(dec2, size=enc3.shape[2:], mode='bilinear', align_corners=True)\n        dec2 = torch.cat((dec2, enc3), dim=1)\n        #print(f\"After cat dec2: {dec2.size()}\")\n        dec2 = self.conv2(dec2)\n        \n        dec3 = self.upconv3(dec2)\n        #print(f\"dec3: {dec3.size()}, enc2: {enc2.size()}\")\n        if dec3.size()[2:] != enc2.size()[2:]:\n            dec3 = F.interpolate(dec3, size=enc2.shape[2:], mode='bilinear', align_corners=True)\n        dec3 = torch.cat((dec3, enc2), dim=1)\n        #print(f\"After cat dec3: {dec3.size()}\")\n        dec3 = self.conv3(dec3)\n        \n        dec4 = self.upconv4(dec3)\n        #print(f\"dec4: {dec4.size()}, enc1: {enc1.size()}\")\n        if dec4.size()[2:] != enc1.size()[2:]:\n            dec4 = F.interpolate(dec4, size=enc1.shape[2:], mode='bilinear', align_corners=True)\n        dec4 = torch.cat((dec4, enc1), dim=1)\n        #print(f\"After cat dec4: {dec4.size()}\")\n        dec4 = self.conv4(dec4)\n        \n        dec5 = self.upconv5(dec4)\n        #print(f\"dec5: {dec5.size()}\")\n        if dec5.size()[2:] != x.size()[2:]:\n            dec5 = F.interpolate(dec5, size=x.shape[2:], mode='bilinear', align_corners=True)\n        dec5 = self.conv5(dec5)\n        \n        vessel = self.vessel_out(dec5)\n        kidney = self.kidney_out(dec5)\n        \n        return vessel, kidney\n\n    \nprint (\"NET OK!!!\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def choose_biggest_object(mask, threshold):\n    mask = (mask > threshold).astype(np.uint8) * 255\n\n    print(f\"Mask shape before connectedComponents: {mask.shape}\")\n    if len(mask.shape) != 2:\n        raise ValueError(\"Mask must be a single-channel image\")\n\n    # Apply connected components\n    num_label, label, stats,  = cv2.connectedComponentsWithStats(mask, connectivity=8)\n    max_label = -1\n    max_area = -1\n    for l in range(1, num_label):\n        if stats[l, cv2.CC_STAT_AREA] >= max_area:\n            max_area = stats[l, cv2.CC_STAT_AREA]\n            max_label = l\n    processed = (label == max_label).astype(np.uint8)\n    return processed\n\ndef remove_small_objects(mask, min_size, threshold):\n    mask = ((mask > threshold) * 255).astype(np.uint8)\n    # find all connected components (labels)\n    num_label, label, stats, centroid = cv2.connectedComponentsWithStats(mask, connectivity=8)\n    # create a mask where small objects are removed\n    processed = np.zeros_like(mask)\n    for l in range(1, num_label):\n        if stats[l, cv2.CC_STAT_AREA] >= min_size:\n            processed[label == l] = 1\n    return processed","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(net, train_loader, val_loader, criterion, optimizer, start_epoch=0, total_epochs=10, accumulation_steps=4, gradient_clip=1.0, checkpoint_interval=1, checkpoint_dir='./checkpoints'):\n    net.train()\n    scaler = GradScaler()\n\n    # Create checkpoint directory if it doesn't exist\n    os.makedirs(checkpoint_dir, exist_ok=True)\n\n    best_val_loss = float('inf')\n\n    for epoch in range(start_epoch, total_epochs):\n        epoch_loss = 0\n        optimizer.zero_grad()\n        for i, (images, masks) in enumerate(train_loader):\n            images, masks = images.cuda(), masks.cuda()\n            \n            # Check for NaNs in input data\n            if torch.isnan(images).any() or torch.isnan(masks).any():\n                print(\"NaNs found in input data\")\n                continue\n            \n            # Show the first batch of images and masks at the start of each epoch\n            if i == 0:\n                show_images(images, masks, n=1)\n\n            with autocast():\n                vessel_pred, kidney_pred = net(images)\n                \n                if torch.isnan(vessel_pred).any() or torch.isnan(kidney_pred).any():\n                    print(\"NaNs found in model outputs\")\n                    continue\n\n                loss_vessel = criterion(vessel_pred, masks)\n                loss_kidney = criterion(kidney_pred, masks)\n                loss = (loss_vessel + loss_kidney) / 2.0 \n\n            # Check for NaNs in loss\n            if torch.isnan(loss):\n                print(\"NaNs found in loss\")\n                continue\n\n            scaler.scale(loss).backward()\n            \n            # Gradient clipping\n            torch.nn.utils.clip_grad_norm_(net.parameters(), max_norm=0.1)\n            \n            # Check for NaNs in gradients\n            nan_grad = False\n            for param in net.parameters():\n                if param.grad is not None and (torch.isnan(param.grad).any() or torch.isinf(param.grad).any()):\n                    #print(f\"NaNs or infinite values found in gradients at epoch {epoch+1}, batch {i+1}\")\n                    nan_grad = True\n                    break\n            if nan_grad:\n                optimizer.zero_grad()\n                continue\n\n            if (i + 1) % accumulation_steps == 0:\n                scaler.step(optimizer)\n                scaler.update()\n                optimizer.zero_grad()\n            \n            epoch_loss += loss.item()\n            torch.cuda.empty_cache()  # Clear CUDA cache\n\n        # Validation\n        net.eval()\n        val_loss = 0\n        with torch.no_grad():\n            for images, masks in val_loader:\n                images, masks = images.cuda(), masks.cuda()\n                with autocast():\n                    vessel_pred, kidney_pred = net(images)\n                    loss_vessel = criterion(vessel_pred, masks)\n                    loss_kidney = criterion(kidney_pred, masks)\n                    loss = (loss_vessel + loss_kidney) / 2.0 \n                val_loss += loss.item()\n        val_loss /= len(val_loader)\n        print(f'Epoch {epoch+1}/{total_epochs}, Training Loss: {epoch_loss/len(train_loader)}, Validation Loss: {val_loss}')\n\n        # Save checkpoint\n        if (epoch + 1) % checkpoint_interval == 0:\n            checkpoint_path = os.path.join(checkpoint_dir, f'checkpoint_epoch_{epoch+1}.pth')\n            save_checkpoint(epoch + 1, net, optimizer, epoch_loss / len(train_loader), checkpoint_path)\n            # Also save the latest checkpoint\n            save_checkpoint(epoch + 1, net, optimizer, epoch_loss / len(train_loader), os.path.join(checkpoint_dir, 'latest_checkpoint.pth'))\n\n        # Save the best model\n        if val_loss < best_val_loss:\n            best_val_loss = val_loss\n            save_checkpoint(epoch + 1, net, optimizer, epoch_loss / len(train_loader), os.path.join(checkpoint_dir, 'best_model.pth'))\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n''''def do_submit(net, valid_meta, batch_size=1, p_threshold=0.5):\n    submission_data = []\n    net.eval()\n    \n    for d in valid_meta:\n        volume = [cv2.imread(f, cv2.IMREAD_GRAYSCALE) for f in d.file]\n        \n        # Check if any image failed to load\n        for idx, img in enumerate(volume):\n            if img is None:\n                raise FileNotFoundError(f\"Failed to load image: {d.file[idx]}\")\n        \n        # Resize images to 512x512\n        volume = [cv2.resize(img, (512, 512)) for img in volume]\n        \n        volume = np.stack(volume)\n        D, H, W = volume.shape\n        volume = torch.from_numpy(volume).float().unsqueeze(0).unsqueeze(0)  # Add batch and channel dimensions\n        \n        with torch.no_grad():\n            vessel_pred, kidney_pred = net(volume.cuda())\n        \n        vessel_pred = torch.sigmoid(vessel_pred).cpu().numpy().squeeze()\n        kidney_pred = torch.sigmoid(kidney_pred).cpu().numpy().squeeze()\n        \n        vessel_pred = (vessel_pred > p_threshold).astype(np.uint8) * 255\n        kidney_pred = (kidney_pred > p_threshold).astype(np.uint8) * 255\n        \n        for i, f in enumerate(d.file):\n            file_id = os.path.basename(f).replace('.tif', '')\n            submission_data.append({\n                'file_id': file_id,\n                'vessel': vessel_pred[i].tolist(),  # Convert numpy array to list\n                'kidney': kidney_pred[i].tolist()   # Convert numpy array to list\n            })\n    \n    submission_df = pd.DataFrame(submission_data)\n    return submission_df\n    '''\n","metadata":{"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob\n\n\n# Load the model and optimizer\nnet = Net(pretrained=True).cuda()\nnet.apply(init_weights)\noptimizer = torch.optim.Adam(net.parameters(), lr=1e-5, weight_decay=1e-5)\n#optimizer = torch.optim.RMSprop(net.parameters(), lr=1e-7, weight_decay=1e-5)\n\n\n# Collect all image files from the training directory\n\ntrain_files = []\n\n# List of directories or patterns you want to include\npatterns = [\n    '/kaggle/input/blood-vessel-segmentation/train/kidney_1_dense/images/*.tif',\n    '/kaggle/input/blood-vessel-segmentation/train/kidney_1_voi/images/*.tif',\n    '/kaggle/input/blood-vessel-segmentation/train/kidney_3_sparse/images/*.tif'\n    # Add more patterns as needed\n]\n\nfor pattern in patterns:\n    train_files.extend(glob.glob(pattern, recursive=True))\n\nrle_path = '/kaggle/input/blood-vessel-segmentation/train_rles.csv'\nrle_data = pd.read_csv(rle_path)\n\n\n# Verify the IDs in train_files and rle_data\nprint(\"Sample file IDs from train_files:\")\nfor f in train_files[:5]:\n    print(os.path.basename(f).split('.')[0])\n\nprint(\"Sample IDs from rle_data:\")\nprint(rle_data['id'].head())\n\n\n\n\n# Create metadata for all images\ntrain_meta = [\n    DotDict(\n        file=train_files,\n        shape=(len(train_files), 512, 512),\n        id=[os.path.splitext(os.path.basename(f))[0] for f in train_files]\n    )\n]\n\n# Prepare training DataLoader\ntrain_dataset = MyDataset(train_files)  \ntrain_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)\n\n\n# Prepare validation DataLoader\nval_files = glob.glob('/kaggle/input/blood-vessel-segmentation/train/kidney_2/images/*.tif', recursive=True)\nval_dataset = MyDataset(val_files)\nval_loader = DataLoader(val_dataset, batch_size=16, shuffle=False)\n\n\ncriterion = nn.BCEWithLogitsLoss()\n\n# Define the number of epochs you want to train for\ntotal_epochs = 10\ncheckpoint_dir = './checkpoints'\n\n# Load latest checkpoint if exists\nstart_epoch = 0\ncheckpoint_path = os.path.join(checkpoint_dir, 'latest_checkpoint.pth')\nif os.path.isfile(checkpoint_path):\n    start_epoch, net, optimizer, _ = load_checkpoint(checkpoint_path, net, optimizer)\n    print(f\"Resuming training from epoch {start_epoch}\")\n\n# Continue training for additional epochs\ntrain(net, train_loader, val_loader, criterion, optimizer, start_epoch=start_epoch, total_epochs=total_epochs, checkpoint_dir=checkpoint_dir)\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def choose_biggest_object(mask, threshold):\n    mask = ((mask > threshold) * 255).astype(np.uint8)\n    num_label, label, stats, centroid = cv2.connectedComponentsWithStats(mask, connectivity=8)\n    max_label = -1\n    max_area = -1\n    for l in range(1, num_label):\n        if stats[l, cv2.CC_STAT_AREA] >= max_area:\n            max_area = stats[l, cv2.CC_STAT_AREA]\n            max_label = l\n    processed = (label==max_label).astype(np.uint8)\n    return processed\n\n\ndef remove_small_objects(mask, min_size, threshold):\n    mask = ((mask > threshold) * 255).astype(np.uint8)\n    # find all connected components (labels)\n    num_label, label, stats, centroid = cv2.connectedComponentsWithStats(mask, connectivity=8)\n    # create a mask where small objects are removed\n    processed = np.zeros_like(mask)\n    for l in range(1, num_label):\n        if stats[l, cv2.CC_STAT_AREA] >= min_size:\n            processed[label == l] = 1\n    return processed\n\n\ndef rle_encode(mask):\n    pixel = mask.flatten()\n    pixel = np.concatenate([[0], pixel, [0]])\n    run = np.where(pixel[1:] != pixel[:-1])[0] + 1\n    run[1::2] -= run[::2]\n    rle = ' '.join(str(r) for r in run)\n    if rle == '':\n        rle = '1 0'\n    return rle\n\n#-------------------------------\n\n\ncheckpoint_file = \\\n    '/kaggle/working/checkpoints'\n   \nstate_dict = torch.load(checkpoint_file, map_location=lambda storage, loc: storage)['state_dict']\nprint(net.load_state_dict(state_dict, strict=False))  # True\n\nnet = net.eval()\nnet = net.cuda()\n\n\ndef dice_coefficient(pred, target):\n    intersection = np.sum(pred * target)\n    return (2. * intersection) / (np.sum(pred) + np.sum(target))\n\ndef iou(pred, target):\n    intersection = np.sum(pred * target)\n    union = np.sum(pred) + np.sum(target) - intersection\n    return intersection / union\n\ndef evaluate(predictions, ground_truths):\n    dice_scores = []\n    iou_scores = []\n\n    for pred, gt in zip(predictions, ground_truths):\n        dice_scores.append(dice_coefficient(pred, gt))\n        iou_scores.append(iou(pred, gt))\n    \n    return {\n        'Dice Coefficient': np.mean(dice_scores),\n        'IoU': np.mean(iou_scores)\n    }\n\n\n\ndef do_submit():\n    submission_df = []\n    predictions = []\n    ground_truths = []  # Load your ground truth masks here\n\n    for d in valid_meta:\n        volume = [cv2.imread(f, cv2.IMREAD_GRAYSCALE) for f in d.file]\n        volume = np.stack(volume)\n        D, H, W = volume.shape\n        \n        predict = np.zeros(d.shape, dtype=np.float16)\n        axes = [0, 1, 2]  # Axes to consider for TTA\n        for axis in axes:\n            loader = np.array_split(np.arange((D, H, W)[axis]), max(1, int((D, H, W)[axis] // cfg.batch_size)))\n            num_valid = len(loader)\n            \n            B = 0 \n            start_timer = timer()\n            for t in range(num_valid):\n                print(f'\\r validation: {t}/{num_valid}', time_to_str(timer() - start_timer, 'min'), end='', flush=True)\n\n                if axis == 0:\n                    image = volume[loader[t].tolist()]\n                if axis == 1:\n                    image = volume[:, loader[t].tolist()]\n                    image = image.transpose(1, 0, 2)\n                if axis == 2:\n                    image = volume[:, :, loader[t].tolist()]\n                    image = image.transpose(2, 0, 1)\n\n                batch_size, bh, bw = image.shape\n                m = image.reshape(batch_size, -1)\n                m = (m - m.min(keepdims=True)) / (m.max(keepdims=True) - m.min(keepdims=True) + 0.001)\n                m = m.reshape(batch_size, bh, bw)\n                m = np.ascontiguousarray(m)\n                image = torch.from_numpy(m).float().cuda().unsqueeze(1)\n\n                counter = 0\n                vessel, kidney = 0, 0\n                image = image.cuda() \n                with torch.cuda.amp.autocast(enabled=True):\n                    with torch.no_grad():\n                        v, k = net(image)\n                        vessel += v\n                        kidney += k\n                        counter += 1\n\n                        v, k = net(torch.flip(image, dims=[2,]))\n                        vessel += torch.flip(v, dims=[2,])\n                        kidney += torch.flip(k, dims=[2,])\n                        counter += 1\n\n                        v, k = net(torch.flip(image, dims=[3,]))\n                        vessel += torch.flip(v, dims=[3,])\n                        kidney += torch.flip(k, dims=[3,])\n                        counter += 1\n\n                        v, k = net(torch.rot90(image, k=1, dims=[2, 3]))\n                        vessel += torch.rot90(v, k=-1, dims=[2, 3])\n                        kidney += torch.rot90(k, k=-1, dims=[2, 3])\n                        counter += 1\n\n                        v, k = net(torch.rot90(image, k=2, dims=[2, 3]))\n                        vessel += torch.rot90(v, k=-2, dims=[2, 3])\n                        kidney += torch.rot90(k, k=-2, dims=[2, 3])\n                        counter += 1\n\n                        v, k = net(torch.rot90(image, k=3, dims=[2, 3]))\n                        vessel += torch.rot90(v, k=-3, dims=[2, 3])\n                        kidney += torch.rot90(k, k=-3, dims=[2, 3])\n                        counter += 1\n\n                vessel = vessel / counter\n                kidney = kidney / counter\n\n                vessel = vessel.float().data.cpu().numpy()\n                kidney = kidney.float().data.cpu().numpy()\n\n                batch_size = len(vessel)\n                for b in range(batch_size):\n                    mk = kidney[b, 0]\n                    mk = choose_biggest_object(mk, threshold=0.5)\n                    mv = vessel[b, 0]\n                    p = (mv * mk)\n                    if axis == 0:\n                        predict[B + b] += p\n                    if axis == 1:\n                        predict[:, B + b] += p\n                    if axis == 2:\n                        predict[:, :, B + b] += p\n\n                B += batch_size\n\n        predict = predict / len(axes)\n        predict = (predict > cfg.p_threshold).astype(np.uint8)\n\n        if cfg.cc_threshold > 0:\n            predict = cc3d.dust(\n                predict,\n                connectivity=26,\n                threshold=cfg.cc_threshold,\n                in_place=False\n            )\n\n        rle = [rle_encode(p) for p in predict]\n        predictions.append(predict)  # Store predictions for evaluation\n        ground_truths.append(ground_truth)  # Store corresponding ground truth\n\n        submission_df.append(\n            pd.DataFrame(data={\n                'id': d['id'],\n                'rle': rle,\n            })\n        )\n\n    submission_df = pd.concat(submission_df)\n    submission_df.to_csv('submission.csv', index=False)\n    print(submission_df)\n    \n    # Evaluate the predictions\n    metrics = evaluate(predictions, ground_truths)\n    print(\"Evaluation Metrics:\")\n    for metric, score in metrics.items():\n        print(f\"{metric}: {score}\")\n\n\nglob_file = glob(f'{data_dir}/test/kidney_5/images/*.tif')\n\ndo_submit()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AugmentedDataset(Dataset):\n    def __init__(self, original_dataset):\n        self.original_dataset = original_dataset\n\n    def __len__(self):\n        return len(self.original_dataset)\n\n    def __getitem__(self, idx):\n        images, masks = self.original_dataset[idx]\n        augmented_images, augmented_masks = self.apply_augmentation(images, masks)\n        return augmented_images, augmented_masks\n\n    @staticmethod\n    def apply_augmentation(images, masks):\n        k = random.randint(0, 3)\n        augmented_images = torch.rot90(images, k=k, dims=(1, 2))\n        augmented_masks = torch.rot90(masks, k=k, dims=(1, 2))\n        if random.random() > 0.5:\n            augmented_images = torch.flip(augmented_images, dims=(1,))\n            augmented_masks = torch.flip(augmented_masks, dims=(1,))\n        if random.random() > 0.5:\n            augmented_images = torch.flip(augmented_images, dims=(2,))\n            augmented_masks = torch.flip(augmented_masks, dims=(2,))\n        return augmented_images, augmented_masks\n\n            \n            \n            \naugmented_train_dataset = MyAugDataset(train_files)  \naugmented_train_loader = DataLoader(augmented_train_dataset, batch_size=16, shuffle=True)\n\n\ncriterion = nn.BCEWithLogitsLoss()\ntotal_epochs = 10\ncheckpoint_dir = './checkpoints'\nstart_epoch = 0\ncheckpoint_path = os.path.join(checkpoint_dir, 'latest_checkpoint.pth')\nif os.path.isfile(checkpoint_path):\n    start_epoch, net, optimizer, _ = load_checkpoint(checkpoint_path, net, optimizer)\n    print(f\"Resuming training from epoch {start_epoch}\")\n\n# Continue training for additional epochs\ntrain(net, augmented_train_loader, val_loader, criterion, optimizer, start_epoch=start_epoch, total_epochs=total_epochs, checkpoint_dir=checkpoint_dir)\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def choose_biggest_object(mask, threshold):\n    mask = ((mask > threshold) * 255).astype(np.uint8)\n    num_label, label, stats, centroid = cv2.connectedComponentsWithStats(mask, connectivity=8)\n    max_label = -1\n    max_area = -1\n    for l in range(1, num_label):\n        if stats[l, cv2.CC_STAT_AREA] >= max_area:\n            max_area = stats[l, cv2.CC_STAT_AREA]\n            max_label = l\n    processed = (label==max_label).astype(np.uint8)\n    return processed\n\n\ndef remove_small_objects(mask, min_size, threshold):\n    mask = ((mask > threshold) * 255).astype(np.uint8)\n    # find all connected components (labels)\n    num_label, label, stats, centroid = cv2.connectedComponentsWithStats(mask, connectivity=8)\n    # create a mask where small objects are removed\n    processed = np.zeros_like(mask)\n    for l in range(1, num_label):\n        if stats[l, cv2.CC_STAT_AREA] >= min_size:\n            processed[label == l] = 1\n    return processed\n\n\ndef rle_encode(mask):\n    pixel = mask.flatten()\n    pixel = np.concatenate([[0], pixel, [0]])\n    run = np.where(pixel[1:] != pixel[:-1])[0] + 1\n    run[1::2] -= run[::2]\n    rle = ' '.join(str(r) for r in run)\n    if rle == '':\n        rle = '1 0'\n    return rle\n\n#-------------------------------\n\n\ncheckpoint_file = \\\n    '/kaggle/working/checkpoints'\n   \nstate_dict = torch.load(checkpoint_file, map_location=lambda storage, loc: storage)['state_dict']\nprint(net.load_state_dict(state_dict, strict=False))  # True\n\nnet = net.eval()\nnet = net.cuda()\n\n\ndef dice_coefficient(pred, target):\n    intersection = np.sum(pred * target)\n    return (2. * intersection) / (np.sum(pred) + np.sum(target))\n\ndef iou(pred, target):\n    intersection = np.sum(pred * target)\n    union = np.sum(pred) + np.sum(target) - intersection\n    return intersection / union\n\ndef evaluate(predictions, ground_truths):\n    dice_scores = []\n    iou_scores = []\n\n    for pred, gt in zip(predictions, ground_truths):\n        dice_scores.append(dice_coefficient(pred, gt))\n        iou_scores.append(iou(pred, gt))\n    \n    return {\n        'Dice Coefficient': np.mean(dice_scores),\n        'IoU': np.mean(iou_scores)\n    }\n\n\n\ndef do_submit():\n    submission_df = []\n    predictions = []\n    ground_truths = []  # Load your ground truth masks here\n\n    for d in valid_meta:\n        volume = [cv2.imread(f, cv2.IMREAD_GRAYSCALE) for f in d.file]\n        volume = np.stack(volume)\n        D, H, W = volume.shape\n        \n        predict = np.zeros(d.shape, dtype=np.float16)\n        axes = [0, 1, 2]  # Axes to consider for TTA\n        for axis in axes:\n            loader = np.array_split(np.arange((D, H, W)[axis]), max(1, int((D, H, W)[axis] // cfg.batch_size)))\n            num_valid = len(loader)\n            \n            B = 0 \n            start_timer = timer()\n            for t in range(num_valid):\n                print(f'\\r validation: {t}/{num_valid}', time_to_str(timer() - start_timer, 'min'), end='', flush=True)\n\n                if axis == 0:\n                    image = volume[loader[t].tolist()]\n                if axis == 1:\n                    image = volume[:, loader[t].tolist()]\n                    image = image.transpose(1, 0, 2)\n                if axis == 2:\n                    image = volume[:, :, loader[t].tolist()]\n                    image = image.transpose(2, 0, 1)\n\n                batch_size, bh, bw = image.shape\n                m = image.reshape(batch_size, -1)\n                m = (m - m.min(keepdims=True)) / (m.max(keepdims=True) - m.min(keepdims=True) + 0.001)\n                m = m.reshape(batch_size, bh, bw)\n                m = np.ascontiguousarray(m)\n                image = torch.from_numpy(m).float().cuda().unsqueeze(1)\n\n                counter = 0\n                vessel, kidney = 0, 0\n                image = image.cuda() \n                with torch.cuda.amp.autocast(enabled=True):\n                    with torch.no_grad():\n                        v, k = net(image)\n                        vessel += v\n                        kidney += k\n                        counter += 1\n\n                        v, k = net(torch.flip(image, dims=[2,]))\n                        vessel += torch.flip(v, dims=[2,])\n                        kidney += torch.flip(k, dims=[2,])\n                        counter += 1\n\n                        v, k = net(torch.flip(image, dims=[3,]))\n                        vessel += torch.flip(v, dims=[3,])\n                        kidney += torch.flip(k, dims=[3,])\n                        counter += 1\n\n                        v, k = net(torch.rot90(image, k=1, dims=[2, 3]))\n                        vessel += torch.rot90(v, k=-1, dims=[2, 3])\n                        kidney += torch.rot90(k, k=-1, dims=[2, 3])\n                        counter += 1\n\n                        v, k = net(torch.rot90(image, k=2, dims=[2, 3]))\n                        vessel += torch.rot90(v, k=-2, dims=[2, 3])\n                        kidney += torch.rot90(k, k=-2, dims=[2, 3])\n                        counter += 1\n\n                        v, k = net(torch.rot90(image, k=3, dims=[2, 3]))\n                        vessel += torch.rot90(v, k=-3, dims=[2, 3])\n                        kidney += torch.rot90(k, k=-3, dims=[2, 3])\n                        counter += 1\n\n                vessel = vessel / counter\n                kidney = kidney / counter\n\n                vessel = vessel.float().data.cpu().numpy()\n                kidney = kidney.float().data.cpu().numpy()\n\n                batch_size = len(vessel)\n                for b in range(batch_size):\n                    mk = kidney[b, 0]\n                    mk = choose_biggest_object(mk, threshold=0.5)\n                    mv = vessel[b, 0]\n                    p = (mv * mk)\n                    if axis == 0:\n                        predict[B + b] += p\n                    if axis == 1:\n                        predict[:, B + b] += p\n                    if axis == 2:\n                        predict[:, :, B + b] += p\n\n                B += batch_size\n\n        predict = predict / len(axes)\n        predict = (predict > cfg.p_threshold).astype(np.uint8)\n\n        if cfg.cc_threshold > 0:\n            predict = cc3d.dust(\n                predict,\n                connectivity=26,\n                threshold=cfg.cc_threshold,\n                in_place=False\n            )\n\n        rle = [rle_encode(p) for p in predict]\n        predictions.append(predict)  # Store predictions for evaluation\n        ground_truths.append(ground_truth)  # Store corresponding ground truth\n\n        submission_df.append(\n            pd.DataFrame(data={\n                'id': d['id'],\n                'rle': rle,\n            })\n        )\n\n    submission_df = pd.concat(submission_df)\n    submission_df.to_csv('submission.csv', index=False)\n    print(submission_df)\n    \n    # Evaluate the predictions\n    metrics = evaluate(predictions, ground_truths)\n    print(\"Evaluation Metrics:\")\n    for metric, score in metrics.items():\n        print(f\"{metric}: {score}\")\n\n\nglob_file = glob(f'{data_dir}/test/kidney_5/images/*.tif')\n\ndo_submit()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}