{ "cells": [ { "cell_type": "markdown", "id": "8a1bc074-7648-4559-a012-e569e426ac5f", "metadata": {}, "source": [ "# Merging labels\n", "In principle, all segmentation algorithms are limited. In case results are sub-optimal and no better segmentation algorithm is available, post-processing labels may be an option. There are some functions available for merging labels according to their properties such as intensity along the edge where labels touch the pixel count of pair-wise combined labels." ] }, { "cell_type": "code", "execution_count": 1, "id": "2cff9edb-3a15-4fc6-8ffa-381dc2bafb5d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pyclesperanto_prototype as cle\n", "from napari_segment_blobs_and_things_with_membranes import local_minima_seeded_watershed\n", "import numpy as np\n", "cle.select_device(\"TX\")" ] }, { "cell_type": "markdown", "id": "33f6f96f-be5f-422b-b4b2-161dd8959df2", "metadata": {}, "source": [ "## Merging touching labels\n", "The most trivial use-case might be merging labeled objects that touch." ] }, { "cell_type": "code", "execution_count": 2, "id": "68c97923-2988-41ed-ad84-d3cb08f702a6", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "
\n", "\n", "\n", "cle._ image
\n", "\n", "\n", "\n", "\n", "\n", "
shape(254, 256)
dtypeuint32
size254.0 kB
min0.0
max72.0
\n", "\n", "
" ], "text/plain": [ "cl.OCLArray([[ 0, 0, 0, ..., 68, 68, 68],\n", " [ 0, 0, 0, ..., 68, 68, 68],\n", " [ 0, 0, 0, ..., 68, 68, 68],\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": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "blobs = cle.imread(\"../../data/blobs.tif\")\n", "blobs_labels = cle.voronoi_otsu_labeling(blobs, spot_sigma=3)\n", "blobs_labels" ] }, { "cell_type": "code", "execution_count": 3, "id": "82186da8-b6e3-450b-951a-56e057955a71", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "
\n", "\n", "\n", "cle._ image
\n", "\n", "\n", "\n", "\n", "\n", "
shape(254, 256)
dtypeuint32
size254.0 kB
min0.0
max61.0
\n", "\n", "
" ], "text/plain": [ "cl.OCLArray([[ 0, 0, 0, ..., 57, 57, 57],\n", " [ 0, 0, 0, ..., 57, 57, 57],\n", " [ 0, 0, 0, ..., 57, 57, 57],\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": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cle.merge_touching_labels(blobs_labels)" ] }, { "cell_type": "markdown", "id": "73603a37-9126-445e-8c4a-96baad7c5085", "metadata": {}, "source": [ "## Merging labels according to border intensity\n", "As an example we use a cropped slice of the [`cells3d` example dataset in scikit-image](https://scikit-image.org/docs/stable/auto_examples/applications/plot_3d_image_processing.html)." ] }, { "cell_type": "code", "execution_count": 4, "id": "cd7487d7-d23f-4eda-9f91-3b86828a4b39", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "
\n", "\n", "\n", "cle._ image
\n", "\n", "\n", "\n", "\n", "\n", "
shape(100, 100)
dtypefloat32
size39.1 kB
min1062.0
max20614.0
\n", "\n", "
" ], "text/plain": [ "cl.OCLArray([[2029., 2518., 2368., ..., 2248., 1888., 1804.],\n", " [2425., 2415., 2490., ..., 1814., 1977., 2062.],\n", " [2085., 2293., 2316., ..., 1909., 1789., 1820.],\n", " ...,\n", " [3677., 2483., 2423., ..., 2233., 2456., 2359.],\n", " [2859., 2527., 2547., ..., 1936., 2399., 2111.],\n", " [2859., 2541., 2510., ..., 2332., 2248., 2066.]], dtype=float32)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "image = cle.imread(\"../../data/membranes_2d.tif\")[30:130, 0:100]\n", "image" ] }, { "cell_type": "markdown", "id": "bde3ea3a-92cd-4f0a-9127-100f2a2a37fb", "metadata": {}, "source": [ "In the following example, our cell in the center of the image was wrongly segmented as two cells:" ] }, { "cell_type": "code", "execution_count": 5, "id": "b1c48e5a-0b91-4586-9259-b82c63621671", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "
\n", "\n", "\n", "nsbatwm made image
\n", "\n", "\n", "\n", "\n", "\n", "
shape(100, 100)
dtypeint32
size39.1 kB
min1
max12
\n", "\n", "
" ], "text/plain": [ "StackViewNDArray([[ 5, 5, 5, ..., 3, 2, 2],\n", " [ 5, 5, 5, ..., 3, 3, 2],\n", " [ 5, 5, 5, ..., 3, 3, 3],\n", " ...,\n", " [11, 11, 11, ..., 12, 12, 12],\n", " [11, 11, 11, ..., 12, 12, 12],\n", " [11, 11, 11, ..., 12, 12, 12]])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "labels = local_minima_seeded_watershed(image, spot_sigma=5, outline_sigma=0)\n", "labels" ] }, { "cell_type": "markdown", "id": "d98d6b8a-7b3b-41c3-9aee-965a7b275af5", "metadata": {}, "source": [ "This can be corrected by merging cells with border intensity below a given threshold." ] }, { "cell_type": "code", "execution_count": 6, "id": "7cd7a49e-8f4e-4d89-89be-779c7eb8f944", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "c:\\structure\\code\\pyclesperanto_prototype\\pyclesperanto_prototype\\_tier3\\_generate_touch_mean_intensity_matrix.py:30: UserWarning: generate_touch_mean_intensity_matrix is supposed to work with images of integer type only.\n", "Loss of information is possible when passing non-integer images.\n", " warnings.warn(\"generate_touch_mean_intensity_matrix is supposed to work with images of integer type only.\\n\" +\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "
\n", "\n", "\n", "cle._ image
\n", "\n", "\n", "\n", "\n", "\n", "
shape(100, 100)
dtypeuint32
size39.1 kB
min1.0
max8.0
\n", "\n", "
" ], "text/plain": [ "cl.OCLArray([[3, 3, 3, ..., 2, 2, 2],\n", " [3, 3, 3, ..., 2, 2, 2],\n", " [3, 3, 3, ..., 2, 2, 2],\n", " ...,\n", " [7, 7, 7, ..., 8, 8, 8],\n", " [7, 7, 7, ..., 8, 8, 8],\n", " [7, 7, 7, ..., 8, 8, 8]], dtype=uint32)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "merged_labels = cle.merge_labels_with_border_intensity_within_range(image, labels, maximum_intensity=5000)\n", "merged_labels" ] }, { "cell_type": "code", "execution_count": null, "id": "12cc5970-d150-403d-94a7-8d1c34ce3e92", "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" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 5 }