{ "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", "\n", "\n", "\n", "\n", "\n", "\n", "
shape(50, 50)
dtypeuint32
size9.8 kB
min0
max1
\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", "\n", "\n", "\n", "\n", "\n", "\n", "
shape(50, 50)
dtypeuint32
size9.8 kB
min0
max1
\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 }