Skip to content

Commit b57c27e

Browse files
committed
feature: Added a second image_segmenter class and interactive functions to display segmenter data
Added a image_segmenter_overlayed class which reads a secondary image thats overlayed over the primary. This is useful for medical data for example PET where one has an anatomical reference image and then a heatmap overlayed and wants to segment based on both. Also added some functions to go along with it as well as a example notebook. Also had some issues with commiting, these are describes in an issue here: mpl-extensions#265. This changed the pre-commit-config.
1 parent 66a63c5 commit b57c27e

9 files changed

+585
-14
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,7 @@ _version.py
139139

140140
# mpl testing
141141
result_images/
142+
143+
144+
# Pycharm paths
145+
.idea/

.pre-commit-config.yaml

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@ ci:
22
autoupdate_schedule: "quarterly"
33
repos:
44
- repo: https://github.com/pre-commit/pre-commit-hooks
5-
rev: v4.3.0
5+
rev: v4.4.0
66
hooks:
77
- id: check-docstring-first
88
- id: end-of-file-fixer
99
- id: trailing-whitespace
1010

1111
- repo: https://github.com/psf/black
12-
rev: 22.8.0
12+
rev: 23.1.0
1313
hooks:
1414
- id: black
1515

1616
- repo: https://github.com/pycqa/isort
17-
rev: 5.10.1
17+
rev: 5.12.0
1818
hooks:
1919
- id: isort
2020

2121
- repo: https://github.com/nbQA-dev/nbQA
22-
rev: 1.5.2
22+
rev: 1.6.3
2323
hooks:
2424
- id: nbqa-black
2525
- id: nbqa-isort
@@ -30,18 +30,18 @@ repos:
3030
- id: nbstripout
3131

3232
- repo: https://github.com/pre-commit/mirrors-prettier
33-
rev: v3.0.0-alpha.0
33+
rev: v3.0.0-alpha.6
3434
hooks:
3535
- id: prettier
3636

3737
- repo: https://github.com/PyCQA/flake8
38-
rev: 5.0.4
38+
rev: 6.0.0
3939
hooks:
4040
- id: flake8
41-
additional_dependencies: [flake8-typing-imports==1.7.0]
41+
additional_dependencies: [flake8-typing-imports==1.12.0]
4242

4343
- repo: https://github.com/PyCQA/autoflake
44-
rev: v1.6.1
44+
rev: v2.0.1
4545
hooks:
4646
- id: autoflake
4747
args:

docs/examples/custom-callbacks.ipynb

+1
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
"\n",
158158
"# attach a custom callback\n",
159159
"\n",
160+
"\n",
160161
"# if running from a script you can just delete the widgets.Output and associated code\n",
161162
"def my_callback(tau, beta):\n",
162163
" if tau < 7.5:\n",

docs/examples/devlop/devlop-controller.ipynb

