{
"cells": [
{
"cell_type": "markdown",
"id": "7e9d353c-9058-4e23-9b0c-1a545c8e36df",
"metadata": {},
"source": [
"# Shape features\n",
"In this notebook we will compare the impact of small manual modifications to labels/outlines on measured shape features."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "27df8f52-528e-4db7-b80d-477cd242a2e5",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import numpy as np\n",
"import stackview\n",
"import napari_skimage_regionprops as nsr\n",
"from skimage.morphology import disk"
]
},
{
"cell_type": "markdown",
"id": "df03603d-1e11-40d0-aace-62f0e3088812",
"metadata": {},
"source": [
"For demonstration purposes, we use a blank image and a circular region of interest."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "60c1362f-b247-4e14-a805-6034530d1e77",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"image = np.zeros((50,50))"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a8e2ceed-e79e-463f-8884-8cc90bea2d55",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"labels = np.zeros(image.shape, dtype=np.uint32)\n",
"labels[9:40, 9:40] = disk(15)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "40adc48b-3b7a-494c-8670-b789e3a9066e",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"\n",
"\n",
"shape | (50, 50) | \n",
"dtype | uint32 | \n",
"size | 9.8 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=uint32)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stackview.insight(labels)"
]
},
{
"cell_type": "markdown",
"id": "84bb235c-b7b1-4549-b4d0-73c1aee010ab",
"metadata": {},
"source": [
"We can print out the roundness and circularity of this single object like this:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "3249d5ae-044c-403f-b8b9-828aace59207",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"roundness: 0.9996522134693254\n",
"circularity: 0.9106696648110818\n"
]
}
],
"source": [
"stats = nsr.regionprops_table(image, labels, shape=True)\n",
"\n",
"print(\"roundness: \", stats['roundness'][0])\n",
"print(\"circularity: \", stats['circularity'][0])"
]
},
{
"cell_type": "markdown",
"id": "7a32cbc1-4c8b-4013-b74a-ded70d68f325",
"metadata": {},
"source": [
"## Manual modification\n",
"When executing the next cell, a small user-interface will open that allows you to modify the object. Change the Eraser radius to 1 and hold the ALT-Key while clicking to remove individual pixels from the object."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "c5be6c19-8da0-426c-a048-2da97e7242d6",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "117d368bbddd478687e70b9739fb66b9",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(HBox(children=(HBox(children=(VBox(children=(ImageWidget(height=200, width=200),)),)), VBox(chiā¦"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stackview.annotate(image, labels, zoom_factor=4)"
]
},
{
"cell_type": "markdown",
"id": "107a8041-b48b-4260-bc83-b8807068e53b",
"metadata": {},
"source": [
"When you are done modifying the object, continue executing the next code cells."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "fc827137-5054-4207-a4f4-8d55428a795a",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" | \n",
"\n",
"\n",
"\n",
"shape | (50, 50) | \n",
"dtype | uint32 | \n",
"size | 9.8 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=uint32)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stackview.insight(labels)"
]
},
{
"cell_type": "markdown",
"id": "f1a66e2f-8670-40fa-8588-b0557b144e62",
"metadata": {},
"source": [
"As you can see, small modifications to the outline can have huge impact on individual metrics."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "3c86f14e-fe65-482c-90c3-3a4118cb61a4",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"roundness: 0.8564505192042108\n",
"circularity: 0.13777164107308135\n"
]
}
],
"source": [
"stats = nsr.regionprops_table(image, labels, shape=True)\n",
"\n",
"print(\"roundness: \", stats['roundness'][0])\n",
"print(\"circularity: \", stats['circularity'][0])"
]
},
{
"cell_type": "markdown",
"id": "734e08bb-ba69-4ae0-a4ce-665ad7ecab7a",
"metadata": {},
"source": [
"## Exercise\n",
"Modify the code above to also measure aspect ratio and solidity."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6d88d227-4999-49f9-8b82-e08afe6002c0",
"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.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}