{
"cells": [
{
"cell_type": "markdown",
"id": "e9f9be63-1543-4808-872b-7a8e3ad6ea45",
"metadata": {},
"source": [
"# Measure distance to a center line\n",
"A common question is how to determine distances of points to the center of a segmented object. For this we can skeletonize the object, produce a distance map and read out intensities from the distance map at the given points to determine their distance to the skeleton / center line.\n",
"\n",
"See also:\n",
"* https://scikit-image.org/docs/stable/auto_examples/edges/plot_skeleton.html\n",
"* https://examples.itk.org/src/filtering/distancemap/maurerdistancemapofbinary/documentation\n",
"* https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.morphology.distance_transform_edt.html"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "d1d23dfa",
"metadata": {
"lines_to_next_cell": 2
},
"outputs": [],
"source": [
"from skimage.io import imread\n",
"import napari_segment_blobs_and_things_with_membranes as nsbatwm\n",
"import napari_simpleitk_image_processing as nsitk\n",
"import numpy as np\n",
"import stackview\n",
"import pyclesperanto_prototype as cle"
]
},
{
"cell_type": "markdown",
"id": "c7ee349b",
"metadata": {},
"source": [
"## Starting point: a binary image\n",
"We start using a binary image that looks like an arm."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "435b72bd",
"metadata": {
"lines_to_next_cell": 2
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"
\n",
"
\n",
"\n",
"
\n",
"
\n",
"\n",
"
\n",
"
shape
(100, 100)
\n",
"
dtype
uint16
\n",
"
size
19.5 kB
\n",
"
min
0
max
1
\n",
"
\n",
"\n",
"
\n",
"
\n",
"
"
],
"text/plain": [
"StackViewNDArray([[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=uint16)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"binary_arm = imread(\"../../data/binary_arm.tif\")\n",
"stackview.insight(binary_arm)"
]
},
{
"cell_type": "markdown",
"id": "fbaed36b-f7c5-40a7-bef2-6ddad8747269",
"metadata": {},
"source": [
"Furthermore, we continue with a list of coordinates in X/Y format:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "81cbd0ce-d30e-4a73-b6a6-b2d41f521ffc",
"metadata": {},
"outputs": [],
"source": [
"coordinates_xy = np.asarray([\n",
" [70, 80],\n",
" [70, 70],\n",
" [70, 60]]).T"
]
},
{
"cell_type": "markdown",
"id": "3a8b1fd9-c9b7-4533-814b-bef2de93c8a6",
"metadata": {},
"source": [
"We next produce a label image where the given coordinates are labeled. The first coordinate (index=0 in the list) will be labeled with 1, the second with 2, and so on. Background pixels are 0. \n",
"We use this label image for visualization and further down, we will also use this image to do the measurement."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "95a916e7-21ba-402b-9335-d55e167f39ec",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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9OnTlZWVpUceeURtbW3eeeZJun79ul5++WUVFBQoMzNThYWF2rVrlwYHB70+zNM4cAno5MmT7ktf+pI7cuSIO3/+vKuqqnLTpk1zFy9etB6aiW9+85vu6NGj7m9/+5trb293y5cvd7Nnz3afffaZ12fv3r0uOzvb/epXv3IdHR3umWeecTNnznTRaNRw5HbOnTvn5s6d6x5++GFXVVXltTNPzv3nP/9xc+bMcc8995z761//6rq7u92f/vQn949//MPrwzw5t3v3bjd9+nT32muvue7ubvfLX/7SffnLX3YNDQ1eH+Zp7BIyhB599FG3cePGmLb58+e7HTt2GI0osfT19TlJrqWlxTnn3ODgoAuFQm7v3r1en//+978uEAi4V1991WqYZq5cueKKiopcc3OzKy8v90KIebpp+/btbunSpV94nnm6afny5e773/9+TNuKFSvc2rVrnXPM03hJuMtxAwMDamtrU2VlZUx7ZWWlWltbjUaVWCKRiCTpvvvukyR1d3ert7c3Zs78fr/Ky8tTcs42b96s5cuX6/HHH49pZ55uOn36tEpLS/X0008rNzdXCxcu1JEjR7zzzNNNS5cu1euvv64LFy5Ikt5//32dPXtWTz75pCTmabwk3K9of/rpp7px44aCwWBMezAYVG9vr9GoEodzTlu3btXSpUtVXFwsSd683GnOLl68eM/HaOnkyZN677339M477ww5xzzd9OGHH+rQoUPaunWrfvSjH+ncuXN64YUX5Pf7tW7dOubp/2zfvl2RSETz589XWlqabty4oT179mjVqlWS+PM0XhIuhD7n8/liHjvnhrSloi1btuiDDz7Q2bNnh5xL9Tnr6elRVVWVzpw5o4yMjC/sl+rzNDg4qNLSUtXX10uSFi5cqM7OTh06dEjr1q3z+qX6PJ06dUonTpxQY2OjFixYoPb2dlVXVysvL0/r16/3+qX6PI1Vwl2OmzFjhtLS0oasevr6+ob8iyPVPP/88zp9+rTefPNNzZo1y2sPhUKSlPJz1tbWpr6+PpWUlCg9PV3p6elqaWnRK6+8ovT0dG8uUn2eZs6cqQcffDCm7YEHHtClS5ck8efpcy+99JJ27NihlStX6qGHHtKzzz6rF198UeFwWBLzNF4SLoSmTp2qkpISNTc3x7Q3NzerrKzMaFS2nHPasmWLmpqa9MYbb6igoCDmfEFBgUKhUMycDQwMqKWlJaXm7LHHHlNHR4fa29u9o7S0VGvWrFF7e7sKCwuZJ0lLliwZssX/woULmjNnjiT+PH3u6tWrQ+4KmpaW5m3RZp7GieGmiC/0+Rbtn/70p+78+fOuurraTZs2zf3rX/+yHpqJH/7why4QCLi33nrLffLJJ95x9epVr8/evXtdIBBwTU1NrqOjw61atYqtos7F7I5zjnly7ub29fT0dLdnzx7397//3f385z93WVlZ7sSJE14f5sm59evXu/vvv9/bot3U1ORmzJjhtm3b5vVhnsYuIUPIOed+/OMfuzlz5ripU6e6r33ta9525FQk6Y7H0aNHvT6Dg4Nu586dLhQKOb/f75YtW+Y6OjrsBp0gbg8h5umm3/72t664uNj5/X43f/58d/jw4ZjzzJNz0WjUVVVVudmzZ7uMjAxXWFjoamtrXX9/v9eHeRo77icEADCTcDUhAEDqIIQAAGYIIQCAGUIIAGCGEAIAmCGEAABmCCEAgBlCCABghhACAJghhAAAZgghAICZ/wWLxXqB8dKncQAAAABJRU5ErkJggg==",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# draw the coordinates into an image; for visualization purposes\n",
"blank_image = cle.create((binary_arm.shape))\n",
"labeled_spots = coordinate_visualization = cle.pointlist_to_labelled_spots(coordinates_xy, blank_image)\n",
"\n",
"# show the labeled pixels on top of the binary image\n",
"cle.imshow(binary_arm, continue_drawing=True, max_display_intensity=1)\n",
"cle.imshow(labeled_spots, labels=True, alpha=0.6)"
]
},
{
"cell_type": "markdown",
"id": "0ba19ff9-2c9e-4636-8c97-6d23b69c475c",
"metadata": {},
"source": [
"## Pre-processing\n",
"Before we can skeletonize the image, we need to fill the black holes in the white area."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "fdd7664a-96b4-456f-9131-fce331a9fa08",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"