{"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":"markdown","source":"## summary\n\n","metadata":{}},{"cell_type":"code","source":"\nfrom sklearn.metrics import roc_auc_score, accuracy_score, f1_score, log_loss\nimport pickle\nfrom torch.utils.data import DataLoader\nfrom torch.cuda.amp import autocast, GradScaler\nimport warnings\nimport sys\nimport pandas as pd\nimport os\nimport gc\nimport sys\nimport math\nimport time\nimport random\nimport shutil\nfrom pathlib import Path\nfrom contextlib import contextmanager\nfrom collections import defaultdict, Counter\nimport cv2\n\nimport scipy as sp\nimport numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\nfrom tqdm.auto import tqdm\nfrom functools import partial\n\nimport argparse\nimport importlib\nimport torch\nimport torch.nn as nn\nfrom torch.optim import Adam, SGD, AdamW\nimport torch.nn.functional as F\n\n\nimport datetime","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:49.774376Z","iopub.execute_input":"2023-09-27T07:14:49.775456Z","iopub.status.idle":"2023-09-27T07:14:53.372264Z","shell.execute_reply.started":"2023-09-27T07:14:49.775412Z","shell.execute_reply":"2023-09-27T07:14:53.371313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nfrom torch.utils.data import DataLoader, Dataset\nimport cv2\nimport torch\nimport os\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom albumentations import ImageOnlyTransform","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:53.374477Z","iopub.execute_input":"2023-09-27T07:14:53.375071Z","iopub.status.idle":"2023-09-27T07:14:54.545634Z","shell.execute_reply.started":"2023-09-27T07:14:53.375038Z","shell.execute_reply":"2023-09-27T07:14:54.544699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sys.path.append(\"/kaggle/input/resnet3d\")\nsys.path.append(\"/kaggle/input/resnet3d-v2/resnet3d_v2\")\n\nfrom resnet3d import generate_model\nfrom resnet3d_v2 import generate_model  as generate_model_v2","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:54.547108Z","iopub.execute_input":"2023-09-27T07:14:54.547459Z","iopub.status.idle":"2023-09-27T07:14:54.585148Z","shell.execute_reply.started":"2023-09-27T07:14:54.547427Z","shell.execute_reply":"2023-09-27T07:14:54.584278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## config","metadata":{}},{"cell_type":"code","source":"TH = 0.51\ntake_indices = [3, 4, 5, 6,7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]  # [5, 6, 24] # ","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:54.586396Z","iopub.execute_input":"2023-09-27T07:14:54.586804Z","iopub.status.idle":"2023-09-27T07:14:54.592384Z","shell.execute_reply.started":"2023-09-27T07:14:54.586766Z","shell.execute_reply":"2023-09-27T07:14:54.590339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nclass CFG:\n    \n    num_workers = 1\n    \n    in_chans = 20 # 65\n    # ============== training cfg =============\n    crop_size = 256\n    image_size = 256\n    stride = image_size // 2\n\n    batch_size = 4\n    \n    device =  torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n    valid_aug_list = [\n        ToTensorV2(transpose_mask=True),\n    ]\n","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:54.595822Z","iopub.execute_input":"2023-09-27T07:14:54.596595Z","iopub.status.idle":"2023-09-27T07:14:54.626751Z","shell.execute_reply.started":"2023-09-27T07:14:54.596558Z","shell.execute_reply":"2023-09-27T07:14:54.626110Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## helper","metadata":{}},{"cell_type":"code","source":"# ref.: https://www.kaggle.com/stainsby/fast-tested-rle\ndef rle(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = img.flatten()\n    # pixels = (pixels >= thr).astype(int)\n    \n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:54.628034Z","iopub.execute_input":"2023-09-27T07:14:54.628361Z","iopub.status.idle":"2023-09-27T07:14:54.643519Z","shell.execute_reply.started":"2023-09-27T07:14:54.628325Z","shell.execute_reply":"2023-09-27T07:14:54.642637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## model","metadata":{}},{"cell_type":"code","source":"class Decoder(nn.Module):\n    def __init__(self, encoder_dims, upscale):\n        super().__init__()\n        self.convs = nn.ModuleList([\n            nn.Sequential(\n                nn.Conv2d(encoder_dims[i]+encoder_dims[i-1], encoder_dims[i-1], 3, 1, 1, bias=False),\n                nn.BatchNorm2d(encoder_dims[i-1]),\n                nn.ReLU(inplace=True)\n            ) for i in range(1, len(encoder_dims))])\n\n        self.logit = nn.Conv2d(encoder_dims[0], 1, 1, 1, 0)\n        self.up = nn.Upsample(scale_factor=upscale, mode=\"bilinear\")\n\n    def forward(self, feature_maps):\n        for i in range(len(feature_maps)-1, 0, -1):\n            f_up = F.interpolate(feature_maps[i], scale_factor=2, mode=\"bilinear\")\n            f = torch.cat([feature_maps[i-1], f_up], dim=1)\n            f_down = self.convs[i-1](f)\n            feature_maps[i-1] = f_down\n\n        x = self.logit(feature_maps[0])\n        mask = self.up(x)\n        return mask\n\n\nclass SegModel(nn.Module):\n    def __init__(self, model_depth, gen_model_version=1):\n        super().__init__()\n        if gen_model_version == 1:\n            self.encoder = generate_model(model_depth=model_depth, n_input_channels=1)\n            self.decoder = Decoder(encoder_dims=[64, 128, 256, 512], upscale=4)\n        if gen_model_version == 2:\n            self.encoder = generate_model_v2(model_depth=model_depth, n_input_channels=1)\n            self.decoder = Decoder(encoder_dims=[256, 512, 1024, 2048], upscale=4)\n        \n        \n    def forward(self, x):\n        feat_maps = self.encoder(x)\n        feat_maps_pooled = [torch.mean(f, dim=2) for f in feat_maps]\n        pred_mask = self.decoder(feat_maps_pooled)\n        return pred_mask\n    \n    def load_pretrained_weights(self, state_dict):\n        # Convert 3 channel weights to single channel\n        # ref - https://timm.fast.ai/models#Case-1:-When-the-number-of-input-channels-is-1\n        conv1_weight = state_dict['conv1.weight']\n        state_dict['conv1.weight'] = conv1_weight.sum(dim=1, keepdim=True)\n        print(self.encoder.load_state_dict(state_dict, strict=False))","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:54.644877Z","iopub.execute_input":"2023-09-27T07:14:54.645736Z","iopub.status.idle":"2023-09-27T07:14:54.661628Z","shell.execute_reply.started":"2023-09-27T07:14:54.645704Z","shell.execute_reply":"2023-09-27T07:14:54.660672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## main","metadata":{}},{"cell_type":"code","source":"def read_fragment_and_binary_mask(fragment_id, z_start, z_end):\n    images = []\n\n    \n    idxs = range(z_start, z_end)\n\n    for i in tqdm(idxs):\n        \n        image = cv2.imread(f\"/kaggle/input/vesuvius-challenge-ink-detection/test/{fragment_id}/surface_volume/{i:02}.tif\", 0)\n        images.append(image)\n        \n        del image\n        gc.collect()\n    \n    fragment = np.stack(images, axis=2)\n    \n    \n    del images\n    gc.collect()\n    \n    binary_mask = cv2.imread(f\"/kaggle/input/vesuvius-challenge-ink-detection/test/{fragment_id}/mask.png\", 0)\n    binary_mask = (binary_mask / 255).astype(int)\n    \n    return fragment, binary_mask","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:54.662794Z","iopub.execute_input":"2023-09-27T07:14:54.663466Z","iopub.status.idle":"2023-09-27T07:14:54.674812Z","shell.execute_reply.started":"2023-09-27T07:14:54.663435Z","shell.execute_reply":"2023-09-27T07:14:54.674058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%capture \n!pip install --no-index --no-deps /kaggle/input/onnxruntime-wheel/onnxruntime_gpu-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:14:54.675856Z","iopub.execute_input":"2023-09-27T07:14:54.676702Z","iopub.status.idle":"2023-09-27T07:15:01.979158Z","shell.execute_reply.started":"2023-09-27T07:14:54.676672Z","shell.execute_reply":"2023-09-27T07:15:01.977925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import onnxruntime as ort\nfrom collections import OrderedDict\n\n\ndef get_pred_mask(fragment, binary_mask, crop_size, image_size, model_depth, model_weights, threshold, n_channels, model_indx, std, mean):\n    \n    \n    ## Prepare slices\n    \n    CFG.crop_size = crop_size\n    CFG.image_size = image_size\n    CFG.stride = image_size // 2\n    CFG.model_depth = model_depth\n    CFG.threshold = threshold\n\n    CFG.batch_size = 1\n\n    # pad with zeros to make the image dividable into tiles\n    ori_h = binary_mask.shape[0]\n    ori_w = binary_mask.shape[1]\n    pad0 = (CFG.crop_size - binary_mask.shape[0] % CFG.crop_size)\n    pad1 = (CFG.crop_size - binary_mask.shape[1] % CFG.crop_size)\n    binary_mask = np.pad(binary_mask, [(0, pad0), (0, pad1)], constant_values=0)\n    \n    mask_pred = np.zeros(binary_mask.shape)\n    mask_count = np.zeros(binary_mask.shape)\n\n    x1_list = list(range(0, fragment.shape[1]-CFG.crop_size+1, CFG.stride))\n    y1_list = list(range(0, fragment.shape[0]-CFG.crop_size+1, CFG.stride))\n\n    xyxys = []\n    for y1 in y1_list:\n        for x1 in x1_list:\n            y2 = y1 + CFG.crop_size\n            x2 = x1 + CFG.crop_size\n\n            xyxys.append((x1, y1, x2, y2))\n    xyxys = np.stack(xyxys)\n    \n    \n    ## Load model \n    \n    if model_indx != -1:\n        if model_indx == 5:\n            gen_model_version = 2\n        else:\n            gen_model_version = 1\n        \n        model = SegModel(model_depth, gen_model_version)\n        # load model_weights\n        state_dict = torch.load(model_weights)\n    \n        \n        new_state_dict = OrderedDict()\n        for k, v in state_dict.items():\n            # module, since it's trained DataParallel (even though we have only 1 machine, but still)\n            if 'module' in k:\n                k = k.replace('module.', '')\n            new_state_dict[k] = v\n        model.load_state_dict(new_state_dict)\n        model = model.to(CFG.device)\n        model.eval()\n        \n        \n        del state_dict, new_state_dict\n    \n    else:\n        # Models by Sumo are in ONNX format\n        sess_options = ort.SessionOptions()\n        ort_session = ort.InferenceSession(model_weights, sess_options=sess_options, providers=[(\"CUDAExecutionProvider\", {\"cudnn_conv_use_max_workspace\": '1'})])\n        \n        \n\n        \n    # Load normalizations (for Viktor's models)\n    \n    \n    valid_aug_list = [\n            A.Resize(CFG.image_size, CFG.image_size),\n            A.Normalize(\n                mean= [0] * n_channels,\n                std= [1] * n_channels\n            ),\n            ToTensorV2(transpose_mask=True),\n        ]\n    # Create the augmentation pipeline\n    augmentations = A.Compose(valid_aug_list)\n    \n    \n    \n    \n    for xy in tqdm(xyxys, total=len(xyxys)): #tqdm(enumerate(xyxys), total=len(xyxys)):\n        x1, y1, x2, y2 = xy\n        \n        if model_indx == 0 or model_indx == 3 or model_indx == 4 or model_indx == 5 or model_indx in [6, 7, 8, 9, 10, 11, 12, 13, 14, 15]:\n            image = fragment[y1:y2, x1:x2] / 255\n            # Channel-wise normalization from albumentations\n            augmented = augmentations(image=image)\n            image = augmented[\"image\"]\n            image = image.unsqueeze(0).unsqueeze(0).float()\n            image = image.to(CFG.device)\n            \n            \n        if model_indx == 1 or model_indx == 2:\n            # A simple pixel-wise normalization: x/max(x), such that each pixel is between 0 and 1\n            frag_crop = fragment[y1:y2, x1:x2]\n            frag_crop = torch.from_numpy(frag_crop.astype(np.float32)).unsqueeze(0).permute(0, 3, 1, 2)\n            frag_crop = frag_crop/65535.0\n            image = frag_crop\n            image = image.unsqueeze(0).float()\n            image = image.to(CFG.device)\n        \n        if model_indx == -1:\n            # Sumo normalized not across the z-axis (depth), but across xy axis. \n            \n            image = fragment[y1:y2, x1:x2] # / 256 # min: 0, max: 255, shape (768, 768, N_channels)\n            # calculate std and mean for each channel\n            # image = np.clip(image * std[None, None, :] + mean[None, None, :], 0, 255).astype(np.uint8) # min: 0, max: 255\n            image = (image - mean[None, None, :]) / std[None, None, :]\n            image = np.expand_dims(image, axis=0)\n            # got from (B, H, W, C) to (B, C, H, W)\n            image = np.transpose(image, (0, 3, 1, 2)).astype(np.float32)\n            \n            # image = torch.from_numpy(image.astype(np.float32))\n            # image = image.to(CFG.device)\n        \n        \n        \n        ## predictions\n        \n        if model_indx != -1:\n            with torch.no_grad():\n                y_preds = model(image)\n                torch.sigmoid_(y_preds)\n            \n            del image\n            y_preds = y_preds.cpu()\n        \n        if model_indx == -1:\n            # Assuming you have a numpy array 'input_data' representing your input\n            # input_data = np.random.randn(1, 15, 768, 768).astype(np.float32) # Modify this line according to your input shape\n\n            # Run the session\n            ort_inputs = {ort_session.get_inputs()[0].name: image}\n            ort_outs = ort_session.run(None, ort_inputs)\n            y_preds = ort_outs[0]\n            \n            # y_preds = model(image)\n            \n            del image\n            \n            \n            # apply nn.Upsample(scale_factor=upscale, mode=\"bilinear\") to y_preds\n            y_preds = torch.from_numpy(y_preds)\n            # y_preds = nn.Upsample(scale_factor=4, mode=\"bilinear\")(y_preds)\n            # use F.interpolate instead of nn.Upsample\n            y_preds = F.interpolate(y_preds, scale_factor=4, mode=\"bilinear\")            \n            y_preds = y_preds.squeeze().to('cpu').numpy()\n         \n        \n        ## prediction accumulation\n            \n        if model_indx != -1:\n            mask_pred[y1:y2, x1:x2] += y_preds.squeeze().numpy()\n        else:\n            mask_pred[y1:y2, x1:x2] += y_preds\n        mask_count[y1:y2, x1:x2] += 1 # np.ones((CFG.crop_size, CFG.crop_size))\n        \n        del y_preds\n        gc.collect()\n    \n    # return to original height and width\n    mask_pred = mask_pred[:ori_h, :ori_w]\n    mask_count = mask_count[:ori_h, :ori_w]\n    \n    # score averaging\n    mask_pred = mask_pred / mask_count\n    return mask_pred\n    \n    \n    ","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:01.980890Z","iopub.execute_input":"2023-09-27T07:15:01.981256Z","iopub.status.idle":"2023-09-27T07:15:02.635005Z","shell.execute_reply.started":"2023-09-27T07:15:01.981219Z","shell.execute_reply":"2023-09-27T07:15:02.634039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/vesuvius-all-models/ensemble_metadata.csv\")\n# remove rows where you see sumowork in model_name \n# df = df[~df['model_name'].str.contains('sumowork', case=False)]\ndf","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:02.636271Z","iopub.execute_input":"2023-09-27T07:15:02.636645Z","iopub.status.idle":"2023-09-27T07:15:02.680265Z","shell.execute_reply.started":"2023-09-27T07:15:02.636615Z","shell.execute_reply":"2023-09-27T07:15:02.679256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['model_weights_kaggle'] = df['model_weights'].apply(lambda x: x.split(\"/\")[-1])\ndf['model_weights_kaggle'] = \"/kaggle/input/vesuvius-all-models/all-models-v0/all-models-v0/\" + df[\"model_name\"]\ndf","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:02.681792Z","iopub.execute_input":"2023-09-27T07:15:02.682150Z","iopub.status.idle":"2023-09-27T07:15:02.711854Z","shell.execute_reply.started":"2023-09-27T07:15:02.682099Z","shell.execute_reply":"2023-09-27T07:15:02.710974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# take indices take_indices \ndf = df.loc[take_indices].reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:02.713452Z","iopub.execute_input":"2023-09-27T07:15:02.713869Z","iopub.status.idle":"2023-09-27T07:15:02.720939Z","shell.execute_reply.started":"2023-09-27T07:15:02.713835Z","shell.execute_reply":"2023-09-27T07:15:02.720065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:02.726383Z","iopub.execute_input":"2023-09-27T07:15:02.727205Z","iopub.status.idle":"2023-09-27T07:15:02.739727Z","shell.execute_reply.started":"2023-09-27T07:15:02.727165Z","shell.execute_reply":"2023-09-27T07:15:02.738554Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Decoder(nn.Module):\n    def __init__(self, encoder_dims, upscale):\n        super().__init__()\n        self.convs = nn.ModuleList([\n            nn.Sequential(\n                nn.Conv2d(encoder_dims[i]+encoder_dims[i-1], encoder_dims[i-1], 3, 1, 1, bias=False),\n                nn.BatchNorm2d(encoder_dims[i-1]),\n                nn.ReLU(inplace=True)\n            ) for i in range(1, len(encoder_dims))])\n\n        self.logit = nn.Conv2d(encoder_dims[0], 1, 1, 1, 0)\n        self.up = nn.Upsample(scale_factor=upscale, mode=\"bilinear\")\n\n    def forward(self, feature_maps):\n        for i in range(len(feature_maps)-1, 0, -1):\n            f_up = F.interpolate(feature_maps[i], scale_factor=2, mode=\"bilinear\")\n            f = torch.cat([feature_maps[i-1], f_up], dim=1)\n            f_down = self.convs[i-1](f)\n            feature_maps[i-1] = f_down\n\n        x = self.logit(feature_maps[0])\n        mask = self.up(x)\n        return mask\n\n\nclass SegModel(nn.Module):\n    def __init__(self, model_depth, gen_model_version=1):\n        super().__init__()\n        if gen_model_version == 1:\n            self.encoder = generate_model(model_depth=model_depth, n_input_channels=1)\n            self.decoder = Decoder(encoder_dims=[64, 128, 256, 512], upscale=4)\n        if gen_model_version == 2:\n            self.encoder = generate_model_v2(model_depth=model_depth, n_input_channels=1)\n            self.decoder = Decoder(encoder_dims=[256, 512, 1024, 2048], upscale=4)\n        \n        \n    def forward(self, x):\n        feat_maps = self.encoder(x)\n        feat_maps_pooled = [torch.mean(f, dim=2) for f in feat_maps]\n        pred_mask = self.decoder(feat_maps_pooled)\n        return pred_mask\n    \n    def load_pretrained_weights(self, state_dict):\n        # Convert 3 channel weights to single channel\n        # ref - https://timm.fast.ai/models#Case-1:-When-the-number-of-input-channels-is-1\n        conv1_weight = state_dict['conv1.weight']\n        state_dict['conv1.weight'] = conv1_weight.sum(dim=1, keepdim=True)\n        print(self.encoder.load_state_dict(state_dict, strict=False))","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:02.741603Z","iopub.execute_input":"2023-09-27T07:15:02.742222Z","iopub.status.idle":"2023-09-27T07:15:02.758120Z","shell.execute_reply.started":"2023-09-27T07:15:02.742143Z","shell.execute_reply":"2023-09-27T07:15:02.757179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def analyze_fragment(fragment_id, apply_threshold=True):\n    \n    print(f\"Analyzing fragment {fragment_id}\\n\\n\")\n    \n    n_models = 0\n    \n    _, binary_mask = read_fragment_and_binary_mask(fragment_id, z_start=0, z_end=2)\n    final_mask_pred = np.zeros_like(binary_mask, dtype=np.float32)\n    del _\n    gc.collect()\n    \n    \n    model_params = df.to_dict(orient='index')\n    \n    for indx  in model_params:\n        \n        \n        m_param = model_params[indx]\n        \n        \n        print(\"Model params:\", m_param)\n        \n        crop_size = m_param['crop_size']\n        image_size = m_param['image_size']\n        model_depth = m_param['model_depth'] if 'model_depth' in m_param else None\n        threshold = m_param['threshold'] if 'threshold' in m_param else None\n        # model_weights = m_param['model_weights']\n        model_weights = m_param['model_weights_kaggle']\n        z_start = m_param['z_start']\n        z_end = m_param['z_end']\n        n_channels = z_end - z_start\n        model_indx = m_param['model_indx']\n        \n        \n        fragment, binary_mask = read_fragment_and_binary_mask(fragment_id, z_start=z_start, z_end=z_end)\n        \n            \n        \n        \n        \n        print(f\"Min and max of fragment:\", fragment.min(), fragment.max())\n        \n        \n        \n        # Models by Sumo and Viktor expect different normalization\n        if model_indx == -1:\n            h, w, c = fragment.shape\n\n            std = []\n            mean = []\n            binary_mask_flattened = np.reshape(binary_mask, -1)\n            print(\"Calculating std and mean...\")\n            for channel in tqdm(range(c)):\n                fragment_channel = fragment[:, :, channel] \n                fragment_channel_flattened = np.reshape(fragment_channel, -1)\n\n                \n                fragment_channel_flattened = fragment_channel_flattened[binary_mask_flattened == 1]\n                std_channel = np.std(fragment_channel_flattened) \n                mean_channel = np.mean(fragment_channel_flattened)  \n                std.append(std_channel)\n                mean.append(mean_channel)\n                \n                \n            std = np.asarray(std) \n            mean = np.asarray(mean) \n            \n        else:\n            \n            std = None\n            mean = None\n            \n        \n        # Convert the array to np.uint16\n        fragment = fragment.astype(np.uint16)\n\n        # Then scale the array so that the maximum value is 65536\n        # Because the original maximum of np.uint8 is 255, you scale it up by multiplying with the ratio 65536/255\n        if model_indx != -1:\n            scale_factor = 65536 / 255\n            fragment = (fragment * scale_factor).astype(np.uint16)\n        else:\n            fragment = fragment.astype(np.uint16)\n        \n        \n        \n        mask_pred = get_pred_mask(fragment, binary_mask, crop_size, image_size, model_depth, model_weights, threshold, n_channels, model_indx, std, mean)\n        if apply_threshold:\n            mask_pred = (mask_pred >= threshold).astype(float)\n        \n        \n        mask_pred *= binary_mask\n        final_mask_pred += mask_pred\n        n_models += 1\n        \n        \n        \n        \n        del mask_pred, fragment\n        gc.collect()\n        \n        torch.cuda.empty_cache()\n        \n        \n    final_mask_pred /=  n_models\n    \n    return final_mask_pred\n        ","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:02.759762Z","iopub.execute_input":"2023-09-27T07:15:02.760111Z","iopub.status.idle":"2023-09-27T07:15:02.777122Z","shell.execute_reply.started":"2023-09-27T07:15:02.760082Z","shell.execute_reply":"2023-09-27T07:15:02.775979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fragment_ids = sorted(os.listdir(\"/kaggle/input/vesuvius-challenge-ink-detection/test\"))\nfragment_ids = fragment_ids[::-1]\nfragment_ids","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:02.778393Z","iopub.execute_input":"2023-09-27T07:15:02.778779Z","iopub.status.idle":"2023-09-27T07:15:02.799417Z","shell.execute_reply.started":"2023-09-27T07:15:02.778748Z","shell.execute_reply":"2023-09-27T07:15:02.798238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_fragment_1 = \"/kaggle/input/vesuvius-challenge-ink-detection/train/1/inklabels.png\"\nlabels_fragment_1 = cv2.imread(labels_fragment_1, 0)\nplt.imshow(labels_fragment_1)","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:02.800992Z","iopub.execute_input":"2023-09-27T07:15:02.801349Z","iopub.status.idle":"2023-09-27T07:15:05.219871Z","shell.execute_reply.started":"2023-09-27T07:15:02.801297Z","shell.execute_reply":"2023-09-27T07:15:05.218970Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nresults = []\nfor fragment_id in fragment_ids:\n\n    \n    # make prediction for each model\n    final_mask_pred_raw  = analyze_fragment(fragment_id, apply_threshold=False)\n    gc.collect()\n    \n    # apply thresholds\n    final_mask_pred_raw = (final_mask_pred_raw >= TH).astype(int)\n    \n    # get rle\n    inklabels_rle = rle(final_mask_pred_raw)\n    \n    plt.imshow(final_mask_pred_raw)\n    plt.show()\n\n    # save \n    results.append((fragment_id, inklabels_rle))\n    \n    ","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:15:05.221377Z","iopub.execute_input":"2023-09-27T07:15:05.221965Z","iopub.status.idle":"2023-09-27T07:20:22.928097Z","shell.execute_reply.started":"2023-09-27T07:15:05.221930Z","shell.execute_reply":"2023-09-27T07:20:22.925375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import numpy as np\n# from skimage import measure, morphology\n\n# # Let's assume `final_mask_pred_raw` is your prediction mask\n\n# # Label each connected region\n# labels = measure.label(final_mask_pred_raw)\n\n# # Iterate over each unique region\n# for region_id in np.unique(labels):\n#     # Skip the background\n#     if region_id == 0:\n#         continue\n    \n#     # Create a mask for the current region\n#     region_mask = (labels == region_id)\n\n#     # Check if the sum of the current region (equivalent to the area for binary image) is less than 20\n#     if region_mask.sum() < 10000:\n#         # If so, remove this region from the original mask\n#         final_mask_pred_raw = final_mask_pred_raw & ~region_mask\n\n# # Now final_mask_pred_raw will only contain regions of 1's that have an area of 20 or more\n","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.929507Z","iopub.status.idle":"2023-09-27T07:20:22.929962Z","shell.execute_reply.started":"2023-09-27T07:20:22.929730Z","shell.execute_reply":"2023-09-27T07:20:22.929752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plt.imshow(final_mask_pred_raw)","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.931524Z","iopub.status.idle":"2023-09-27T07:20:22.932283Z","shell.execute_reply.started":"2023-09-27T07:20:22.932028Z","shell.execute_reply":"2023-09-27T07:20:22.932052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plt.imshow(final_mask_pred_raw[850:950, 500+200:1000-200])","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.934013Z","iopub.status.idle":"2023-09-27T07:20:22.934610Z","shell.execute_reply.started":"2023-09-27T07:20:22.934301Z","shell.execute_reply":"2023-09-27T07:20:22.934323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# final_mask_pred_raw[850:950, 500+200:1000-200].sum()","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.936171Z","iopub.status.idle":"2023-09-27T07:20:22.936632Z","shell.execute_reply.started":"2023-09-27T07:20:22.936401Z","shell.execute_reply":"2023-09-27T07:20:22.936422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"sub = pd.DataFrame(results, columns=['Id', 'Predicted'])","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.938360Z","iopub.status.idle":"2023-09-27T07:20:22.938796Z","shell.execute_reply.started":"2023-09-27T07:20:22.938575Z","shell.execute_reply":"2023-09-27T07:20:22.938597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.940179Z","iopub.status.idle":"2023-09-27T07:20:22.940921Z","shell.execute_reply.started":"2023-09-27T07:20:22.940691Z","shell.execute_reply":"2023-09-27T07:20:22.940712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.942363Z","iopub.status.idle":"2023-09-27T07:20:22.943223Z","shell.execute_reply.started":"2023-09-27T07:20:22.942966Z","shell.execute_reply":"2023-09-27T07:20:22.942994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sample_sub = pd.read_csv('/kaggle/input/vesuvius-challenge-ink-detection/sample_submission.csv')\n# sample_sub = pd.merge(sample_sub[['Id']], sub, on='Id', how='left')\n# sample_sub","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.944744Z","iopub.status.idle":"2023-09-27T07:20:22.945194Z","shell.execute_reply.started":"2023-09-27T07:20:22.944958Z","shell.execute_reply":"2023-09-27T07:20:22.944979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sample_sub.to_csv(\"submission.csv\", index=False)\n","metadata":{"execution":{"iopub.status.busy":"2023-09-27T07:20:22.946880Z","iopub.status.idle":"2023-09-27T07:20:22.947353Z","shell.execute_reply.started":"2023-09-27T07:20:22.947105Z","shell.execute_reply":"2023-09-27T07:20:22.947127Z"},"trusted":true},"execution_count":null,"outputs":[]}]}