Skip to content

Commit b69e37f

Browse files
Add solutions
1 parent 2c15793 commit b69e37f

5 files changed

Lines changed: 196 additions & 0 deletions

File tree

‎solutions/fish/fish.ipynb‎

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "e123b8e5",
6+
"metadata": {
7+
"editable": true,
8+
"slideshow": {
9+
"slide_type": "slide"
10+
},
11+
"tags": []
12+
},
13+
"source": [
14+
"# Segmenting `fish.tif` using Python\n",
15+
"\n",
16+
"> This proposed solution is inspired from our guide: [Introduction to Python for Image Analysis](https://epfl-center-for-imaging.github.io/python-intro-images/lab/index.html?path=Content.ipynb).\n",
17+
"\n",
18+
"In the cell below, we read the image into Python, apply a few operations to segment the fish using [Scikit-image](https://scikit-image.org) and [Scipy](https://scipy.org/) functions. We then save the mask as a TIFF image."
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": null,
24+
"id": "5cb8d516",
25+
"metadata": {},
26+
"outputs": [],
27+
"source": [
28+
"\n",
29+
"from pathlib import Path\n",
30+
"from scipy.ndimage import binary_fill_holes\n",
31+
"import skimage.io\n",
32+
"from skimage.morphology import remove_small_objects\n",
33+
"from skimage.measure import label\n",
34+
"\n",
35+
"image_path = Path(\".\").resolve().parents[1] / \"public\" / \"Images\" / \"fish.tif\"\n",
36+
"\n",
37+
"image = skimage.io.imread(image_path)\n",
38+
"\n",
39+
"binary_img = image < 200\n",
40+
"binary_img = binary_fill_holes(binary_img)\n",
41+
"binary_img = remove_small_objects(binary_img, min_size=500)\n",
42+
"\n",
43+
"label_img = label(binary_img)\n",
44+
"\n",
45+
"mask_path = Path(\".\").resolve().parents[1] / \"Submissions\" / \"fish\" / \"example_solution.tif\"\n",
46+
"\n",
47+
"skimage.io.imsave(mask_path, label_img)"
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": null,
53+
"id": "05a526ce",
54+
"metadata": {
55+
"trusted": true
56+
},
57+
"outputs": [],
58+
"source": []
59+
}
60+
],
61+
"metadata": {
62+
"kernelspec": {
63+
"display_name": "imaging-server-kit",
64+
"language": "python",
65+
"name": "python3"
66+
},
67+
"language_info": {
68+
"codemirror_mode": {
69+
"name": "ipython",
70+
"version": 3
71+
},
72+
"file_extension": ".py",
73+
"mimetype": "text/x-python",
74+
"name": "python",
75+
"nbconvert_exporter": "python",
76+
"pygments_lexer": "ipython3",
77+
"version": "3.10.18"
78+
}
79+
},
80+
"nbformat": 4,
81+
"nbformat_minor": 5
82+
}

