In [1]:
Copied!
# Setup a simple segmentation function
import numpy as np
import skimage
def otsu_threshold_segmentation(image: np.ndarray, max_label: int) -> np.ndarray:
"""Simple segmentation using Otsu thresholding."""
threshold = skimage.filters.threshold_otsu(image)
binary = image > threshold
label_image = skimage.measure.label(binary)
label_image += max_label
label_image = np.where(binary, label_image, 0)
return label_image.astype(np.uint32)
# Setup a simple segmentation function
import numpy as np
import skimage
def otsu_threshold_segmentation(image: np.ndarray, max_label: int) -> np.ndarray:
"""Simple segmentation using Otsu thresholding."""
threshold = skimage.filters.threshold_otsu(image)
binary = image > threshold
label_image = skimage.measure.label(binary)
label_image += max_label
label_image = np.where(binary, label_image, 0)
return label_image.astype(np.uint32)
Step 2: Open the OmeZarr container¶
In [2]:
Copied!
from pathlib import Path
from ngio import open_ome_zarr_container
from ngio.utils import download_ome_zarr_dataset
# Download the dataset
download_dir = Path(".").absolute().parent.parent / "data"
hcs_path = download_ome_zarr_dataset("CardiomyocyteTiny", download_dir=download_dir)
image_path = hcs_path / "B" / "03" / "0"
# Open the ome-zarr container
ome_zarr = open_ome_zarr_container(image_path)
from pathlib import Path
from ngio import open_ome_zarr_container
from ngio.utils import download_ome_zarr_dataset
# Download the dataset
download_dir = Path(".").absolute().parent.parent / "data"
hcs_path = download_ome_zarr_dataset("CardiomyocyteTiny", download_dir=download_dir)
image_path = hcs_path / "B" / "03" / "0"
# Open the ome-zarr container
ome_zarr = open_ome_zarr_container(image_path)
Unzipping contents of '/home/runner/work/ngio/ngio/data/20200812-CardiomyocyteDifferentiation14-Cycle1-tiny.zarr.zip' to '/home/runner/work/ngio/ngio/data/tmp'
Step 3: Segment the image¶
For this example, we will not segment the image all at once. Instead we will iterate over the image FOVs and segment them one by one.
In [3]:
Copied!
from ngio.experimental.iterators import SegmentationIterator
# First we will need the image object and the FOVs table
image = ome_zarr.get_image()
roi_table = ome_zarr.get_roi_table("FOV_ROI_table")
# Second we need to derive a new label image to use as target for the segmentation
label = ome_zarr.derive_label("new_label", overwrite=True)
# Setup the segmentation iterator
seg_iterator = SegmentationIterator(
input_image=image,
output_label=label,
channel_selection="DAPI",
axes_order=["z", "y", "x"],
)
seg_iterator = seg_iterator.product(roi_table)
# Make sure that if other axes are present they are iterated over
seg_iterator = seg_iterator.by_zyx()
max_label = 0 # We will use this to avoid label collisions
for image_data, label_writer in seg_iterator.iter_as_numpy():
roi_segmentation = otsu_threshold_segmentation(
image_data, max_label
) # Segment the image
max_label = roi_segmentation.max() # Get the max label for the next iteration
label_writer(patch=roi_segmentation) # Write the segmentation back to the label
# No need to consolidate, the iterator does it automatically after the last write
from ngio.experimental.iterators import SegmentationIterator
# First we will need the image object and the FOVs table
image = ome_zarr.get_image()
roi_table = ome_zarr.get_roi_table("FOV_ROI_table")
# Second we need to derive a new label image to use as target for the segmentation
label = ome_zarr.derive_label("new_label", overwrite=True)
# Setup the segmentation iterator
seg_iterator = SegmentationIterator(
input_image=image,
output_label=label,
channel_selection="DAPI",
axes_order=["z", "y", "x"],
)
seg_iterator = seg_iterator.product(roi_table)
# Make sure that if other axes are present they are iterated over
seg_iterator = seg_iterator.by_zyx()
max_label = 0 # We will use this to avoid label collisions
for image_data, label_writer in seg_iterator.iter_as_numpy():
roi_segmentation = otsu_threshold_segmentation(
image_data, max_label
) # Segment the image
max_label = roi_segmentation.max() # Get the max label for the next iteration
label_writer(patch=roi_segmentation) # Write the segmentation back to the label
# No need to consolidate, the iterator does it automatically after the last write
Plot the segmentation¶
In [4]:
Copied!
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
rand_cmap = np.random.rand(1000, 3)
rand_cmap[0] = 0
rand_cmap = ListedColormap(rand_cmap)
fig, axs = plt.subplots(2, 1, figsize=(8, 4))
axs[0].set_title("Original image")
axs[0].imshow(image.get_as_numpy(c=0, z=1, axes_order=["y", "x"]), cmap="gray")
axs[1].set_title("Final segmentation")
axs[1].imshow(label.get_as_numpy(z=1, axes_order=["y", "x"]), cmap=rand_cmap)
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
rand_cmap = np.random.rand(1000, 3)
rand_cmap[0] = 0
rand_cmap = ListedColormap(rand_cmap)
fig, axs = plt.subplots(2, 1, figsize=(8, 4))
axs[0].set_title("Original image")
axs[0].imshow(image.get_as_numpy(c=0, z=1, axes_order=["y", "x"]), cmap="gray")
axs[1].set_title("Final segmentation")
axs[1].imshow(label.get_as_numpy(z=1, axes_order=["y", "x"]), cmap=rand_cmap)
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
Step 4: Masked image segmentation¶
In this example we will use a mask to restrict the segmentation to certain areas of the image. In this case we will create a simple mask for illustration purposes, but in a real case scenario the mask could come from another segmentation mask.
In [5]:
Copied!
# Create a basic mask for illustration purposes
mask = ome_zarr.derive_label("mask", overwrite=True)
mask_data = mask.get_as_numpy(axes_order=["z", "y", "x"])
mask_data[:, 200:-200, 500:2000] = 1
mask_data[:, 200:-200, 3000:-500] = 2
mask_data[:, 600:-600, 1200:-1000] = 0
mask_data[:, 700:-700, 1600:-1500] = 3
mask.set_array(mask_data, axes_order=["z", "y", "x"])
mask.consolidate()
fig, axs = plt.subplots(2, 1, figsize=(8, 4))
axs[0].set_title("Original image")
axs[0].imshow(image.get_as_numpy(c=0, z=1, axes_order=["y", "x"]), cmap="gray")
axs[1].set_title("Mask")
axs[1].imshow(mask.get_as_numpy(z=1, axes_order=["y", "x"]), cmap=rand_cmap)
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
# Create a basic mask for illustration purposes
mask = ome_zarr.derive_label("mask", overwrite=True)
mask_data = mask.get_as_numpy(axes_order=["z", "y", "x"])
mask_data[:, 200:-200, 500:2000] = 1
mask_data[:, 200:-200, 3000:-500] = 2
mask_data[:, 600:-600, 1200:-1000] = 0
mask_data[:, 700:-700, 1600:-1500] = 3
mask.set_array(mask_data, axes_order=["z", "y", "x"])
mask.consolidate()
fig, axs = plt.subplots(2, 1, figsize=(8, 4))
axs[0].set_title("Original image")
axs[0].imshow(image.get_as_numpy(c=0, z=1, axes_order=["y", "x"]), cmap="gray")
axs[1].set_title("Mask")
axs[1].imshow(mask.get_as_numpy(z=1, axes_order=["y", "x"]), cmap=rand_cmap)
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
In [6]:
Copied!
from ngio.experimental.iterators import MaskedSegmentationIterator
# First we will need the masked image object
# (that contains the masking table information inside)
image = ome_zarr.get_masked_image(masking_label_name="mask")
# Second we need to derive a new label image to use as target for the segmentation
label = ome_zarr.derive_label("masked_new_label", overwrite=True)
# Setup the masked segmentation iterator
seg_iterator = MaskedSegmentationIterator(
input_image=image,
output_label=label,
channel_selection="DAPI",
axes_order=["z", "y", "x"],
)
# Make sure that if other axes are present they are iterated over
seg_iterator = seg_iterator.by_zyx()
max_label = 0 # We will use this to avoid label collisions
for image_data, label_writer in seg_iterator.iter_as_numpy():
roi_segmentation = otsu_threshold_segmentation(
image_data, max_label
) # Segment the image
max_label = roi_segmentation.max() # Get the max label for the next iteration
label_writer(patch=roi_segmentation) # Write the segmentation back to the label
# No need to consolidate, the iterator does it automatically after the last write
from ngio.experimental.iterators import MaskedSegmentationIterator
# First we will need the masked image object
# (that contains the masking table information inside)
image = ome_zarr.get_masked_image(masking_label_name="mask")
# Second we need to derive a new label image to use as target for the segmentation
label = ome_zarr.derive_label("masked_new_label", overwrite=True)
# Setup the masked segmentation iterator
seg_iterator = MaskedSegmentationIterator(
input_image=image,
output_label=label,
channel_selection="DAPI",
axes_order=["z", "y", "x"],
)
# Make sure that if other axes are present they are iterated over
seg_iterator = seg_iterator.by_zyx()
max_label = 0 # We will use this to avoid label collisions
for image_data, label_writer in seg_iterator.iter_as_numpy():
roi_segmentation = otsu_threshold_segmentation(
image_data, max_label
) # Segment the image
max_label = roi_segmentation.max() # Get the max label for the next iteration
label_writer(patch=roi_segmentation) # Write the segmentation back to the label
# No need to consolidate, the iterator does it automatically after the last write
In [7]:
Copied!
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
fig, axs = plt.subplots(2, 1, figsize=(8, 4))
axs[0].set_title("Original image")
axs[0].imshow(image.get_as_numpy(c=0, z=1, axes_order=["y", "x"]), cmap="gray")
axs[1].set_title("Final segmentation")
axs[1].imshow(label.get_as_numpy(z=1, axes_order=["y", "x"]), cmap=rand_cmap)
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
fig, axs = plt.subplots(2, 1, figsize=(8, 4))
axs[0].set_title("Original image")
axs[0].imshow(image.get_as_numpy(c=0, z=1, axes_order=["y", "x"]), cmap="gray")
axs[1].set_title("Final segmentation")
axs[1].imshow(label.get_as_numpy(z=1, axes_order=["y", "x"]), cmap=rand_cmap)
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
In [ ]:
Copied!