{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"! pip install \"../input/keras-application/Keras_Applications-1.0.8-py3-none-any.whl\"\n! pip install \"../input/efficientnet111/efficientnet-1.1.1-py3-none-any.whl\"\n! pip install \"../input/efficientnetpytorch\"\n! pip install \"../input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl\"\n! pip install \"../input/hpapytorchzoozip/pytorch_zoo-master\"\n! pip install \"../input/hpacellsegmentatormaster/HPA-Cell-Segmentation-master\"\n! pip install \"../input/tfexplainforoffline/tf_explain-0.2.1-py3-none-any.whl\"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IS_FINAL = True","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nimport os, gc, cv2\n\nimport torch\nimport torch.nn as nn\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn.functional as nnf\nimport sklearn\nfrom sklearn.metrics import confusion_matrix\nimport matplotlib.pyplot as plt\nimport gc\n\nfrom torch.autograd import Variable\nfrom tqdm.notebook import tqdm\n\nfrom efficientnet_pytorch import EfficientNet\n\nimport zlib\nimport base64\nfrom pycocotools import _mask as coco_mask\nimport random\nimport tensorflow as tf\n\n\n    \nimport os.path\nimport urllib\nimport zipfile\n\nimport scipy.ndimage as ndi\nfrom skimage import filters, measure, segmentation\nfrom skimage.morphology import (binary_erosion, closing, disk,\n                                remove_small_holes, remove_small_objects)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUM_CL = 19\n\nBATCH = 16\nEPOCHS = 15\n\nLR = 0.0001\nIM_SIZE = 256\n\nDEVICE = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nPATH = '/kaggle/input/'\nTRAIN_DIR = PATH + 'segmented-train/'\n# TEST_DIR = PATH + 'test/'\n","metadata":{"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nfrom tqdm import tqdm\n\nfrom hpacellseg.cellsegmentator import *\n\n\nclass CellSegmentator(object):\n    \"\"\"Uses pretrained DPN-Unet models to segment cells from images.\"\"\"\n\n    def __init__(\n        self,\n        nuclei_model=\"../input/hpacellsegmentatormodelweights/dpn_unet_nuclei_v1.pth\",\n        cell_model=\"../input/hpacellsegmentatormodelweights/dpn_unet_cell_3ch_v1.pth\",\n        scale_factor=1.0,\n        device=\"cuda\",\n        padding=False,\n        multi_channel_model=True,\n    ):\n        \"\"\"Class for segmenting nuclei and whole cells from confocal microscopy images.\n        It takes lists of images and returns the raw output from the\n        specified segmentation model. Models can be automatically\n        downloaded if they are not already available on the system.\n        When working with images from the Huan Protein Cell atlas, the\n        outputs from this class' methods are well combined with the\n        label functions in the utils module.\n        Note that for cell segmentation, there are two possible models\n        available. One that works with 2 channeled images and one that\n        takes 3 channels.\n        Keyword arguments:\n        nuclei_model -- A loaded torch nuclei segmentation model or the\n                        path to a file which contains such a model.\n                        If the argument is a path that points to a non-existant file,\n                        a pretrained nuclei_model is going to get downloaded to the\n                        specified path (default: './nuclei_model.pth').\n        cell_model -- A loaded torch cell segmentation model or the\n                      path to a file which contains such a model.\n                      The cell_model argument can be None if only nuclei\n                      are to be segmented (default: './cell_model.pth').\n        scale_factor -- How much to scale images before they are fed to\n                        segmentation models. Segmentations will be scaled back\n                        up by 1/scale_factor to match the original image\n                        (default: 0.25).\n        device -- The device on which to run the models.\n                  This should either be 'cpu' or 'cuda' or pointed cuda\n                  device like 'cuda:0' (default: 'cuda').\n        padding -- Whether to add padding to the images before feeding the\n                   images to the network. (default: False).\n        multi_channel_model -- Control whether to use the 3-channel cell model or not.\n                               If True, use the 3-channel model, otherwise use the\n                               2-channel version (default: True).\n        \"\"\"\n        if device != \"cuda\" and device != \"cpu\" and \"cuda\" not in device:\n            raise ValueError(f\"{device} is not a valid device (cuda/cpu)\")\n        if device != \"cpu\":\n            try:\n                assert torch.cuda.is_available()\n            except AssertionError:\n                print(\"No GPU found, using CPU.\", file=sys.stderr)\n                device = \"cpu\"\n        self.device = device\n\n        if isinstance(nuclei_model, str):\n            if not os.path.exists(nuclei_model):\n                print(\n                    f\"Could not find {nuclei_model}. Downloading it now\",\n                    file=sys.stderr,\n                )\n                download_with_url(NUCLEI_MODEL_URL, nuclei_model)\n            nuclei_model = torch.load(\n                nuclei_model, map_location=torch.device(self.device)\n            )\n        if isinstance(nuclei_model, torch.nn.DataParallel) and device == \"cpu\":\n            nuclei_model = nuclei_model.module\n\n        self.nuclei_model = nuclei_model.to(self.device).eval()\n\n        self.multi_channel_model = multi_channel_model\n        if isinstance(cell_model, str):\n            if not os.path.exists(cell_model):\n                print(\n                    f\"Could not find {cell_model}. Downloading it now\", file=sys.stderr\n                )\n                if self.multi_channel_model:\n                    download_with_url(MULTI_CHANNEL_CELL_MODEL_URL, cell_model)\n                else:\n                    download_with_url(TWO_CHANNEL_CELL_MODEL_URL, cell_model)\n            cell_model = torch.load(cell_model, map_location=torch.device(self.device))\n        self.cell_model = cell_model.to(self.device).eval()\n        self.scale_factor = scale_factor\n        self.padding = padding\n\n    def _image_conversion(self, images):\n        \"\"\"Convert/Format images to RGB image arrays list for cell predictions.\n        Intended for internal use only.\n        Keyword arguments:\n        images -- list of lists of image paths/arrays. It should following the\n                 pattern if with er channel input,\n                 [\n                     [microtubule_path0/image_array0, microtubule_path1/image_array1, ...],\n                     [er_path0/image_array0, er_path1/image_array1, ...],\n                     [nuclei_path0/image_array0, nuclei_path1/image_array1, ...]\n                 ]\n                 or if without er input,\n                 [\n                     [microtubule_path0/image_array0, microtubule_path1/image_array1, ...],\n                     None,\n                     [nuclei_path0/image_array0, nuclei_path1/image_array1, ...]\n                 ]\n        \"\"\"\n        microtubule_imgs, er_imgs, nuclei_imgs = images\n        if self.multi_channel_model:\n            if not isinstance(er_imgs, list):\n                raise ValueError(\"Please speicify the image path(s) for er channels!\")\n        else:\n            if not er_imgs is None:\n                raise ValueError(\n                    \"second channel should be None for two channel model predition!\"\n                )\n\n        if not isinstance(microtubule_imgs, list):\n            raise ValueError(\"The microtubule images should be a list\")\n        if not isinstance(nuclei_imgs, list):\n            raise ValueError(\"The microtubule images should be a list\")\n\n        if er_imgs:\n            if not len(microtubule_imgs) == len(er_imgs) == len(nuclei_imgs):\n                raise ValueError(\"The lists of images needs to be the same length\")\n        else:\n            if not len(microtubule_imgs) == len(nuclei_imgs):\n                raise ValueError(\"The lists of images needs to be the same length\")\n\n        if not all(isinstance(item, np.ndarray) for item in microtubule_imgs):\n            microtubule_imgs = [\n                os.path.expanduser(item) for _, item in enumerate(microtubule_imgs)\n            ]\n            nuclei_imgs = [\n                os.path.expanduser(item) for _, item in enumerate(nuclei_imgs)\n            ]\n\n            microtubule_imgs = list(\n                map(lambda item: imageio.imread(item), microtubule_imgs)\n            )\n            nuclei_imgs = list(map(lambda item: imageio.imread(item), nuclei_imgs))\n            if er_imgs:\n                er_imgs = [os.path.expanduser(item) for _, item in enumerate(er_imgs)]\n                er_imgs = list(map(lambda item: imageio.imread(item), er_imgs))\n\n        if not er_imgs:\n            er_imgs = [\n                np.zeros(item.shape, dtype=item.dtype)\n                for _, item in enumerate(microtubule_imgs)\n            ]\n        cell_imgs = list(\n            map(\n                lambda item: np.dstack((item[0], item[1], item[2])),\n                list(zip(microtubule_imgs, er_imgs, nuclei_imgs)),\n            )\n        )\n\n        return cell_imgs\n\n    def pred_nuclei(self, images):\n        \"\"\"Predict the nuclei segmentation.\n        Keyword arguments:\n        images -- A list of image arrays or a list of paths to images.\n                  If as a list of image arrays, the images could be 2d images\n                  of nuclei data array only, or must have the nuclei data in\n                  the blue channel; If as a list of file paths, the images\n                  could be RGB image files or gray scale nuclei image file\n                  paths.\n        Returns:\n        predictions -- A list of predictions of nuclei segmentation for each nuclei image.\n        \"\"\"\n\n        def _preprocess(image):\n            if isinstance(image, str):\n                image = imageio.imread(image)\n            self.target_shape = image.shape\n            if len(image.shape) == 2:\n                image = np.dstack((image, image, image))\n            image = transform.rescale(image, self.scale_factor, multichannel=True)\n            nuc_image = np.dstack((image[..., 2], image[..., 2], image[..., 2]))\n            if self.padding:\n                rows, cols = nuc_image.shape[:2]\n                self.scaled_shape = rows, cols\n                nuc_image = cv2.copyMakeBorder(\n                    nuc_image,\n                    32,\n                    (32 - rows % 32),\n                    32,\n                    (32 - cols % 32),\n                    cv2.BORDER_REFLECT,\n                )\n            nuc_image = nuc_image.transpose([2, 0, 1])\n            return nuc_image\n\n        def _segment_helper(imgs):\n            with torch.no_grad():\n                mean = torch.as_tensor(NORMALIZE[\"mean\"], device=self.device)\n                std = torch.as_tensor(NORMALIZE[\"std\"], device=self.device)\n                imgs = torch.tensor(imgs).float()\n                imgs = imgs.to(self.device)\n                imgs = imgs.sub_(mean[:, None, None]).div_(std[:, None, None])\n\n                imgs = self.nuclei_model(imgs)\n                imgs = F.softmax(imgs, dim=1)\n                return imgs\n\n        preprocessed_imgs = list(map(_preprocess, images))\n        bs = 24\n        predictions = []\n        for i in range(0, len(preprocessed_imgs), bs):\n            start = i\n            end = min(len(preprocessed_imgs), i+bs)\n            x = preprocessed_imgs[start:end]\n            pred = _segment_helper(x).cpu().numpy()\n            predictions.append(pred)\n        predictions = list(np.concatenate(predictions, axis=0))\n        predictions = map(util.img_as_ubyte, predictions)\n        predictions = list(map(self._restore_scaling_padding, predictions))\n        return predictions\n\n    def _restore_scaling_padding(self, n_prediction):\n        \"\"\"Restore an image from scaling and padding.\n        This method is intended for internal use.\n        It takes the output from the nuclei model as input.\n        \"\"\"\n        n_prediction = n_prediction.transpose([1, 2, 0])\n        if self.padding:\n            n_prediction = n_prediction[\n                32 : 32 + self.scaled_shape[0], 32 : 32 + self.scaled_shape[1], ...\n            ]\n        if not self.scale_factor == 1:\n            n_prediction[..., 0] = 0\n            n_prediction = cv2.resize(\n                n_prediction,\n                (self.target_shape[0], self.target_shape[1]),\n                interpolation=cv2.INTER_AREA,\n            )\n        return n_prediction\n\n    def pred_cells(self, images, precombined=False):\n        \"\"\"Predict the cell segmentation for a list of images.\n        Keyword arguments:\n        images -- list of lists of image paths/arrays. It should following the\n                  pattern if with er channel input,\n                  [\n                      [microtubule_path0/image_array0, microtubule_path1/image_array1, ...],\n                      [er_path0/image_array0, er_path1/image_array1, ...],\n                      [nuclei_path0/image_array0, nuclei_path1/image_array1, ...]\n                  ]\n                  or if without er input,\n                  [\n                      [microtubule_path0/image_array0, microtubule_path1/image_array1, ...],\n                      None,\n                      [nuclei_path0/image_array0, nuclei_path1/image_array1, ...]\n                  ]\n                  The ER channel is required when multichannel is True\n                  and required to be None when multichannel is False.\n                  The images needs to be of the same size.\n        precombined -- If precombined is True, the list of images is instead supposed to be\n                       a list of RGB numpy arrays (default: False).\n        Returns:\n        predictions -- a list of predictions of cell segmentations.\n        \"\"\"\n\n        def _preprocess(image):\n            self.target_shape = image.shape\n            if not len(image.shape) == 3:\n                raise ValueError(\"image should has 3 channels\")\n            cell_image = transform.rescale(image, self.scale_factor, multichannel=True)\n            if self.padding:\n                rows, cols = cell_image.shape[:2]\n                self.scaled_shape = rows, cols\n                cell_image = cv2.copyMakeBorder(\n                    cell_image,\n                    32,\n                    (32 - rows % 32),\n                    32,\n                    (32 - cols % 32),\n                    cv2.BORDER_REFLECT,\n                )\n            cell_image = cell_image.transpose([2, 0, 1])\n            return cell_image\n\n        def _segment_helper(imgs):\n            with torch.no_grad():\n                mean = torch.as_tensor(NORMALIZE[\"mean\"], device=self.device)\n                std = torch.as_tensor(NORMALIZE[\"std\"], device=self.device)\n                imgs = torch.tensor(imgs).float()\n                imgs = imgs.to(self.device)\n                imgs = imgs.sub_(mean[:, None, None]).div_(std[:, None, None])\n\n                imgs = self.cell_model(imgs)\n                imgs = F.softmax(imgs, dim=1)\n                return imgs\n\n        if not precombined:\n            images = self._image_conversion(images)\n        preprocessed_imgs = list(map(_preprocess, images))\n        bs = 24\n        predictions = []\n        for i in range(0, len(preprocessed_imgs), bs):\n            start = i\n            end = min(len(preprocessed_imgs), i+bs)\n            x = preprocessed_imgs[start:end]\n            pred = _segment_helper(x).cpu().numpy()\n            predictions.append(pred)\n        predictions = list(np.concatenate(predictions, axis=0))\n        predictions = map(self._restore_scaling_padding, predictions)\n        predictions = list(map(util.img_as_ubyte, predictions))\n\n        return predictions\n    \n\n\nHIGH_THRESHOLD = 0.4\nLOW_THRESHOLD = HIGH_THRESHOLD - 0.25\n\n\ndef download_with_url(url_string, file_path, unzip=False):\n    \"\"\"Download file with a link.\"\"\"\n    with urllib.request.urlopen(url_string) as response, open(\n        file_path, \"wb\"\n    ) as out_file:\n        data = response.read()  # a `bytes` object\n        out_file.write(data)\n\n    if unzip:\n        with zipfile.ZipFile(file_path, \"r\") as zip_ref:\n            zip_ref.extractall(os.path.dirname(file_path))\n\n\ndef __fill_holes(image):\n    \"\"\"Fill_holes for labelled image, with a unique number.\"\"\"\n    boundaries = segmentation.find_boundaries(image)\n    image = np.multiply(image, np.invert(boundaries))\n    image = ndi.binary_fill_holes(image > 0)\n    image = ndi.label(image)[0]\n    return image\n\n\n\n\n\ndef label_cell(nuclei_pred, cell_pred):\n    \"\"\"Label the cells and the nuclei.\n    Keyword arguments:\n    nuclei_pred -- a 3D numpy array of a prediction from a nuclei image.\n    cell_pred -- a 3D numpy array of a prediction from a cell image.\n    Returns:\n    A tuple containing:\n    nuclei-label -- A nuclei mask data array.\n    cell-label  -- A cell mask data array.\n    0's in the data arrays indicate background while a continous\n    strech of a specific number indicates the area for a specific\n    cell.\n    The same value in cell mask and nuclei mask refers to the identical cell.\n    NOTE: The nuclei labeling from this function will be sligthly\n    different from the values in :func:`label_nuclei` as this version\n    will use information from the cell-predictions to make better\n    estimates.\n    \"\"\"\n    def __wsh(\n        mask_img,\n        threshold,\n        border_img,\n        seeds,\n        threshold_adjustment=0.35,\n        small_object_size_cutoff=10,\n    ):\n        img_copy = np.copy(mask_img)\n        m = seeds * border_img  # * dt\n        img_copy[m <= threshold + threshold_adjustment] = 0\n        img_copy[m > threshold + threshold_adjustment] = 1\n        img_copy = img_copy.astype(np.bool)\n        img_copy = remove_small_objects(img_copy, small_object_size_cutoff).astype(\n            np.uint8\n        )\n\n        mask_img[mask_img <= threshold] = 0\n        mask_img[mask_img > threshold] = 1\n        mask_img = mask_img.astype(np.bool)\n        mask_img = remove_small_holes(mask_img, 63)\n        mask_img = remove_small_objects(mask_img, 1).astype(np.uint8)\n        markers = ndi.label(img_copy, output=np.uint32)[0]\n        labeled_array = segmentation.watershed(\n            mask_img, markers, mask=mask_img, watershed_line=True\n        )\n        return labeled_array\n\n    nuclei_label = __wsh(\n        nuclei_pred[..., 2] / 255.0,\n        0.4,\n        1 - (nuclei_pred[..., 1] + cell_pred[..., 1]) / 255.0 > 0.05,\n        nuclei_pred[..., 2] / 255,\n        threshold_adjustment=-0.25,\n        small_object_size_cutoff=32,\n    )\n\n    # for hpa_image, to remove the small pseduo nuclei\n    nuclei_label = remove_small_objects(nuclei_label, 157)\n    nuclei_label = measure.label(nuclei_label)\n    # this is to remove the cell borders' signal from cell mask.\n    # could use np.logical_and with some revision, to replace this func.\n    # Tuned for segmentation hpa images\n    threshold_value = max(0.22, filters.threshold_otsu(cell_pred[..., 2] / 255) * 0.5)\n    # exclude the green area first\n    cell_region = np.multiply(\n        cell_pred[..., 2] / 255 > threshold_value,\n        np.invert(np.asarray(cell_pred[..., 1] / 255 > 0.05, dtype=np.int8)),\n    )\n    sk = np.asarray(cell_region, dtype=np.int8)\n    distance = np.clip(cell_pred[..., 2], 255 * threshold_value, cell_pred[..., 2])\n    cell_label = segmentation.watershed(-distance, nuclei_label, mask=sk)\n    cell_label = remove_small_objects(cell_label, 344).astype(np.uint8)\n    selem = disk(2)\n    cell_label = closing(cell_label, selem)\n    cell_label = __fill_holes(cell_label)\n    # this part is to use green channel, and extend cell label to green channel\n    # benefit is to exclude cells clear on border but without nucleus\n    sk = np.asarray(\n        np.add(\n            np.asarray(cell_label > 0, dtype=np.int8),\n            np.asarray(cell_pred[..., 1] / 255 > 0.05, dtype=np.int8),\n        )\n        > 0,\n        dtype=np.int8,\n    )\n    cell_label = segmentation.watershed(-distance, cell_label, mask=sk)\n    cell_label = __fill_holes(cell_label)\n    cell_label = np.asarray(cell_label > 0, dtype=np.uint8)\n    cell_label = measure.label(cell_label)\n    cell_label = remove_small_objects(cell_label, 344)\n    cell_label = measure.label(cell_label)\n    cell_label = np.asarray(cell_label, dtype=np.uint16)\n    nuclei_label = np.multiply(cell_label > 0, nuclei_label) > 0\n    nuclei_label = measure.label(nuclei_label)\n    nuclei_label = remove_small_objects(nuclei_label, 157)\n    nuclei_label = np.multiply(cell_label, nuclei_label > 0)\n\n    return nuclei_label, cell_label","metadata":{"_kg_hide-input":true,"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read and visualize sample image\ndef read_sample_image(filename):\n    \n    '''\n    read individual images\n    of different filters (R, G, B, Y)\n    and stack them.\n    ---------------------------------\n    Arguments:\n    filename -- sample image path\n    \n    Returns:\n    stacked_images -- stacked (RGBY) image\n    '''\n    \n    red = cv2.imread(TRAIN_DIR + filename + \"_red.png\", cv2.IMREAD_UNCHANGED)\n    green = cv2.imread(TRAIN_DIR + filename + \"_green.png\", cv2.IMREAD_UNCHANGED)\n    blue = cv2.imread(TRAIN_DIR + filename + \"_blue.png\", cv2.IMREAD_UNCHANGED)\n    yellow = cv2.imread(TRAIN_DIR + filename + \"_yellow.png\", cv2.IMREAD_UNCHANGED)\n\n    stacked_images = np.transpose(np.array([red, green, blue, yellow]), (1,2,0))\n    return stacked_images\n\ndef read_test_image(filename):\n    red = cv2.imread(TEST_DIR + filename + \"_red.png\", cv2.IMREAD_UNCHANGED)\n    green = cv2.imread(TEST_DIR + filename + \"_green.png\", cv2.IMREAD_UNCHANGED)\n    blue = cv2.imread(TEST_DIR + filename + \"_blue.png\", cv2.IMREAD_UNCHANGED)\n    yellow = cv2.imread(TEST_DIR + filename + \"_yellow.png\", cv2.IMREAD_UNCHANGED)\n\n    stacked_images = np.transpose(np.array([red, green, blue, yellow]), (1,2,0))\n#     plt.imshow(stacked_images)\n    return stacked_images\n\n\ndef plot_all(im, label):\n    \n    '''\n    plot all RGBY image,\n    Red, Green, Blue, Yellow, \n    filters images.\n    --------------------------\n    Argument:\n    im - image\n    '''\n    \n    plt.figure(figsize=(15, 15))\n    plt.subplot(1, 5, 1)\n    plt.imshow(im[:,:,:3])\n    plt.title('RGBY Image')\n    plt.axis('off')\n    plt.subplot(1, 5, 2)\n    plt.imshow(im[:,:,0], cmap='Reds')\n    plt.title('Microtubule channels')\n    plt.axis('off')\n    plt.subplot(1, 5, 3)\n    plt.imshow(im[:,:,1], cmap='Greens')\n    plt.title('Protein of Interest')\n    plt.axis('off')\n    plt.subplot(1, 5, 4)\n    plt.imshow(im[:,:,2], cmap='Blues')\n    plt.title('Nucleus')\n    plt.axis('off')\n    plt.subplot(1, 5, 5)\n    plt.imshow(im[:,:,3], cmap='Oranges')\n    plt.title('Endoplasmic Reticulum')\n    plt.axis('off')\n    plt.show()\n    \n# read and visualize sample image\ndef read_sample_image_seg(filename):\n    \n    '''\n    read individual images\n    of different filters (R, B, Y)\n    and stack them for segmentation.\n    ---------------------------------\n    Arguments:\n    filename -- sample image file path\n    \n    Returns:\n    stacked_images -- stacked (RBY) image path in lists.\n    '''\n    \n    red = TRAIN_DIR + filename + \"_red.png\"\n    blue = TRAIN_DIR+ filename + \"_blue.png\"\n    yellow = TRAIN_DIR + filename + \"_yellow.png\"\n    green = TRAIN_DIR + filename + \"_green.png\"\n\n    stacked_images = [[red], [yellow], [blue]]\n#    plt.imshow(stacked_images[0])\n#    plt.imshow(stacked_images[1])\n#    plt.imshow(stacked_images[2])\n    return stacked_images, red, blue, yellow, green\n\ndef read_test_image_seg(filename):\n    \n    '''\n    read individual images\n    of different filters (R, B, Y)\n    and stack them for segmentation.\n    ---------------------------------\n    Arguments:\n    filename -- sample image file path\n    \n    Returns:\n    stacked_images -- stacked (RBY) image path in lists.\n    '''\n    \n    red = TEST_DIR + filename + \"_red.png\"\n    blue = TEST_DIR+ filename + \"_blue.png\"\n    yellow = TEST_DIR + filename + \"_yellow.png\"\n    green = TEST_DIR + filename + \"_green.png\"\n\n    stacked_images = [[red], [yellow], [blue]]\n    return stacked_images, red, blue, yellow, green\n\n\n# segment cell \ndef segmentCell(image, segmentator):\n    \n    '''\n    segment cell and nuclei from\n    microtubules, endoplasmic reticulum,\n    and nuclei (R, B, Y) filters.\n    ------------------------------------\n    Argument:\n    image -- (R, B, Y) li\n    st of image arrays\n    segmentator -- CellSegmentator class object\n    \n    Returns:\n    cell_mask -- segmented cell mask\n    '''\n    '''\n    print('image is', image)\n    print(\"image2 is\", image[2])\n    '''\n    nuc_segmentations = segmentator.pred_nuclei(image[2])\n    cell_segmentations = segmentator.pred_cells(image)\n    nuclei_mask, cell_mask = label_cell(nuc_segmentations[0], cell_segmentations[0])\n    \n    gc.collect(); del nuc_segmentations; del cell_segmentations; del nuclei_mask\n    \n    return cell_mask\n\ndef faster_segmentCell(blue, image, segmentator):\n    \n    '''\n    segment cell and nuclei from\n    microtubules, endoplasmic reticulum,\n    and nuclei (R, B, Y) filters.\n    ------------------------------------\n    Argument:\n    image -- (R, B, Y) li\n    st of image arrays\n    segmentator -- CellSegmentator class object\n    \n    Returns:\n    cell_mask -- segmented cell mask\n    '''\n    '''\n    print('image is', image)\n    print(\"image2 is\", image[2])\n    '''\n    # nuc_segmentations = segmentator.pred_nuclei(image[2])\n    nuc_segmentations = segmentator.pred_nuclei([blue])\n    cell_segmentations = segmentator.pred_cells([image], precombined=True)\n    nuclei_mask, cell_mask = label_cell(nuc_segmentations[0], cell_segmentations[0])\n    \n    gc.collect(); del nuc_segmentations; del cell_segmentations\n    \n    \n    return cell_mask, nuclei_mask\n\n\n# plot segmented cells mask, image\n\ndef plot_cell_segments(mask, r, b, y):\n    \n    '''\n    plot segmented cells\n    and images\n    ---------------------\n    Arguments:\n    mask -- cell mask\n    red -- red filter image path\n    blue -- blue filter image path\n    yellow -- yellow filter image path\n    '''\n    microtubule = plt.imread(r)    \n    endoplasmicrec = plt.imread(b)    \n    nuclei = plt.imread(y)\n    img = np.dstack((microtubule, endoplasmicrec, nuclei))\n    \n    plt.figure(figsize=(15, 15))\n    plt.subplot(1, 3, 1)\n    plt.imshow(img)\n    plt.title('Image')\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 2)\n    plt.imshow(mask)\n    plt.title('Mask')\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 3)\n    plt.imshow(img)\n    plt.imshow(mask, alpha=0.6)\n    plt.title('Image + Mask')\n    plt.axis('off')\n    plt.show()\n\n# plot single segmented cells mask, image\ndef plot_single_cell(mask, red, blue, yellow):\n    \n    '''\n    plot single cell mask\n    and image\n    ---------------------\n    Arguments:\n    mask -- cell mask\n    red -- red filter image path\n    blue -- blue filter image path\n    yellow -- yellow filter image path\n    '''\n    microtubule = plt.imread(r)    \n    endoplasmicrec = plt.imread(b)    \n    nuclei = plt.imread(y)\n    img = np.dstack((microtubule, endoplasmicrec, nuclei))\n    \n    contours= cv2.findContours(mask.astype('uint8'),\n                               cv2.RETR_TREE, \n                               cv2.CHAIN_APPROX_SIMPLE)\n\n    areas = [cv2.contourArea(c) for c in contours[0]]\n    x = np.argsort(areas)\n    cnt = contours[0][x[-1]]\n    x,yc,w,h = cv2.boundingRect(cnt)\n    \n    plt.figure(figsize=(15, 15))\n    plt.subplot(1, 3, 1)\n    plt.imshow(img[yc:yc+h, x:x+w])\n    plt.title('Cell Image')\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 2)\n    plt.imshow(mask[yc:yc+h, x:x+w])\n    plt.title('Cell Mask')\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 3)\n    plt.imshow(img[yc:yc+h, x:x+w])\n    plt.imshow(mask[yc:yc+h, x:x+w], alpha=0.6)\n    plt.title('Cell Image + Mask')\n    plt.axis('off')\n    plt.show()\n    \n# return all segmented cell images in an original image\ndef images_single_cell(mask, red, blue, yellow, green):\n    \n    '''\n    create single cell mask\n    and image\n    ---------------------\n    Arguments:\n    mask -- cell mask\n    red -- red filter image path\n    blue -- blue filter image path\n    yellow -- yellow filter image path\n    '''\n    microtubule = plt.imread(red)    \n    endoplasmicrec = plt.imread(blue)    \n    nuclei = plt.imread(yellow)\n    protein = plt.imread(green)\n    img = np.dstack((microtubule, endoplasmicrec, nuclei, protein))\n    \n    contours= cv2.findContours(mask.astype('uint8'),\n                               cv2.RETR_TREE, \n                               cv2.CHAIN_APPROX_SIMPLE)\n    \n    images = list()\n    for cnt in contours[0]:\n        x,yc,w,h = cv2.boundingRect(cnt)\n        images.append(img[yc:yc+h, x:x+w])\n        \n    del contours, microtubule, endoplasmicrec, nuclei, protein, img\n    gc.collect()\n\n    return images\n\n# return all segmented cell images in an original image\ndef faster_images_single_cell(mask, red, blue, yellow, green):\n    \n    '''\n    create single cell mask\n    and image\n    ---------------------\n    Arguments:\n    mask -- cell mask\n    red -- red filter image path\n    blue -- blue filter image path\n    yellow -- yellow filter image path\n    '''\n    microtubule = red  \n    endoplasmicrec = blue  \n    nuclei = yellow\n    protein = green\n    img = np.dstack((microtubule, endoplasmicrec, nuclei, protein))\n    \n    contours= cv2.findContours(mask.astype('uint8'),\n                               cv2.RETR_TREE, \n                               cv2.CHAIN_APPROX_SIMPLE)\n    \n    images = list()\n    for cnt in contours[0]:\n        x,yc,w,h = cv2.boundingRect(cnt)\n        images.append(img[yc:yc+h, x:x+w])\n        \n    del contours, microtubule, endoplasmicrec, nuclei, protein, img\n    gc.collect()\n\n    return images\n\n\n# Extend the size of an image by padding\ndef add_margin(image, size):\n    '''\n    Extend the size of an image by padding \n    Height * Width * Channel -> size * size * Channel\n    '''\n    H, W, C = image.shape\n    pad_H1 = (size - H)//2\n    pad_H2 = pad_H1 + (size - H)%2\n    pad_W1 = (size - W)//2\n    pad_W2 = pad_W1 + (size - W)%2\n    \n    return np.pad(image,[(pad_H1, pad_H2),(pad_W1, pad_W2),(0,0)], 'constant')\n\n# Make the image square by padding\ndef resize_to_square(image):\n    '''\n    Extend the size of an image by padding \n    Height * Width * Channel -> max(H, W) * max(H, W) * Channel\n    '''\n    H, W, C = image.shape\n    size = max(H, W)    \n    return add_margin(image, size)\n\n\ndef binary_mask(rgby_images):\n    \n    '''\n    generate masks from \n    rgby images.\n    --------------------\n    Arguments:\n    rgby_images -- RGBY cell images\n    \n    Return:\n    mask -- binary mask.\n    '''\n    pass\n\n","metadata":{"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Dataset class for cell-level classification\n# For training dataset\nclass GetData_single_cell(Dataset):\n    def __init__(self, path, list_IDs, df_labels, img_size, Transform='None'):\n        self.path = path\n        self.list_IDs = list_IDs\n        self.labels = df_labels\n        self.img_size = img_size        \n        self.transform = Transform\n        \n    def __len__(self):\n        return len(self.list_IDs)    \n    \n    def __getitem__(self, index):\n        ID = self.list_IDs[index]   \n                        \n        red = np.load(self.path + \"red/\" + str(ID).zfill(6) + '_red.npy')\n        blue = np.load(self.path + \"blue/\" + str(ID).zfill(6) + '_blue.npy')\n        yellow = np.load(self.path + \"yellow/\" + str(ID).zfill(6) + '_yellow.npy')\n        green = np.load(self.path + \"green/\" + str(ID).zfill(6) + '_green.npy')\n        \n        img = np.dstack((red, blue, yellow, green))\n\n        img = resize_to_square(img)\n        img = cv2.resize(img, (self.img_size, self.img_size)) \n        X = img/255.\n        X = np.transpose(X, (2, 0, 1))\n\n        y = self.labels.loc[ID]\n        return X, torch.tensor(y, dtype=torch.float)\n","metadata":{"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef encode_binary_mask(mask, mask_val):\n  \"\"\"Converts a binary mask into OID challenge encoding ascii text.\"\"\"\n  mask = np.where(mask==mask_val, True, False)\n  \n  # check input mask --\n  if mask.dtype != np.bool:\n    raise ValueError(\n        \"encode_binary_mask expects a binary mask, received dtype == %s\" %\n        mask.dtype)\n\n  mask = np.squeeze(mask)\n  if len(mask.shape) != 2:\n    raise ValueError(\n        \"encode_binary_mask expects a 2d mask, received shape == %s\" %\n        mask.shape)\n\n  # convert input mask to expected COCO API input --\n  mask_to_encode = mask.reshape(mask.shape[0], mask.shape[1], 1)\n  mask_to_encode = mask_to_encode.astype(np.uint8)\n  mask_to_encode = np.asfortranarray(mask_to_encode)\n\n  # RLE encode mask --\n  encoded_mask = coco_mask.encode(mask_to_encode)[0][\"counts\"]\n\n  # compress and base64 encoding --\n  binary_str = zlib.compress(encoded_mask, zlib.Z_BEST_COMPRESSION)\n  base64_str = base64.b64encode(binary_str)\n  return base64_str.decode()\n\n\ndef is_border_nuclei(contour_points):\n    unique_points = np.unique(contour_points)\n    \n    if 0 in unique_points:\n        return True\n    return False\n\ndef clean_nuclei_mask_vals(nuclei_mask):\n    nuclei = np.unique(nuclei_mask)\n    \n    nuclei_list = []\n    \n    for nucleus in nuclei:\n        # get inidivual nucleus mask\n        nucleus_mask = np.where(nuclei_mask==nucleus, 1,0).astype('uint8')\n        \n        # get contour for cell and nucleus\n        nucleus_cnts, _ = cv2.findContours(nucleus_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n        \n        if not is_border_nuclei(nucleus_cnts[0]): # If not touching the boundary\n            nuclei_list.append(nucleus)\n        \n    return nuclei_list\n\ndef decode_img(img, img_size=(224,224), testing=False):\n    \"\"\"TBD\"\"\"\n    \n    # convert the compressed string to a 3D uint8 tensor\n    if not testing:\n        # resize the image to the desired size\n        img = tf.image.decode_png(img, channels=1)\n        return tf.cast(tf.image.resize(img, img_size), tf.uint8)\n    else:\n        return tf.image.decode_png(img, channels=1)\n    \n\ndef load_image(img_id, img_dir, testing=False):\n    \"\"\" Load An Image Using ID and Directory Path - Composes 4 Individual Images \"\"\"\n    return_axis = 0\n    clr_list = [\"red\", \"green\", \"blue\", \"yellow\"]\n    \n    if not testing:\n        rgby = [\n            np.asarray(Image.open(os.path.join(img_dir, img_id+f\"_{c}.png\")), np.uint8) \\\n            for c in [\"red\", \"green\", \"blue\", \"yellow\"]\n        ]\n        return np.stack(rgby, axis=-1)\n    else:\n        # This is for cellsegmentator\n        return np.stack(\n            [np.asarray(decode_img(tf.io.read_file(os.path.join(img_dir, img_id+f\"_{c}.png\")), testing=True), np.uint8)[..., 0] \\\n             for c in clr_list], axis=return_axis,\n        )\n\ndef get_contour_bbox_from_rle(rle, width, height, return_mask=True,):\n    \"\"\" Get bbox of contour as `xmin ymin xmax ymax`\n    \n    Args:\n        rle (rle_string): Run length encoding containing \n            segmentation mask information\n        height (int): Height of the original image the map comes from\n        width (int): Width of the original image the map comes from\n    \n    Returns:\n        Numpy array for a cell bounding box coordinates\n    \"\"\"\n    mask = rle_to_mask(rle, height, width).copy()\n    cnts = grab_contours(\n        cv2.findContours(\n            mask, \n            cv2.RETR_EXTERNAL, \n            cv2.CHAIN_APPROX_SIMPLE\n        ))\n    x,y,w,h = cv2.boundingRect(cnts[0])\n    \n    if return_mask:\n        return (x,y,x+w,y+h), mask\n    else:\n        return (x,y,x+w,y+h)\n\n    \ndef rgby_reshape(fourchannel):\n    r = im[0]\n    b = im[1]\n    y = im[2]\n    g = im[3]\n    \n    return np.stack((r,b,y), axis=2)\n\ndef create_pred_col(row):\n    \"\"\" Simple function to return the correct prediction string\n    \n    We will want the original public test dataframe submission when it is \n    available. However, we will use the swapped inn submission dataframe\n    when it is not.\n    \n    Args:\n        row (pd.Series): A row in the dataframe\n    \n    Returns:\n        The prediction string\n    \"\"\"\n    if pd.isnull(row.PredictionString_y):\n        return row.PredictionString_x\n    else:\n        return row.PredictionString_y\n\ndef pad_to_square(a):\n    \"\"\" Pad an array `a` evenly until it is a square \"\"\"\n    if a.shape[1]>a.shape[0]: # pad height\n        n_to_add = a.shape[1]-a.shape[0]\n        top_pad = n_to_add//2\n        bottom_pad = n_to_add-top_pad\n        a = np.pad(a, [(top_pad, bottom_pad), (0, 0), (0, 0)], mode='constant')\n\n    elif a.shape[0]>a.shape[1]: # pad width\n        n_to_add = a.shape[0]-a.shape[1]\n        left_pad = n_to_add//2\n        right_pad = n_to_add-left_pad\n        a = np.pad(a, [(0, 0), (left_pad, right_pad), (0, 0)], mode='constant')\n    else:\n        pass\n    return a\n\ndef flatten_list_of_lists(l_o_l, to_string=False):\n    if not to_string:\n        return [item for sublist in l_o_l for item in sublist]\n    else:\n        return [str(item) for sublist in l_o_l for item in sublist]\n\ndef get_contour_bbox_from_raw(raw_mask):\n    \"\"\" Get bbox of contour as `xmin ymin xmax ymax`\n    \n    Args:\n        raw_mask (nparray): Numpy array containing segmentation mask information\n    \n    Returns:\n        Numpy array for a cell bounding box coordinates\n    \"\"\"\n    cnts = grab_contours(\n        cv2.findContours(\n            raw_mask, \n            cv2.RETR_EXTERNAL, \n            cv2.CHAIN_APPROX_SIMPLE\n        ))\n    xywhs = [cv2.boundingRect(cnt) for cnt in cnts]\n    xys = [(xywh[0], xywh[1], xywh[0]+xywh[2], xywh[1]+xywh[3]) for xywh in xywhs]\n    return sorted(xys, key=lambda x: (x[1], x[0]))\n\ndef grab_contours(cnts):\n    # if the length the contours tuple returned by cv2.findContours\n    # is '2' then we are using either OpenCV v2.4, v4-beta, or\n    # v4-official\n    if len(cnts) == 2:\n        cnts = cnts[0]\n\n    # if the length of the contours tuple is '3' then we are using\n    # either OpenCV v3, v4-pre, or v4-alpha\n    elif len(cnts) == 3:\n        cnts = cnts[1]\n\n    # otherwise OpenCV has changed their cv2.findContours return\n    # signature yet again and I have no idea WTH is going on\n    else:\n        raise Exception((\"Contours tuple must have length 2 or 3, \"\n            \"otherwise OpenCV changed their cv2.findContours return \"\n            \"signature yet again. Refer to OpenCV's documentation \"\n            \"in that case\"))\n\n    # return the actual contours array\n    return cnts\n\ndef get_torchd(tile, DEVICE):\n    tile = np.array(tile).swapaxes(1,3)\n    tile = torch.from_numpy(tile)\n    tile = tile.to(DEVICE)\n    tile = tile.float()\n    return tile\n\ndef rle_to_mask(rle_string, height, width):\n    \"\"\" Convert RLE sttring into a binary mask \n    \n    Args:\n        rle_string (rle_string): Run length encoding containing \n            segmentation mask information\n        height (int): Height of the original image the map comes from\n        width (int): Width of the original image the map comes from\n    \n    Returns:\n        Numpy array of the binary segmentation mask for a given cell\n    \"\"\"\n    rows,cols = height,width\n    rle_numbers = [int(num_string) for num_string in rle_string.split(' ')]\n    rle_pairs = np.array(rle_numbers).reshape(-1,2)\n    img = np.zeros(rows*cols,dtype=np.uint8)\n    for index,length in rle_pairs:\n        index -= 1\n        img[index:index+length] = 255\n    img = img.reshape(cols,rows)\n    img = img.T\n    return img\n\n\n\ndef for_predictions(fourchannel):\n    im = fourchannel.transpose(2,0,1)\n    r = im[0]\n    b = im[2]\n    y = im[1]\n    g = im[3]\n    \n    return np.stack((g,y,b), axis=2)","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\n\nimport plotly.express as px\n\nLBL_NAMES = [\"Nucleoplasm\", \"Nuclear Membrane\", \"Nucleoli\", \"Nucleoli Fibrillar Center\", \"Nuclear Speckles\", \"Nuclear Bodies\", \n             \"Endoplasmic Reticulum\", \"Golgi Apparatus\", \"Intermediate Filaments\", \"Actin Filaments\", \"Microtubules\", \"Mitotic Spindle\", \n             \"Centrosome\", \"Plasma Membrane\", \"Mitochondria\", \"Aggresome\", \"Cytosol\", \"Vesicles\", \"Negative\"]\n\nINT_2_STR = {x:LBL_NAMES[x] for x in np.arange(19)}\nINT_2_STR_LOWER = {k:v.lower().replace(\" \", \"_\") for k,v in INT_2_STR.items()}\nSTR_2_INT_LOWER = {v:k for k,v in INT_2_STR_LOWER.items()}\nSTR_2_INT = {v:k for k,v in INT_2_STR.items()}\nFIG_FONT = dict(family=\"Helvetica, Arial\", size=14, color=\"#000000\")\nLABEL_COLORS = [px.colors.label_rgb(px.colors.convert_to_RGB_255(x)) for x in sns.color_palette(\"Spectral\", len(LBL_NAMES))]\nLABEL_COL_MAP = {str(i):x for i,x in enumerate(LABEL_COLORS)}\n\ndef plot_predictions(img, masks, preds, confs=None, fill_alpha=0.3, lbl_as_str=True):\n    # Initialize\n    FONT = cv2.FONT_HERSHEY_SIMPLEX; FONT_SCALE = 1.5 ; FONT_THICKNESS = 2; FONT_LINE_TYPE = cv2.LINE_AA;\n    COLORS = [[round(y*255) for y in x] for x in sns.color_palette(\"Spectral\", len(LBL_NAMES))]\n    to_plot = img.copy()\n    cntr_img = img.copy()\n    if confs==None:\n        confs = [None,]*len(masks)\n\n    cnts = grab_contours(\n        cv2.findContours(\n            masks, \n            cv2.RETR_EXTERNAL, \n            cv2.CHAIN_APPROX_SIMPLE\n        ))\n    cnts = sorted(cnts, key=lambda x: (cv2.boundingRect(x)[1], cv2.boundingRect(x)[0]))\n        \n    for c, pred, conf in zip(cnts, preds, confs):\n        # We can only display one color so we pick the first\n        color = COLORS[pred[0]]\n        if not lbl_as_str:\n            classes = \"CLS=[\"+\",\".join([str(p) for p in pred])+\"]\"\n        else:\n            classes = \", \".join([INT_2_STR[p] for p in pred])\n        M = cv2.moments(c)\n        cx = int(M['m10']/M['m00'])\n        cy = int(M['m01']/M['m00'])\n        \n        text_width, text_height = cv2.getTextSize(classes, FONT, FONT_SCALE, FONT_THICKNESS)[0]\n        \n        # Border and fill\n        cv2.drawContours(to_plot, [c], contourIdx=-1, color=[max(0, x-40) for x in color], thickness=10)\n        cv2.drawContours(cntr_img, [c], contourIdx=-1, color=(color), thickness=-1)\n        \n        # Text\n        cv2.putText(to_plot, classes, (cx-text_width//2,cy-text_height//2),\n                    FONT, FONT_SCALE, [min(255, x+40) for x in color], FONT_THICKNESS, FONT_LINE_TYPE)\n    \n    cv2.addWeighted(cntr_img, fill_alpha, to_plot, 1-fill_alpha, 0, to_plot)\n    plt.figure(figsize=(16,16))\n    plt.imshow(to_plot)\n    plt.axis(False)\n    plt.show()","metadata":{"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = EfficientNet.from_name('efficientnet-b0', num_classes = 19, in_channels = 4)\nmodel.load_state_dict(torch.load('../input/pretrained-net/state_dict.pth'))\nmodel = model.to(DEVICE)\nmodel.eval()","metadata":{"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATA_DIR = os.path.join(PATH,'hpa-single-cell-image-classification')\nTEST_DIR = os.path.join(DATA_DIR, 'test')\n\nTEST_IMG_PATHS = sorted([os.path.join(TEST_DIR, f_name) for f_name in os.listdir(TEST_DIR)])\nprint(f\"... The number of testing images is {len(TEST_IMG_PATHS)}\" \\\n      f\"\\n\\t--> i.e. {len(TEST_IMG_PATHS)//4} 4-channel images ...\")\n\nSUB_PATH = os.path.join(DATA_DIR, 'sample_submission.csv')\nsubmission_df = pd.read_csv(SUB_PATH)\n\nSWAP_PATH = os.path.join(PATH, 'efficientnet-inference/submission.csv')\nss_df = pd.read_csv(SWAP_PATH)\n\n\nprint(\"\\n\\nSAMPLE SUBMISSION DATAFRAME\\n\\n\")\ndisplay(ss_df)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\nIMAGE_SIZES = [1728, 2048, 3072, 4096]\nBATCH_SIZE = 1\nCONF_THRESH = 0.0\nTILE_SIZE = (256,256)\nSAMPLES = 4 \nsegmentator = CellSegmentator()\n\npredict_df_1728 = ss_df[ss_df.ImageWidth == IMAGE_SIZES[0]]\npredict_df_2048 = ss_df[ss_df.ImageWidth == IMAGE_SIZES[1]]\npredict_df_3072 = ss_df[ss_df.ImageWidth == IMAGE_SIZES[2]]\npredict_df_4096 = ss_df[ss_df.ImageWidth == IMAGE_SIZES[3]]\n\npredict_ids_1728 = predict_df_1728.ID.tolist() \npredict_ids_2048 = predict_df_2048.ID.tolist() \npredict_ids_3072 = predict_df_3072.ID.tolist() \npredict_ids_4096 = predict_df_4096.ID.tolist() ","metadata":{"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 1\nfinal_df = pd.DataFrame(columns = ['ID', 'ImageWidth', 'ImageHeight'], data = ss_df)\ndatas = [predict_ids_1728, predict_ids_2048, predict_ids_3072, predict_ids_4096]\nflatten = lambda t: [item for sublist in t for item in sublist]\n\nif IS_FINAL:\n    for i, data in enumerate(datas):\n        #loop through each set of prediction ids\n        img_size = IMAGE_SIZES[i]\n        if len(data) == 0:\n            #skip sets that don't have any images\n            print('skipping')\n        else:\n            predictions = []\n            sub_df = pd.DataFrame(columns=[\"ID\"], data=data)\n    \n            with torch.no_grad():\n                for size_idx, submission_ids in enumerate([data]):\n                    #loop through each id within each dataset\n                    size = IMAGE_SIZES[size_idx]\n                    \n                    print(f\"...WORKING... \\n\")\n                    \n                    #perform segmentation and prediction for each image\n                    for i in tqdm(range(0, len(submission_ids), BATCH_SIZE), total=int(np.ceil(len(submission_ids)/BATCH_SIZE))):\n                        #get numpy arrays for each image, stacked by channel\n                        batch_rgby_images = [\n                            load_image(submission_ids[i], TEST_DIR, testing = True)\n                        ]\n                        \n                        #perform segmentation\n                        cell_segmentations = segmentator.pred_cells([[rgby_image[j] for rgby_image in batch_rgby_images] for j in [0,2,3]])\n                        nuc_segmentations  = segmentator.pred_nuclei([rgby_image[2] for rgby_image in batch_rgby_images])\n                        \n                        #generate masks\n                        batch_masks = [label_cell(nuc_seg, cell_seg)[1].astype(np.uint8) for nuc_seg, cell_seg in zip(nuc_segmentations, cell_segmentations)]\n                        \n                        #delete these to free up memory?\n                        del cell_segmentations, nuc_segmentations\n                        gc.collect()\n                        \n                        batch_rgb_images = [rgby_image.transpose(1,2,0) for rgby_image in batch_rgby_images]\n                        \n                        #get bounding box for each segmented mask\n                        batch_cell_bboxes = [get_contour_bbox_from_raw(mask) for mask in batch_masks]\n                        \n                        #get encoded mask for single cell prediction\n                        submission_rles = [[encode_binary_mask(mask, mask_val=cell_id) for cell_id in range(1, mask.max()+1)] for mask in batch_masks]\n                        \n                        #cut out and resize tiles\n                        batch_cell_tiles = [[\n                            cv2.resize(\n                                pad_to_square(\n                                    rgb_image[bbox[1]:bbox[3], bbox[0]:bbox[2], ...]), \n                                TILE_SIZE, interpolation=cv2.INTER_CUBIC) for bbox in bboxes] \n                            for bboxes, rgb_image in zip(batch_cell_bboxes, batch_rgb_images)\n                        ]\n                        \n                        #make sure tiles are in pytorch approved format\n                        batch_cell_tiles_torchd = [get_torchd(tile, DEVICE) for tile in batch_cell_tiles]\n                        \n                        #generate predictions from model\n                        batch_o_preds = [nnf.softmax(model(tile), dim=1) for tile in batch_cell_tiles_torchd]\n                        batch_o_preds = [[pred.cpu() for pred in cell_preds] for cell_preds in batch_o_preds]\n                        batch_o_preds = [[pred.detach().numpy() for pred in cell_preds] for cell_preds in batch_o_preds]\n                        \n                        #identify top labels\n                        batch_confs = [[pred[np.where(pred>CONF_THRESH)] for pred in o_preds] for o_preds in batch_o_preds]\n                        batch_preds = [[np.where(pred>CONF_THRESH)[0] for pred in o_preds] for o_preds in batch_o_preds]\n                        \n                        for j, preds in enumerate(batch_preds):\n                            for k in range(len(preds)):\n                                if preds[k].size==0:\n                                    batch_preds[j][k]=np.array([18,])\n                                    batch_confs[j][k]=np.array([1-np.max(batch_o_preds[j][k]),])\n                        \n                       \n                        #make prediction strings\n                        submission_strings = [flatten_list_of_lists([[m,]*len(p) for m, p in zip(masks, preds)]) for masks, preds in zip(submission_rles, batch_preds)]\n                        batch_preds = [flatten_list_of_lists(preds, to_string=True) for preds in batch_preds]\n                        batch_confs = [[f\"{conf:.4f}\" for cell_confs in confs for conf in cell_confs] for confs in batch_confs]\n                        prediction = [\" \".join(flatten_list_of_lists(zip(*[preds,confs,masks]))) for preds, confs, masks in zip(batch_preds, batch_confs, submission_rles)]\n                        predictions.append(prediction)\n                    predictions = flatten(predictions)\n                    sub_df['PredictionString' + str(img_size)] = predictions\n            final_df = final_df.merge(sub_df, how = 'left', on = 'ID')\n            display(final_df)\n    final_df['PredictionString'] = np.where(final_df['PredictionString1728'].notna(), final_df['PredictionString1728'], 0)\n    final_df['PredictionString'] = np.where(final_df['PredictionString2048'].notna(), final_df['PredictionString2048'], final_df['PredictionString'])\n    final_df['PredictionString'] = np.where(final_df['PredictionString3072'].notna(), final_df['PredictionString3072'], final_df['PredictionString'])\n\n    final_df = final_df.drop(columns = ['PredictionString1728', 'PredictionString2048', 'PredictionString3072'], axis = 1)\n    display(final_df.head(10))\nelse:\n    final_df = ss_df\n    display(final_df.head())\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ss_df = submission_df.merge(final_df, how=\"left\", on=\"ID\")\nss_df[\"PredictionString\"] = ss_df.apply(create_pred_col, axis=1)\nss_df = ss_df.drop(columns=[\"PredictionString_x\", \"PredictionString_y\", \"ImageWidth_y\", \"ImageHeight_y\"])\nss_df = ss_df.rename(columns = {'ImageWidth_x': 'ImageWidth', 'ImageHeight_x': 'ImageHeight'})\nss_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ss_df.to_csv(\"/kaggle/working/submission.csv\", index=None)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}