‎solutions/grains/grains.ipynb‎

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "3fd1ff50",
6+
"metadata": {},
7+
"source": [
8+
"# Segmenting `grains.tif` with Ilastik and Python\n",
9+
"\n",
10+
"This proposed solution consists of two steps; first, we separate (approximately) the grain bulks from the grain boundaries using [Ilastik](https://ilastik.org). \n",
11+
"\n",
12+
"<video width=\"320\" height=\"240\" controls>\n",
13+
" <source src=\"./ilastik-recording.mp4\" type=\"video/mp4\">\n",
14+
"</video>\n",
15+
"\n",
16+
"We export the `Simple Segmentation` output from Ilastik as a TIFF image.\n",
17+
"\n",
18+
"Then, we read this segmentation mask into Python, and we apply a few simple operations to label the grains using [Scikit-image](https://scikit-image.org). These steps are described below."
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": null,
24+
"id": "2758b261",
25+
"metadata": {},
26+
"outputs": [],
27+
"source": [
28+
"from pathlib import Path\n",
29+
"import numpy as np\n",
30+
"\n",
31+
"import skimage.io\n",
32+
"from skimage.morphology import label\n",
33+
"from skimage.segmentation import watershed\n",
34+
"from scipy.ndimage import distance_transform_edt"
35+
]
36+
},
37+
{
38+
"cell_type": "code",
39+
"execution_count": null,
40+
"id": "19b01b27",
41+
"metadata": {},
42+
"outputs": [],
43+
"source": [
44+
"# Path to the `Simple Segmentation` output from Ilastik:\n",
45+
"segmentation_file = \"grains_Simple Segmentation.tif\"\n",
46+
"\n",
47+
"# Read the grain boundaries mask from Ilastik\n",
48+
"segmentation = skimage.io.imread(segmentation_file)\n",
49+
"segmentation = segmentation.astype(np.uint8) # Make sure it's an 8-bit array\n",
50+
"\n",
51+
"# Binary mask of the bulk (`background` class):\n",
52+
"bulk = segmentation == 1\n",
53+
"\n",
54+
"# Binary mask of the grain boundaries (`foreground` class)\n",
55+
"boundaries = segmentation == 2\n",
56+
"\n",
57+
"# Label the grain bulks (connected components):\n",
58+
"labelled_bulk = label(bulk)\n",
59+
"\n",
60+
"# Compute an euclidean distance transform in the grain boundary mask:\n",
61+
"distance_img = distance_transform_edt(boundaries)\n",
62+
"\n",
63+
"# Fill the remaining space (the grain boundaries) using a watershed transform:\n",
64+
"grains_labelled = watershed(-distance_img, markers=labelled_bulk)\n",
65+
"\n",
66+
"# Save the labelled image:\n",
67+
"mask_path = Path(\".\").resolve().parents[1] / \"Submissions\" / \"grains\" / \"example_solution.tif\"\n",
68+
"\n",
69+
"skimage.io.imsave(mask_path, grains_labelled)"
70+
]
71+
},
72+
{
73+
"cell_type": "code",
74+
"execution_count": null,
75+
"id": "0c7e363d",
76+
"metadata": {},
77+
"outputs": [],
78+
"source": []
79+
}
80+
],
81+
"metadata": {
82+
"kernelspec": {
83+
"display_name": "imaging-server-kit",
84+
"language": "python",
85+
"name": "python3"
86+
},
87+
"language_info": {
88+
"codemirror_mode": {
89+
"name": "ipython",
90+
"version": 3
91+
},
92+
"file_extension": ".py",
93+
"mimetype": "text/x-python",
94+
"name": "python",
95+
"nbconvert_exporter": "python",
96+
"pygments_lexer": "ipython3",
97+
"version": "3.10.18"
98+
}
99+
},
100+
"nbformat": 4,
101+
"nbformat_minor": 5
102+
}
6.63 KB
Binary file not shown.
5.56 MB
Binary file not shown.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Segmenting `sunflowers.tif` in Fiji
2+
3+
Here is a simple workflow in [Fiji](https://fiji.sc/) to segment the sunflower seeds:
4+
5+
- Open `sunflowers.tif` in Fiji.
6+
- `Image` => `Type` => `8-bit` to convert the image to grayscale.
7+
- `Image` => `Adjust` => `Threshold..` to open the intensity threshold menu.
8+
- Set the automatic threshold to `Otsu` and tick `Dark background`. Then, click `Apply` to binarize the image.
9+
- `Analyze` => `Analyze Particles..` to open the particle analysis menu.
10+
- Under `Size`, select `300-5000` to include only that particle size range.
11+
- Under `Show`, select `Count Masks` to output a labelled array. Then, click `OK`.
12+
- This should produce a labelled segmentation mask of the sunflower seeds! You can save it via `File` > `Save As` => `Tiff`.

0 commit comments

Comments
 (0)