{"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 stardist","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-07-06T21:17:07.331541Z","iopub.execute_input":"2023-07-06T21:17:07.332608Z","iopub.status.idle":"2023-07-06T21:17:24.139544Z","shell.execute_reply.started":"2023-07-06T21:17:07.332563Z","shell.execute_reply":"2023-07-06T21:17:24.138017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from __future__ import print_function, unicode_literals, absolute_import, division\nimport sys\nimport numpy as np\nimport matplotlib\nimport matplotlib.pyplot as plt\nimport random\n\nimport imageio\nfrom glob import glob\nfrom tqdm import tqdm\nimport cv2\nfrom csbdeep.utils import Path, normalize\nimport pandas as pd\nimport time\nfrom sklearn.model_selection import train_test_split\nfrom skimage.transform import resize\n\nfrom stardist import fill_label_holes, random_label_cmap, calculate_extents, gputools_available\nfrom stardist.matching import matching, matching_dataset\nfrom stardist.models import Config2D, StarDist2D, StarDistData2D\n     ","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:36:40.587620Z","iopub.execute_input":"2023-07-06T21:36:40.588312Z","iopub.status.idle":"2023-07-06T21:36:40.630791Z","shell.execute_reply.started":"2023-07-06T21:36:40.588277Z","shell.execute_reply":"2023-07-06T21:36:40.629944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.random.seed(42)\nlbl_cmap = random_label_cmap()","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:17:34.939356Z","iopub.execute_input":"2023-07-06T21:17:34.939697Z","iopub.status.idle":"2023-07-06T21:17:35.345313Z","shell.execute_reply.started":"2023-07-06T21:17:34.939662Z","shell.execute_reply":"2023-07-06T21:17:35.344294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BASE_DIR = \"/kaggle/input/hubmap-hacking-the-human-vasculature/\"","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:17:35.346674Z","iopub.execute_input":"2023-07-06T21:17:35.347543Z","iopub.status.idle":"2023-07-06T21:17:35.352411Z","shell.execute_reply.started":"2023-07-06T21:17:35.347506Z","shell.execute_reply":"2023-07-06T21:17:35.351418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"polygons_df = pd.read_json('/kaggle/input/hubmap-hacking-the-human-vasculature/polygons.jsonl', lines=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:17:35.356356Z","iopub.execute_input":"2023-07-06T21:17:35.356911Z","iopub.status.idle":"2023-07-06T21:17:39.476737Z","shell.execute_reply.started":"2023-07-06T21:17:35.356712Z","shell.execute_reply":"2023-07-06T21:17:39.475791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_image(image_id: str) -> np.array:\n    \"\"\"Takes an image id and gets the corresponding image\"\"\"\n    image_path = BASE_DIR + \"train/\" + image_id + \".tif\"\n    image = imageio.v2.imread(image_path)\n    image = resize(image, (120, 120), anti_aliasing=True)\n    return image\n\n_ = plt.imshow(load_image('0006ff2aa7cd'), cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:15.571494Z","iopub.execute_input":"2023-07-06T21:40:15.571904Z","iopub.status.idle":"2023-07-06T21:40:15.905233Z","shell.execute_reply.started":"2023-07-06T21:40:15.571869Z","shell.execute_reply":"2023-07-06T21:40:15.904102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_mask(image_id: str) -> np.array:\n    \"\"\"Takes a image id and gets corresponding mask\"\"\"\n    mask = np.zeros((512, 512, 1), dtype=np.uint8)\n    annots = polygons_df.loc[polygons_df[\"id\"] == image_id, 'annotations'].iloc[0]\n    for annot in annots:\n        annot_type = annot['type']\n        coordinates = annot['coordinates']\n        if annot_type == 'blood_vessel':\n            cv2.fillPoly(mask, [np.array(coordinates)], (255,))\n    mask = mask/255\n    mask = resize(mask, (120, 120), anti_aliasing=True)\n    mask = mask.astype(np.int64)\n    return np.squeeze(mask, axis=-1)\n\n_ = plt.imshow(load_mask('0006ff2aa7cd'), cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:20.248679Z","iopub.execute_input":"2023-07-06T21:40:20.249287Z","iopub.status.idle":"2023-07-06T21:40:20.618646Z","shell.execute_reply.started":"2023-07-06T21:40:20.249246Z","shell.execute_reply":"2023-07-06T21:40:20.617592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_ids = polygons_df[\"id\"].to_numpy()[:250]\nprint(image_ids[:5])\nprint(f'There are {len(image_ids)} images')","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:22.109687Z","iopub.execute_input":"2023-07-06T21:40:22.110090Z","iopub.status.idle":"2023-07-06T21:40:22.116872Z","shell.execute_reply.started":"2023-07-06T21:40:22.110060Z","shell.execute_reply":"2023-07-06T21:40:22.115603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"start_time = time.time()\nX = list(map(load_image,image_ids))\nY = list(map(load_mask,image_ids))\nn_channel = 1 if X[0].ndim == 2 else X[0].shape[-1]\nend_time = time.time()\n\naxis_norm = (0,1)   # normalize channels independently\nif n_channel > 1:\n    print(\"Normalizing image channels %s.\" % ('jointly' if axis_norm is None or 2 in axis_norm else 'independently'))\n    sys.stdout.flush()\n\nX = [normalize(x,1,99.8,axis=axis_norm) for x in tqdm(X)]\nY = [fill_label_holes(y) for y in tqdm(Y)]\n\nprint(f\"took {end_time - start_time} seconds\")","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:23.512044Z","iopub.execute_input":"2023-07-06T21:40:23.512424Z","iopub.status.idle":"2023-07-06T21:40:37.531617Z","shell.execute_reply.started":"2023-07-06T21:40:23.512395Z","shell.execute_reply":"2023-07-06T21:40:37.530517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'There are {len(X)} images')\nprint(f'There are {len(Y)} masks')","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:39.943564Z","iopub.execute_input":"2023-07-06T21:40:39.943943Z","iopub.status.idle":"2023-07-06T21:40:39.949991Z","shell.execute_reply.started":"2023-07-06T21:40:39.943911Z","shell.execute_reply":"2023-07-06T21:40:39.949023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_example(X: np.array, Y: np.array, index=0):\n    \"\"\"Sanity check\"\"\"\n    assert len(X) == len(Y)\n    \n    fig, axs = plt.subplots(1, 2, figsize=(12,6))\n    axs[0].imshow(X[index])\n    axs[0].set_title(f\"Image{X[index].shape}\")\n    \n    axs[1].imshow(Y[index], cmap='gray')\n    axs[1].set_title(f\"Mask {Y[index].shape}\")\n\n\nplot_example(X, Y, 0)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:41.389851Z","iopub.execute_input":"2023-07-06T21:40:41.390528Z","iopub.status.idle":"2023-07-06T21:40:41.898594Z","shell.execute_reply.started":"2023-07-06T21:40:41.390485Z","shell.execute_reply":"2023-07-06T21:40:41.897661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_val_split(X: np.array, Y: np.array, train_size: int) -> (np.array, np.array, np.array, np.array):\n    \"\"\"Splits X and Y into trianing and validation split\"\"\"\n    assert train_size > 0 and train_size < 1, \"Choose a split value between 0 and 1\"\n    assert len(X) == len(Y) and len(X) > 1, \"ensure X and Y are of equal length and there is more than on example\"\n    \n    X_train, X_val, Y_train, Y_val = train_test_split(X, Y, train_size=train_size, random_state=42)\n    \n    assert len(X_train) == len(Y_train) and len(X_val) == len(Y_val)\n    print(f\"There are {len(X_train)} training examples and {len(Y_val)} validation examples\")\n    return X_train, X_val, Y_train, Y_val\n\nX_train, X_val, Y_train, Y_val = train_val_split(X, Y, train_size = 0.8)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:43.956241Z","iopub.execute_input":"2023-07-06T21:40:43.956611Z","iopub.status.idle":"2023-07-06T21:40:43.969941Z","shell.execute_reply.started":"2023-07-06T21:40:43.956577Z","shell.execute_reply":"2023-07-06T21:40:43.968999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_example(X_train, Y_train, 10)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:45.662900Z","iopub.execute_input":"2023-07-06T21:40:45.663247Z","iopub.status.idle":"2023-07-06T21:40:46.170970Z","shell.execute_reply.started":"2023-07-06T21:40:45.663219Z","shell.execute_reply":"2023-07-06T21:40:46.169873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_example(X_val, Y_val, 10)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:51.190975Z","iopub.execute_input":"2023-07-06T21:40:51.191336Z","iopub.status.idle":"2023-07-06T21:40:51.869294Z","shell.execute_reply.started":"2023-07-06T21:40:51.191307Z","shell.execute_reply":"2023-07-06T21:40:51.868410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(Config2D.__doc__)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:40:53.968526Z","iopub.execute_input":"2023-07-06T21:40:53.968906Z","iopub.status.idle":"2023-07-06T21:40:53.975243Z","shell.execute_reply.started":"2023-07-06T21:40:53.968874Z","shell.execute_reply":"2023-07-06T21:40:53.974006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Define the config by setting some parameter values\n\n# 32 is a good default choice (see 1_data.ipynb)\nn_rays = 64  #Number of radial directions for the star-convex polygon.\n\n# Use OpenCL-based computations for data generator during training (requires 'gputools')\nuse_gpu = False and gputools_available()\n\n# Predict on subsampled grid for increased efficiency and larger field of view\ngrid = (2,2)\n\nconf = Config2D (\n    n_rays       = n_rays,\n    grid         = grid,\n    use_gpu      = use_gpu,\n    n_channel_in = n_channel,\n    train_patch_size = (64, 64)\n)\nprint(conf)\nvars(conf)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:42:09.611892Z","iopub.execute_input":"2023-07-06T21:42:09.612901Z","iopub.status.idle":"2023-07-06T21:42:09.624868Z","shell.execute_reply.started":"2023-07-06T21:42:09.612854Z","shell.execute_reply":"2023-07-06T21:42:09.623143Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if use_gpu:\n    from csbdeep.utils.tf import limit_gpu_memory\n    # adjust as necessary: limit GPU memory to be used by TensorFlow to leave some to OpenCL-based computations\n    limit_gpu_memory(0.8)\n    # alternatively, try this:\n    # limit_gpu_memory(None, allow_growth=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:42:12.476182Z","iopub.execute_input":"2023-07-06T21:42:12.476587Z","iopub.status.idle":"2023-07-06T21:42:12.481892Z","shell.execute_reply.started":"2023-07-06T21:42:12.476554Z","shell.execute_reply":"2023-07-06T21:42:12.480818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = StarDist2D(conf, name='stardist_tutorial', basedir='/kaggle/working/models')","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:42:12.917655Z","iopub.execute_input":"2023-07-06T21:42:12.918394Z","iopub.status.idle":"2023-07-06T21:42:13.181739Z","shell.execute_reply.started":"2023-07-06T21:42:12.918357Z","shell.execute_reply":"2023-07-06T21:42:13.180710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"median_size = calculate_extents(list(Y_train), np.median)\nfov = np.array(model._axes_tile_overlap('YX'))\nprint(f\"median object size:      {median_size}\")\nprint(f\"network field of view :  {fov}\")\nif any(median_size > fov):\n    print(\"WARNING: median object size larger than field of view of the neural network.\")","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:42:16.003240Z","iopub.execute_input":"2023-07-06T21:42:16.003850Z","iopub.status.idle":"2023-07-06T21:42:16.389850Z","shell.execute_reply.started":"2023-07-06T21:42:16.003808Z","shell.execute_reply":"2023-07-06T21:42:16.388639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.train(X_train, Y_train, validation_data=(X_val,Y_val), epochs=100, steps_per_epoch=100)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:42:18.528633Z","iopub.execute_input":"2023-07-06T21:42:18.529269Z","iopub.status.idle":"2023-07-06T21:52:52.670981Z","shell.execute_reply.started":"2023-07-06T21:42:18.529220Z","shell.execute_reply":"2023-07-06T21:52:52.670003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.optimize_thresholds(X_val, Y_val)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:52:55.305258Z","iopub.execute_input":"2023-07-06T21:52:55.305625Z","iopub.status.idle":"2023-07-06T21:53:03.277063Z","shell.execute_reply.started":"2023-07-06T21:52:55.305591Z","shell.execute_reply":"2023-07-06T21:53:03.276031Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_model = StarDist2D(None, name='stardist_tutorial', basedir='/kaggle/working/models/')\n     ","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:53:19.634371Z","iopub.execute_input":"2023-07-06T21:53:19.635318Z","iopub.status.idle":"2023-07-06T21:53:20.059882Z","shell.execute_reply.started":"2023-07-06T21:53:19.635277Z","shell.execute_reply":"2023-07-06T21:53:20.058759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = my_model","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:53:22.029863Z","iopub.execute_input":"2023-07-06T21:53:22.030653Z","iopub.status.idle":"2023-07-06T21:53:22.036580Z","shell.execute_reply.started":"2023-07-06T21:53:22.030611Z","shell.execute_reply":"2023-07-06T21:53:22.035300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Y_val_pred = [model.predict_instances(x, n_tiles=model._guess_n_tiles(x), show_tile_progress=False)[0]\n              for x in tqdm(X_val)]\n","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:53:24.460684Z","iopub.execute_input":"2023-07-06T21:53:24.461109Z","iopub.status.idle":"2023-07-06T21:53:28.758281Z","shell.execute_reply.started":"2023-07-06T21:53:24.461077Z","shell.execute_reply":"2023-07-06T21:53:28.757342Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#PLot original labels and predcitions\ntaus = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]\nstats = [matching_dataset(Y_val, Y_val_pred, thresh=t, show_progress=False) for t in tqdm(taus)]\n\nstats[taus.index(0.5)]","metadata":{"execution":{"iopub.status.busy":"2023-07-06T21:53:32.856843Z","iopub.execute_input":"2023-07-06T21:53:32.857209Z","iopub.status.idle":"2023-07-06T21:53:33.283565Z","shell.execute_reply.started":"2023-07-06T21:53:32.857177Z","shell.execute_reply":"2023-07-06T21:53:33.282656Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_prediciton(X: np.array, Y: np.array, num_examples: int):\n    assert len(X) == len(Y), \"Ensure correct X and Y pairings have been placed\"\n    assert num_examples < len(X), \"choose fewer examples\"\n    \n    fig, axs = plt.subplots(num_examples - 1, 3, figsize=(8 , 32))\n    for i in range(0, num_examples - 1):\n        index = random.randint(0, len(X)- 1)\n        img = X[index]\n        mask = Y[index]\n        labels, details = model.predict_instances(img)\n        \n        axs[i, 0].imshow(img)\n        axs[i, 0].set_title(\"image\")\n        \n        axs[i, 1].imshow(mask, cmap='gray')\n        axs[i, 1].set_title(\"mask\")\n        \n        axs[i, 2].imshow(labels,cmap=lbl_cmap)\n        axs[i, 2].set_title(\"prediction\")\n\nplot_prediciton(X_train, Y_train, 10)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T22:01:59.598903Z","iopub.execute_input":"2023-07-06T22:01:59.600101Z","iopub.status.idle":"2023-07-06T22:02:08.126875Z","shell.execute_reply.started":"2023-07-06T22:01:59.600057Z","shell.execute_reply":"2023-07-06T22:02:08.125433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_stats(taus, stats):\n    fig, (ax1,ax2) = plt.subplots(1,2, figsize=(15,5))\n\n    for m in ('precision', 'recall', 'accuracy', 'f1', 'mean_true_score', 'mean_matched_score', 'panoptic_quality'):\n        ax1.plot(taus, [s._asdict()[m] for s in stats], '.-', lw=2, label=m)\n    ax1.set_xlabel('IoU threshold ')\n    ax1.set_ylabel('Metric value')\n    ax1.grid()\n    ax1.legend()\n\n    for m in ('fp', 'tp', 'fn'):\n        ax2.plot(taus, [s._asdict()[m] for s in stats], '.-', lw=2, label=m)\n    ax2.set_xlabel('IoU threshold ')\n    ax2.set_ylabel('Number #')\n    ax2.grid()\n    ax2.legend()\n\nplot_stats(taus, stats)","metadata":{"execution":{"iopub.status.busy":"2023-07-06T22:00:31.872718Z","iopub.execute_input":"2023-07-06T22:00:31.873682Z","iopub.status.idle":"2023-07-06T22:00:32.606230Z","shell.execute_reply.started":"2023-07-06T22:00:31.873646Z","shell.execute_reply":"2023-07-06T22:00:32.605209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}