-2
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@
310310
" )\n",
311311
"\n",
312312
" def update(params, indices):\n",
313-
"\n",
314313
" # update plot\n",
315314
" for i, f in enumerate(funcs):\n",
316315
" if x is not None and not indexed_x:\n",
@@ -379,7 +378,6 @@
379378
"\n",
380379
" lines = []\n",
381380
" for i, f in enumerate(funcs):\n",
382-
"\n",
383381
" if x is not None and not indexed_x:\n",
384382
" lines.append(ax.plot(x, f(x, **params), **plot_kwargs[i])[0])\n",
385383
" elif indexed_x:\n",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Image Segmentation of overlayed images and multi-dimensional images"
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": null,
13+
"metadata": {
14+
"tags": []
15+
},
16+
"outputs": [],
17+
"source": [
18+
"%matplotlib widget\n",
19+
"\n",
20+
"import matplotlib.pyplot as plt\n",
21+
"import numpy as np\n",
22+
"\n",
23+
"%load_ext autoreload\n",
24+
"%autoreload 2\n",
25+
"import mpl_interactions as mpl"
26+
]
27+
},
28+
{
29+
"cell_type": "code",
30+
"execution_count": null,
31+
"metadata": {
32+
"tags": []
33+
},
34+
"outputs": [],
35+
"source": [
36+
"# load a primary sample image\n",
37+
"import urllib\n",
38+
"\n",
39+
"import PIL\n",
40+
"\n",
41+
"url = \"https://github.com/matplotlib/matplotlib/raw/v3.3.0/lib/matplotlib/mpl-data/sample_data/ada.png\"\n",
42+
"\n",
43+
"\n",
44+
"image = np.sum(np.array(PIL.Image.open(urllib.request.urlopen(url))), axis=2) / 255\n",
45+
"# simulating multiple slices along the 2 dimension\n",
46+
"image_stack = np.array([image] * 3).transpose((1, 2, 0))\n",
47+
"\n",
48+
"# secondary image\n",
49+
"url_2 = \"https://github.com/matplotlib/matplotlib/raw/v3.3.0/lib/matplotlib/mpl-data/sample_data/Minduka_Present_Blue_Pack.png\"\n",
50+
"secondary_image = np.sum(np.array(PIL.Image.open(urllib.request.urlopen(url_2))), axis=2) / 255\n",
51+
"# padding secondard to be same size as primary for illustration\n",
52+
"secondary_image_padded = np.pad(\n",
53+
" secondary_image,\n",
54+
" [\n",
55+
" (170, 505),\n",
56+
" (150, 234),\n",
57+
" ],\n",
58+
" mode=\"constant\",\n",
59+
" constant_values=(0, 0),\n",
60+
")\n",
61+
"# simulating multiple slices along the 2 dimension\n",
62+
"secondary_image_stack = np.array([secondary_image_padded] * 3).transpose(1, 2, 0)"
63+
]
64+
},
65+
{
66+
"cell_type": "code",
67+
"execution_count": null,
68+
"metadata": {},
69+
"outputs": [],
70+
"source": [
71+
"fig, ax = plt.subplots(1, 3, tight_layout=True)\n",
72+
"ax[0].imshow(image, cmap=\"gray\")\n",
73+
"ax[1].imshow(secondary_image, cmap=\"magma\")\n",
74+
"ax[2].imshow(image, cmap=\"gray\")\n",
75+
"ax[2].imshow(secondary_image_padded, cmap=\"magma\", alpha=0.6)\n",
76+
"ax[0].set_title(\"Primary image\")\n",
77+
"ax[1].set_title(\"Secondary image\")\n",
78+
"ax[2].set_title(\"Overlayed\")"
79+
]
80+
},
81+
{
82+
"cell_type": "markdown",
83+
"metadata": {},
84+
"source": [
85+
"# Now segment the secondary image over the primary\n",
86+
"1. First create a stack of image_segmenter_overlayed objects"
87+
]
88+
},
89+
{
90+
"cell_type": "code",
91+
"execution_count": null,
92+
"metadata": {},
93+
"outputs": [],
94+
"source": [
95+
"segmenter_stack = mpl.get_segmenter_list(image_stack, secondary_image_stack, n_classes=2)"
96+
]
97+
},
98+
{
99+
"cell_type": "markdown",
100+
"metadata": {},
101+
"source": [
102+
"2. Call draw_masks function to open an interactive window where one can draw the masks on the seperate slices"
103+
]
104+
},
105+
{
106+
"cell_type": "code",
107+
"execution_count": null,
108+
"metadata": {
109+
"tags": []
110+
},
111+
"outputs": [],
112+
"source": [
113+
"mpl.draw_masks(segmenter_list=segmenter_stack)"
114+
]
115+
},
116+
{
117+
"cell_type": "markdown",
118+
"metadata": {},
119+
"source": [
120+
"3. Retrieve mask values from segmenter_list"
121+
]
122+
},
123+
{
124+
"cell_type": "code",
125+
"execution_count": null,
126+
"metadata": {},
127+
"outputs": [],
128+
"source": [
129+
"masks_dict = mpl.get_masks(segmenter_stack, plot_res=True)"
130+
]
131+
},
132+
{
133+
"cell_type": "markdown",
134+
"metadata": {},
135+
"source": [
136+
"4. Retrieve contours of the masks"
137+
]
138+
},
139+
{
140+
"cell_type": "code",
141+
"execution_count": null,
142+
"metadata": {},
143+
"outputs": [],
144+
"source": [
145+
"contours = mpl.get_mask_contours(segmenter_stack)"
146+
]
147+
},
148+
{
149+
"cell_type": "markdown",
150+
"metadata": {},
151+
"source": [
152+
"5. Plot contours on segmented images"
153+
]
154+
},
155+
{
156+
"cell_type": "code",
157+
"execution_count": null,
158+
"metadata": {},
159+
"outputs": [],
160+
"source": []
161+
}
162+
],
163+
"metadata": {
164+
"kernelspec": {
165+
"display_name": "Python 3 (ipykernel)",
166+
"language": "python",
167+
"name": "python3"
168+
},
169+
"language_info": {
170+
"codemirror_mode": {
171+
"name": "ipython",
172+
"version": 3
173+
},
174+
"file_extension": ".py",
175+
"mimetype": "text/x-python",
176+
"name": "python",
177+
"nbconvert_exporter": "python",
178+
"pygments_lexer": "ipython3",
179+
"version": "3.10.9"
180+
}
181+
},
182+
"nbformat": 4,
183+
"nbformat_minor": 4
184+
}

docs/examples/usage.ipynb

+2
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@
452452
")\n",
453453
"\n",
454454
"iplt.title(\"the value of tau is: {tau:.2f}\", controls=controls[\"tau\"])\n",
455+
"\n",
456+
"\n",
455457
"# you can still use plt commands if this is the active figure\n",
456458
"def ylabel(tau):\n",
457459
" return f\"tau/2 is {np.round(tau/2,3)}\"\n",

docs/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ examples/imshow.ipynb
116116
examples/hist.ipynb
117117
examples/scatter-selector.ipynb
118118
examples/image-segmentation.ipynb
119+
examples/image-segmentation-multiple-image.ipynb
119120
examples/zoom-factory.ipynb
120121
examples/heatmap-slicer.ipynb
121122
```

0 commit comments

Comments
 (0)