{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":30201,"databundleVersionId":2750748,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":11936208,"sourceType":"datasetVersion","datasetId":7504326},{"sourceId":410648,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":335323,"modelId":356344},{"sourceId":412035,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":336400,"modelId":357394}],"dockerImageVersionId":31041,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport random\n\nimport pandas as pd\nimport numpy as np\n\nimport colorsys\nimport cv2\nimport albumentations as A\nfrom tqdm.auto import tqdm\n\nimport torch\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\n\nimport matplotlib.pyplot as plt\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision\nfrom torchvision.models.detection.mask_rcnn import MaskRCNNPredictor\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:34.286000Z","iopub.execute_input":"2025-05-26T11:48:34.286538Z","iopub.status.idle":"2025-05-26T11:48:34.290888Z","shell.execute_reply.started":"2025-05-26T11:48:34.286511Z","shell.execute_reply":"2025-05-26T11:48:34.290349Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!mkdir -p /root/.cache/torch/hub/checkpoints/\n!cp ../kaggle/input/resnet50-0676ba61/pytorch/default/1/resnet50-0676ba61.pth /root/.cache/torch/hub/checkpoints/resnet50-0676ba61.pth\n#!pip install ../input/segmentation-models-wheels/pretrainedmodels-0.7.4-py3-none-any.whl","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:37.670703Z","iopub.execute_input":"2025-05-26T11:48:37.670967Z","iopub.status.idle":"2025-05-26T11:48:37.983708Z","shell.execute_reply.started":"2025-05-26T11:48:37.670946Z","shell.execute_reply":"2025-05-26T11:48:37.982953Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#!wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/engine.py\n#!wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/utils.py\n#!wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/transforms.py\n#!wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/coco_eval.py\n#!wget https://raw.githubusercontent.com/pytorch/vision/main/references/detection/coco_utils.py","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:28.041369Z","iopub.status.idle":"2025-05-26T11:48:28.041651Z","shell.execute_reply.started":"2025-05-26T11:48:28.041537Z","shell.execute_reply":"2025-05-26T11:48:28.041549Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sys\nsys.path.append('/kaggle/input/ccetutil')\n# sys.path.append('/kaggle/input/resnet50-0676ba61/pytorch/default/1')\nimport transforms\nimport utils\nimport coco_utils\nimport coco_eval\nimport transforms","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:41.285317Z","iopub.execute_input":"2025-05-26T11:48:41.285609Z","iopub.status.idle":"2025-05-26T11:48:41.290320Z","shell.execute_reply.started":"2025-05-26T11:48:41.285583Z","shell.execute_reply":"2025-05-26T11:48:41.289523Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def random_colors(N, bright=True):\n    \"\"\"\n    Generate random colors.\n    To get visually distinct colors, generate them in HSV space then\n    convert to RGB.\n    \"\"\"\n    brightness = 1.0 if bright else 0.7\n    hsv = [(i / N, 1, brightness) for i in range(N)]\n    colors = list(map(lambda c: colorsys.hsv_to_rgb(*c), hsv))\n    random.shuffle(colors)\n    return colors","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:44.516426Z","iopub.execute_input":"2025-05-26T11:48:44.517036Z","iopub.status.idle":"2025-05-26T11:48:44.521673Z","shell.execute_reply.started":"2025-05-26T11:48:44.517014Z","shell.execute_reply":"2025-05-26T11:48:44.520908Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## decode_rle_mask","metadata":{}},{"cell_type":"code","source":"def decode_rle_mask(rle_mask, shape=(520, 704)):\n\n    \"\"\"\n    Decode run-length encoded segmentation mask string into 2d array\n\n    Parameters\n    ----------\n    rle_mask (str): Run-length encoded segmentation mask string\n    shape (tuple): Height and width of the mask\n\n    Returns\n    -------\n    mask [numpy.ndarray of shape (height, width)]: Decoded 2d segmentation mask\n    \"\"\"\n\n    rle_mask = rle_mask.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (rle_mask[0:][::2], rle_mask[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n\n    mask = np.zeros((shape[0] * shape[1]), dtype=np.uint8)\n    for start, end in zip(starts, ends):\n        mask[start:end] = 1\n\n    mask = mask.reshape(shape[0], shape[1])\n    mask = np.uint8(mask)\n    return mask\n\n\ndef encode_rle_mask(mask, shape=(520, 704)):\n    pixels = mask.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    rle = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    rle[1::2] -= rle[::2]\n    return rle.tolist()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:47.799679Z","iopub.execute_input":"2025-05-26T11:48:47.799941Z","iopub.status.idle":"2025-05-26T11:48:47.806696Z","shell.execute_reply.started":"2025-05-26T11:48:47.799921Z","shell.execute_reply":"2025-05-26T11:48:47.805886Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = pd.read_csv('../input/sartorius-cell-instance-segmentation/train.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:51.611459Z","iopub.execute_input":"2025-05-26T11:48:51.612036Z","iopub.status.idle":"2025-05-26T11:48:51.977676Z","shell.execute_reply.started":"2025-05-26T11:48:51.612006Z","shell.execute_reply":"2025-05-26T11:48:51.976981Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_bboxes_from_mask(masks):\n    coco_boxes = []\n    for mask in masks:\n        pos = np.nonzero(mask)\n        xmin = np.min(pos[1])\n        xmax = np.max(pos[1])\n        ymin = np.min(pos[0])\n        ymax = np.max(pos[0])\n        coco_boxes.append([xmin, ymin, xmax, ymax])\n    coco_boxes = np.asarray(coco_boxes)\n    return coco_boxes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:54.382586Z","iopub.execute_input":"2025-05-26T11:48:54.383166Z","iopub.status.idle":"2025-05-26T11:48:54.387585Z","shell.execute_reply.started":"2025-05-26T11:48:54.383145Z","shell.execute_reply":"2025-05-26T11:48:54.386779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cls_map = {value:idx for idx, value in enumerate(train_df['cell_type'].unique())}\ncls_map_reversed = {cls_map[key]: key for key in cls_map.keys()}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:57.462178Z","iopub.execute_input":"2025-05-26T11:48:57.462748Z","iopub.status.idle":"2025-05-26T11:48:57.469886Z","shell.execute_reply.started":"2025-05-26T11:48:57.462726Z","shell.execute_reply":"2025-05-26T11:48:57.469136Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cls_map","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:01.265774Z","iopub.execute_input":"2025-05-26T11:49:01.266276Z","iopub.status.idle":"2025-05-26T11:49:01.271140Z","shell.execute_reply.started":"2025-05-26T11:49:01.266252Z","shell.execute_reply":"2025-05-26T11:49:01.270467Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_targets_mask(df, img_id):\n    targets = df[df['id'] == img_id]['cell_type'].apply(lambda x: cls_map[x]).values\n    rles = df[df['id'] == img_id]['annotation'].values\n    return targets, rles","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:03.805722Z","iopub.execute_input":"2025-05-26T11:49:03.805998Z","iopub.status.idle":"2025-05-26T11:49:03.810357Z","shell.execute_reply.started":"2025-05-26T11:49:03.805977Z","shell.execute_reply":"2025-05-26T11:49:03.809607Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def apply_mask(image, mask, color, alpha=0.5):\n    \"\"\"Apply the given mask to the image.\n    \"\"\"\n    for c in range(3):\n        image[:, :, c] = np.where(mask == 1,\n                                  image[:, :, c] *\n                                  (1 - alpha) + alpha * color[c] * 255,\n                                  image[:, :, c])\n    return image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:07.823708Z","iopub.execute_input":"2025-05-26T11:49:07.824282Z","iopub.status.idle":"2025-05-26T11:49:07.828563Z","shell.execute_reply.started":"2025-05-26T11:49:07.824258Z","shell.execute_reply":"2025-05-26T11:49:07.827733Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_image_annotations(image, masks, bboxes, labels, aug=None):\n    image = image.copy()\n    \n    colors = {unique_lbl:random_colors(1, True)[0] for unique_lbl in np.unique(labels)}\n    \n    if aug is not None:\n        augmented = aug(image=image, masks=masks, bboxes=bboxes,\n                        labels=labels)\n        image = augmented['image']\n        masks = augmented['masks']\n        bboxes = augmented['bboxes']\n    \n    bboxes = np.stack(bboxes).astype(int)\n        \n    for idx, box in enumerate(bboxes):\n        color = tuple([int(value*255) for value in colors[labels[idx]]])\n        image = cv2.rectangle(image, (box[2], box[3]), (box[0], box[1]), color=color, thickness=1)\n    \n    for idx, mask in enumerate(masks):\n        color = colors[labels[idx]]\n        image = apply_mask(image, mask, color)\n    \n    plt.figure(figsize=(15, 15))\n    plt.imshow(image)\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:10.814058Z","iopub.execute_input":"2025-05-26T11:49:10.814878Z","iopub.status.idle":"2025-05-26T11:49:10.821154Z","shell.execute_reply.started":"2025-05-26T11:49:10.814840Z","shell.execute_reply":"2025-05-26T11:49:10.820477Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# from IPython.core.interactiveshell import InteractiveShell\n# InteractiveShell.ast_node_interactivity = \"all\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:28.055661Z","iopub.status.idle":"2025-05-26T11:48:28.055933Z","shell.execute_reply.started":"2025-05-26T11:48:28.055777Z","shell.execute_reply":"2025-05-26T11:48:28.055791Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:14.883177Z","iopub.execute_input":"2025-05-26T11:49:14.883453Z","iopub.status.idle":"2025-05-26T11:49:14.893857Z","shell.execute_reply.started":"2025-05-26T11:49:14.883435Z","shell.execute_reply":"2025-05-26T11:49:14.893116Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img_id = train_df.iloc[0]['id']\nimg = cv2.imread(f'../input/sartorius-cell-instance-segmentation/train/{img_id}.png')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:17.873460Z","iopub.execute_input":"2025-05-26T11:49:17.873735Z","iopub.status.idle":"2025-05-26T11:49:17.887903Z","shell.execute_reply.started":"2025-05-26T11:49:17.873715Z","shell.execute_reply":"2025-05-26T11:49:17.887184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(img)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:21.082646Z","iopub.execute_input":"2025-05-26T11:49:21.083362Z","iopub.status.idle":"2025-05-26T11:49:21.350654Z","shell.execute_reply.started":"2025-05-26T11:49:21.083339Z","shell.execute_reply":"2025-05-26T11:49:21.349848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels, rles = get_targets_mask(train_df, img_id)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:25.571452Z","iopub.execute_input":"2025-05-26T11:49:25.571715Z","iopub.status.idle":"2025-05-26T11:49:25.587156Z","shell.execute_reply.started":"2025-05-26T11:49:25.571696Z","shell.execute_reply":"2025-05-26T11:49:25.586481Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(rles)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:28.602070Z","iopub.execute_input":"2025-05-26T11:49:28.602366Z","iopub.status.idle":"2025-05-26T11:49:28.606998Z","shell.execute_reply.started":"2025-05-26T11:49:28.602344Z","shell.execute_reply":"2025-05-26T11:49:28.606480Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mask = decode_rle_mask(rles[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:31.062820Z","iopub.execute_input":"2025-05-26T11:49:31.063081Z","iopub.status.idle":"2025-05-26T11:49:31.066829Z","shell.execute_reply.started":"2025-05-26T11:49:31.063063Z","shell.execute_reply":"2025-05-26T11:49:31.066305Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(mask)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:35.170398Z","iopub.execute_input":"2025-05-26T11:49:35.170675Z","iopub.status.idle":"2025-05-26T11:49:35.361510Z","shell.execute_reply.started":"2025-05-26T11:49:35.170656Z","shell.execute_reply":"2025-05-26T11:49:35.360875Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mask.flatten()[1::2].shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:39.150720Z","iopub.execute_input":"2025-05-26T11:49:39.150992Z","iopub.status.idle":"2025-05-26T11:49:39.156372Z","shell.execute_reply.started":"2025-05-26T11:49:39.150972Z","shell.execute_reply":"2025-05-26T11:49:39.155584Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mask.flatten().shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:41.489496Z","iopub.execute_input":"2025-05-26T11:49:41.489761Z","iopub.status.idle":"2025-05-26T11:49:41.494746Z","shell.execute_reply.started":"2025-05-26T11:49:41.489741Z","shell.execute_reply":"2025-05-26T11:49:41.494030Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mask = decode_rle_mask(str(encode_rle_mask(mask)).replace('[', '').replace(']', '').replace(',', ''))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:44.410610Z","iopub.execute_input":"2025-05-26T11:49:44.410870Z","iopub.status.idle":"2025-05-26T11:49:44.415759Z","shell.execute_reply.started":"2025-05-26T11:49:44.410851Z","shell.execute_reply":"2025-05-26T11:49:44.415106Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(mask)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:47.604934Z","iopub.execute_input":"2025-05-26T11:49:47.605625Z","iopub.status.idle":"2025-05-26T11:49:47.796101Z","shell.execute_reply.started":"2025-05-26T11:49:47.605599Z","shell.execute_reply":"2025-05-26T11:49:47.795252Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"masks = []\nfor mask in train_df.loc[train_df['id'] == img_id, 'annotation'].values:\n    decoded_mask = decode_rle_mask(rle_mask=mask, shape=img.shape)\n    masks.append(decoded_mask)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:51.282807Z","iopub.execute_input":"2025-05-26T11:49:51.283075Z","iopub.status.idle":"2025-05-26T11:49:51.427091Z","shell.execute_reply.started":"2025-05-26T11:49:51.283056Z","shell.execute_reply":"2025-05-26T11:49:51.426483Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bboxes = get_bboxes_from_mask(masks)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:28.072315Z","iopub.status.idle":"2025-05-26T11:48:28.072595Z","shell.execute_reply.started":"2025-05-26T11:48:28.072436Z","shell.execute_reply":"2025-05-26T11:48:28.072447Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## plot_image_annotations","metadata":{}},{"cell_type":"code","source":"plot_image_annotations(image=img, masks=masks, bboxes=bboxes, labels=labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:49:55.112297Z","iopub.execute_input":"2025-05-26T11:49:55.112550Z","iopub.status.idle":"2025-05-26T11:49:57.301399Z","shell.execute_reply.started":"2025-05-26T11:49:55.112533Z","shell.execute_reply":"2025-05-26T11:49:57.300410Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_augmentations = A.Compose([\n    A.Resize(640, 640),\n    # A.RandomResizedCrop(640, 640, scale=(0.8, 1.0), ratio=(0.9, 1.3)),\n    A.HorizontalFlip(),\n    A.VerticalFlip(),\n    A.RandomRotate90()\n], bbox_params={\"format\": \"pascal_voc\", \"min_area\": 0, \"min_visibility\": 0, 'label_fields': ['labels']})\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:50:03.254122Z","iopub.execute_input":"2025-05-26T11:50:03.254744Z","iopub.status.idle":"2025-05-26T11:50:03.260768Z","shell.execute_reply.started":"2025-05-26T11:50:03.254717Z","shell.execute_reply":"2025-05-26T11:50:03.260162Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_image_annotations(image=img, masks=masks, bboxes=bboxes, labels=labels, aug=train_augmentations)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:50:05.410541Z","iopub.execute_input":"2025-05-26T11:50:05.411088Z","iopub.status.idle":"2025-05-26T11:50:08.527987Z","shell.execute_reply.started":"2025-05-26T11:50:05.411067Z","shell.execute_reply":"2025-05-26T11:50:08.527274Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## CellSegData","metadata":{}},{"cell_type":"code","source":"class CellSegData(torch.utils.data.Dataset):\n    def __init__(self, root, df, split='train', aug=None, cls_map=None):\n        self.augmentations = aug\n        self.cls_map = cls_map\n\n        train, test = train_test_split(df['id'].unique(), train_size=0.9, random_state=1)\n        if split == 'train':\n            self.dataset = train\n        else:\n            self.dataset = test\n\n        self.dict_df = {img_id: df[df['id'] == img_id] for img_id in tqdm(self.dataset)}\n        self.root = root\n        #print(test)\n        #print(type(self.dict_df))\n\n    def __len__(self):\n        return len(self.dataset)\n\n    def __getitem__(self, index):\n        img_id = self.dataset[index]\n        image = cv2.imread(os.path.join(self.root, img_id + '.png'))\n        \n        # print('index', index, 'img_id', img_id)   # index 295 img_id 541d7fd43b66\n\n        info = self.dict_df[img_id]\n        n_objects = len(info['annotation'])\n\n        labels = info['cell_type'].apply(lambda x: self.cls_map[x]).values\n        rles = info['annotation'].values\n\n        masks = []\n        for mask in rles:\n            decoded_mask = decode_rle_mask(rle_mask=mask, shape=image.shape)\n            masks.append(decoded_mask)\n\n        bboxes = get_bboxes_from_mask(masks)\n\n        if self.augmentations is not None:\n            augmented = self.augmentations(image=image, masks=masks, bboxes=bboxes,\n                                           labels=labels)\n            image = augmented['image']\n            masks = augmented['masks']\n            bboxes = augmented['bboxes']\n            bboxes = np.stack(bboxes).astype(int)\n\n        masks = np.asarray(masks)\n\n        bboxes = torch.as_tensor(bboxes, dtype=torch.int64)\n\n        is_bad_labels = False\n        degenerate_boxes = bboxes[:, 2:] <= bboxes[:, :2]\n        if degenerate_boxes.any():\n            is_bad_labels = True\n            # print the first degenerate box\n            bb_idxs = torch.where(degenerate_boxes.any(dim=1))[0].numpy()\n\n        labels = torch.as_tensor([1 for i in range(len(bboxes))], dtype=torch.int64)\n        masks = torch.as_tensor(masks, dtype=torch.uint8)\n\n        if is_bad_labels:\n            bboxes = bboxes[[i for i in range(len(bboxes)) if i not in bb_idxs]]\n            labels = labels[[i for i in range(len(bboxes)) if i not in bb_idxs]]\n            masks = masks[[i for i in range(len(bboxes)) if i not in bb_idxs]]\n\n        image_id = torch.tensor([index])\n        area = (bboxes[:, 3] - bboxes[:, 1]) * (bboxes[:, 2] - bboxes[:, 0])\n        iscrowd = torch.zeros((n_objects,), dtype=torch.int64)\n\n    \n        #print('image_id', image_id)\n        \n        # This is the required target for the Mask R-CNN\n        target = {\n            'boxes': bboxes,\n            'labels': labels,\n            'masks': masks,\n            'image_id': image_id,\n            'area': area,\n            'iscrowd': iscrowd\n        }\n\n        image = image.transpose((2, 0, 1))\n        return torch.Tensor(image), target, img_id","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:50:12.539002Z","iopub.execute_input":"2025-05-26T11:50:12.539304Z","iopub.status.idle":"2025-05-26T11:50:12.550599Z","shell.execute_reply.started":"2025-05-26T11:50:12.539282Z","shell.execute_reply":"2025-05-26T11:50:12.549922Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def analyze_train_sample(model, ds_train, sample_index):\n    img, targets = ds_train[sample_index]\n    plt.imshow(img.numpy().astype(np.uint8).transpose((1, 2, 0)))\n    plt.title(\"Image\")\n    plt.show()\n\n    masks = np.zeros((640, 640))\n    for mask in targets['masks']:\n        masks = np.logical_or(masks, mask)\n    plt.imshow(img.numpy().transpose((1, 2, 0)))\n    plt.imshow(masks, alpha=0.3)\n    plt.title(\"Ground truth\")\n    plt.show()\n\n    model.eval()\n    with torch.no_grad():\n        preds = model([img.cuda()])[0]\n\n    plt.imshow(img.cpu().numpy().transpose((1, 2, 0)))\n    all_preds_masks = np.zeros((640, 640))\n    for mask in preds['masks'].cpu().detach().numpy():\n        all_preds_masks = np.logical_or(all_preds_masks, mask[0] > 0.5)\n    plt.imshow(all_preds_masks, alpha=0.4)\n    plt.title(\"Predictions\")\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:28.078631Z","iopub.status.idle":"2025-05-26T11:48:28.078825Z","shell.execute_reply.started":"2025-05-26T11:48:28.078731Z","shell.execute_reply":"2025-05-26T11:48:28.078739Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## model","metadata":{}},{"cell_type":"code","source":"from IPython.core.interactiveshell import InteractiveShell\nInteractiveShell.ast_node_interactivity = \"last\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:28.079719Z","iopub.status.idle":"2025-05-26T11:48:28.079979Z","shell.execute_reply.started":"2025-05-26T11:48:28.079867Z","shell.execute_reply":"2025-05-26T11:48:28.079878Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Override pythorch checkpoint with an \"offline\" version of the file\n!mkdir -p /root/.cache/torch/hub/checkpoints/\n\n!cp /kaggle/input/resnet50-0676ba61/pytorch/default/1/resnet50-0676ba61.pth /root/.cache/torch/hub/checkpoints/resnet50-0676ba61.pth","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:50:17.963695Z","iopub.execute_input":"2025-05-26T11:50:17.964401Z","iopub.status.idle":"2025-05-26T11:50:18.487855Z","shell.execute_reply.started":"2025-05-26T11:50:17.964377Z","shell.execute_reply":"2025-05-26T11:50:18.487016Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_epochs = 2\n\ndevice = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n\n# our dataset has two classes only - background and person\n# use our dataset and defined transformations\ndataset = CellSegData('../input/sartorius-cell-instance-segmentation/train', train_df, 'train', train_augmentations, cls_map)\ndataset_test = CellSegData('../input/sartorius-cell-instance-segmentation/train', train_df, 'test', train_augmentations, cls_map)\n\n# define training and validation data loaders\ndata_loader = torch.utils.data.DataLoader(\n    dataset, batch_size=2, shuffle=True, num_workers=2, prefetch_factor=2, collate_fn=utils.collate_fn)\n\ndata_loader_test = torch.utils.data.DataLoader(\n    dataset_test, batch_size=1, shuffle=False, num_workers=4, collate_fn=utils.collate_fn)\n\nNUM_CLASSES = 2\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:50:24.374492Z","iopub.execute_input":"2025-05-26T11:50:24.375031Z","iopub.status.idle":"2025-05-26T11:50:27.929302Z","shell.execute_reply.started":"2025-05-26T11:50:24.375003Z","shell.execute_reply":"2025-05-26T11:50:27.928472Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=False, box_detections_per_img=600)\n\n# model = torch.load('/kaggle/input/resnet50-0676ba61/pytorch/default/1/resnet50-0676ba61.pth')                  \n# print(type(model))\n# model.load_state_dict(model)\n# # Получить roi_heads\n# roi_heads = model.roi_heads\n\nmodel = torch.load('/kaggle/input/model/pytorch/default/1/model.pth', weights_only=False)\nprint(type(model))\n\n# get the number of input features for the classifier\nin_features = model.roi_heads.box_predictor.cls_score.in_features\n# replace the pre-trained head with a new one\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, NUM_CLASSES)\n\n# now get the number of input features for the mask classifier\nin_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels\nhidden_layer = 256\n# and replace the mask predictor with a new one\nmodel.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask, hidden_layer, NUM_CLASSES)\n# weights = torch.load('weights/checkpoint.pth')\n# move model to the right device\n# model.state_dict(weights['model'])\nmodel.to(device)\n\n# construct an optimizer\nparams = [p for p in model.parameters() if p.requires_grad]\noptimizer = torch.optim.AdamW(params, lr=0.0001)\n# optimizer.load_state_dict(weights['optimizer'])\n# and a learning rate scheduler\nlr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer,\n                                                step_size=3,\n                                                gamma=0.1)\noutput_dir = 'weights'\nos.makedirs(output_dir, exist_ok=True)\n\nfor epoch in tqdm(range(num_epochs)):\n    # train for one epoch, printing every 10 iterations\n    model.train()\n    metric_logger = utils.MetricLogger(delimiter=\"  \")\n    metric_logger.add_meter(\"lr\", utils.SmoothedValue(window_size=1, fmt=\"{value:.6f}\"))\n    header = f\"Epoch: [{epoch}]\"\n\n    lr_scheduler = None\n    if epoch == 0:\n        warmup_factor = 1.0 / 1000\n        warmup_iters = min(1000, len(data_loader) - 1)\n\n        lr_scheduler = torch.optim.lr_scheduler.LinearLR(\n            optimizer, start_factor=warmup_factor, total_iters=warmup_iters\n        )\n\n    for images, targets, _ in metric_logger.log_every(data_loader, 10, header):\n        images = list(image.to(device) for image in images)\n        targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\n        loss_dict = model(images, targets)\n\n        losses = sum(loss for loss in loss_dict.values())\n\n        # reduce losses over all GPUs for logging purposes\n        loss_dict_reduced = utils.reduce_dict(loss_dict)\n        losses_reduced = sum(loss for loss in loss_dict_reduced.values())\n\n        loss_value = losses_reduced.item()\n\n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n\n        if lr_scheduler is not None:\n            lr_scheduler.step()\n\n        metric_logger.update(loss=losses_reduced, **loss_dict_reduced)\n        metric_logger.update(lr=optimizer.param_groups[0][\"lr\"])\n\n    if output_dir:\n        checkpoint = {\n            \"model\": model.state_dict(),\n            \"optimizer\": optimizer.state_dict(),\n            \"epoch\": epoch,\n        }\n        utils.save_on_master(checkpoint, os.path.join(output_dir, f\"model_{epoch}.pth\"))\n        utils.save_on_master(checkpoint, os.path.join(output_dir, \"checkpoint.pth\"))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:50:32.360611Z","iopub.execute_input":"2025-05-26T11:50:32.361133Z","iopub.status.idle":"2025-05-26T11:57:16.240837Z","shell.execute_reply.started":"2025-05-26T11:50:32.361113Z","shell.execute_reply":"2025-05-26T11:57:16.239658Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Загрузка модели","metadata":{}},{"cell_type":"code","source":"#checkpoint = torch.load('/Users/olegfadeev/Downloads/CV-7. Сегментация. Часть II/ipynb/weights/checkpoint.pth', map_location=torch.device(\"cpu\"), weights_only=True)\n\n#model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=False, box_detections_per_img=600)\n# get the number of input features for the classifier\n#in_features = model.roi_heads.box_predictor.cls_score.in_features\n# replace the pre-trained head with a new one\n#model.roi_heads.box_predictor = FastRCNNPredictor(in_features, NUM_CLASSES)\n\n# now get the number of input features for the mask classifier\n#in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels\n#hidden_layer = 256\n# and replace the mask predictor with a new one\n#model.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask, hidden_layer, NUM_CLASSES)\n\n# model = torchvision.models.detection.maskrcnn_resnet50_fpn()\n#model.load_state_dict(checkpoint['model'])\n#model.eval()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:48:28.086139Z","iopub.status.idle":"2025-05-26T11:48:28.086406Z","shell.execute_reply.started":"2025-05-26T11:48:28.086279Z","shell.execute_reply":"2025-05-26T11:48:28.086289Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Valuation","metadata":{}},{"cell_type":"code","source":"MASK_THRESHOLD = 0.5\nMIN_SCORE = 0.59\nWIDTH = 704\nHEIGHT = 520\n\ndef remove_overlapping_pixels(mask, other_masks):\n    for other_mask in other_masks:\n        if np.sum(np.logical_and(mask, other_mask)) > 0:\n            mask[np.logical_and(mask, other_mask)] = 0\n    return mask\n\ndef rle_encoding(x):\n    dots = np.where(x.flatten() == 1)[0]\n    run_lengths = []\n    prev = -2\n    for b in dots:\n        if (b>prev+1): run_lengths.extend((b + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n    return ' '.join(map(str, run_lengths))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:57:21.439208Z","iopub.execute_input":"2025-05-26T11:57:21.439905Z","iopub.status.idle":"2025-05-26T11:57:21.445528Z","shell.execute_reply.started":"2025-05-26T11:57:21.439875Z","shell.execute_reply":"2025-05-26T11:57:21.444834Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision.transforms import functional as F\n\nclass CellTestDataset(Dataset):\n    def __init__(self, image_dir, transforms=None):\n        self.transforms = transforms\n        self.image_dir = image_dir\n        self.image_ids = [f[:-4]for f in os.listdir(self.image_dir)]\n\n    def __getitem__(self, idx):\n        image_id = self.image_ids[idx]\n        image_path = os.path.join(self.image_dir, image_id + '.png')\n        image = Image.open(image_path).convert(\"RGB\")\n\n        image = F.to_tensor(image)\n            \n        # print('image', image.shape, type(image), image)\n        return {'image': image, 'image_id': image_id}\n\n    def __len__(self):\n        return len(self.image_ids)\n\nTEST_PATH = \"../input/sartorius-cell-instance-segmentation/test\"\n\nds_test = CellTestDataset(TEST_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:57:25.235486Z","iopub.execute_input":"2025-05-26T11:57:25.235721Z","iopub.status.idle":"2025-05-26T11:57:25.243066Z","shell.execute_reply.started":"2025-05-26T11:57:25.235706Z","shell.execute_reply":"2025-05-26T11:57:25.242288Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval();\n\nsubmission = []\nfor sample in ds_test:\n    img = sample['image']\n    # print(img)\n    image_id = sample['image_id']\n    with torch.no_grad():\n        result = model([img.to(device)])[0]\n    # print(result)\n    previous_masks = []\n    for i, mask in enumerate(result[\"masks\"]):\n        \n        score = result[\"scores\"][i].cpu().item()\n        \n        mask = mask.cpu().numpy()\n        # print('mask', mask)\n        # Keep only highly likely pixels\n        binary_mask = mask > MASK_THRESHOLD\n        binary_mask = remove_overlapping_pixels(binary_mask, previous_masks)\n        previous_masks.append(binary_mask)\n        rle = rle_encoding(binary_mask)\n        submission.append((image_id, rle))\n        \n    \n    # Add empty prediction if no RLE was generated for this image\n    all_images_ids = [image_id for image_id, rle in submission]\n    if image_id not in all_images_ids:\n        submission.append((image_id, \"\"))\n\ndf_sub = pd.DataFrame(submission, columns=['id', 'predicted'])\ndf_sub.to_csv(\"submission.csv\", index=False)\ndf_sub.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-26T11:57:31.655320Z","iopub.execute_input":"2025-05-26T11:57:31.655591Z","iopub.status.idle":"2025-05-26T12:00:08.856116Z","shell.execute_reply.started":"2025-05-26T11:57:31.655572Z","shell.execute_reply":"2025-05-26T12:00:08.855522Z"}},"outputs":[],"execution_count":null}]}