{
"cells": [
{
"cell_type": "markdown",
"id": "925cb362-2b6f-4375-9e18-22ae9c224f4b",
"metadata": {},
"source": [
"# Eroded Otsu-labeling\n",
"This operation segments and labels an image using blurring, Otsu-thresholding, binary erosion and masked Voronoi-labeling.\n",
"\n",
"After bluring and thresholding using Otsu's method, iterative binary erosion is applied. Objects in the eroded image are labeled using connected component labeling and these labels are dilated to fit again into the initial binary image using masked-Voronoi labeling.\n",
"\n",
"This function is similar to `voronoi_otsu_labeling`. It is intended to deal better in cases where labels of objects swapping into each other if objects are dense. Like when using Voronoi-Otsu-labeling, small objects may disappear when applying this operation.\n",
"\n",
"This function is inspired by a similar [implementation in Java](https://github.com/biovoxxel/bv3dbox/blob/9e38ed02cff606e7e8fbe57db0f6af810bf1a83a/BioVoxxel_3D_Box/src/main/java/de/biovoxxel/bv3dbox/plugins/BV_LabelSplitter.java#L83) by Jan Brocher (Biovoxxel) in the [Biovoxxel toolbox](https://zenodo.org/badge/latestdoi/434949702). Big thanks Jan!"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "8d145bbd-da76-4b81-9355-82db031c1dfe",
"metadata": {},
"outputs": [],
"source": [
"from skimage.data import cells3d\n",
"import pyclesperanto_prototype as cle\n",
"import napari_segment_blobs_and_things_with_membranes as nsbatwm"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "eb4a2ea5-a362-426d-807a-f7bbb375fd4e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(60, 2, 256, 256)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"image = cells3d()\n",
"image.shape"
]
},
{
"cell_type": "markdown",
"id": "380e59ab-2a3e-4650-a866-c5d13315ad71",
"metadata": {},
"source": [
"We just crop out a 2D slice."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "997d3d15-f380-436d-b819-60f6b1ed8672",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (256, 256) | \n",
"dtype | float32 | \n",
"size | 256.0 kB | \n",
"min | 1091.0 | max | 58327.0 | \n",
" \n",
" \n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[ 8868., 6923., 5690., ..., 13942., 12804., 14653.],\n",
" [ 7113., 5501., 5216., ..., 16739., 13657., 15554.],\n",
" [ 5833., 7160., 5928., ..., 15838., 16739., 17166.],\n",
" ...,\n",
" [ 2513., 3936., 3414., ..., 3699., 4126., 4220.],\n",
" [ 3319., 3272., 2513., ..., 3699., 3367., 2940.],\n",
" [ 3130., 3794., 3225., ..., 2987., 3746., 4315.]],\n",
" dtype=float32)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"nuclei = cle.asarray(image[30, 1])\n",
"nuclei"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "598aa36f-a3cd-443f-8165-2d88d7b0e0ba",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (256, 256) | \n",
"dtype | uint32 | \n",
"size | 256.0 kB | \n",
"min | 0.0 | max | 17.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"labels = cle.eroded_otsu_labeling(nuclei, number_of_erosions=11, outline_sigma=4)\n",
"labels"
]
},
{
"cell_type": "markdown",
"id": "f2e9b308-7955-49ba-9887-ad83fac8e505",
"metadata": {},
"source": [
"## Parameter: number_of_erosions\n",
"If the specified number of erosions is too small, sticky objects will be labeled together."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "69e13d04-152f-4ee5-8dd5-4d8db331c4f9",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (256, 256) | \n",
"dtype | uint32 | \n",
"size | 256.0 kB | \n",
"min | 0.0 | max | 16.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"labels = cle.eroded_otsu_labeling(nuclei, number_of_erosions=5, outline_sigma=4)\n",
"labels"
]
},
{
"cell_type": "markdown",
"id": "607ac2f1-b594-4f82-98dc-27e305d8fe96",
"metadata": {},
"source": [
"If too many erosions are configured, objects may disappear."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "62b486af-235e-42be-9785-9009ff3df68a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (256, 256) | \n",
"dtype | uint32 | \n",
"size | 256.0 kB | \n",
"min | 0.0 | max | 3.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"labels = cle.eroded_otsu_labeling(nuclei, number_of_erosions=20, outline_sigma=4)\n",
"labels"
]
},
{
"cell_type": "markdown",
"id": "83b2ece5-b769-4e42-858f-dc26ec06cfc0",
"metadata": {},
"source": [
"## Parameter: outline_sigma\n",
"With this outline, you can control the denoising before thresholding. If this value is too low, objects may have noisy edges and holes lead to more object-splits."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "f3f28d92-1f8c-4a86-adb5-d0eb9fbc4eb7",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (256, 256) | \n",
"dtype | uint32 | \n",
"size | 256.0 kB | \n",
"min | 0.0 | max | 37.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"labels = cle.eroded_otsu_labeling(nuclei, number_of_erosions=5, outline_sigma=1)\n",
"labels"
]
},
{
"cell_type": "markdown",
"id": "a20547ce-b34d-4417-bc93-5ff4f0d4c763",
"metadata": {},
"source": [
"If this value is too high, object outlines may be not fitting to the original objects anymore."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "ab4de1df-5371-4f43-a699-39123c1ce007",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"cle._ image \n",
"\n",
"shape | (256, 256) | \n",
"dtype | uint32 | \n",
"size | 256.0 kB | \n",
"min | 0.0 | max | 11.0 | \n",
" \n",
"\n",
" | \n",
"
\n",
"
"
],
"text/plain": [
"cl.OCLArray([[0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" ...,\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0],\n",
" [0, 0, 0, ..., 0, 0, 0]], dtype=uint32)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"labels = cle.eroded_otsu_labeling(nuclei, number_of_erosions=11, outline_sigma=10)\n",
"labels"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bad3d788-baf1-482a-a818-3596ecd49e08",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.15"
}
},
"nbformat": 4,
"nbformat_minor": 5
}