Skip to content

Commit ec1da21

Browse files
authored
Merge pull request #99 from stellaprins/sp/otsu
Change shapes image
2 parents 4a36c66 + 3e9a7cc commit ec1da21

9 files changed

+18
-30
lines changed
-12.3 KB
Binary file not shown.
-23.2 KB
Binary file not shown.

episodes/fig/otsu-shapes.png

-23.6 KB
Binary file not shown.

episodes/fig/sauvola-shapes.png

-33.9 KB
Binary file not shown.

episodes/fig/shapes-histogram.png

5.9 KB
Loading

episodes/fig/shapes-thresholds.png

283 KB
Loading

episodes/fig/shapes.png

32.2 KB
Loading

episodes/fig/yen-shapes.png

-24.6 KB
Binary file not shown.

episodes/filters-and-thresholding.md

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -187,19 +187,20 @@ from skimage.util import random_noise, img_as_ubyte
187187
from packaging import version
188188

189189
image = np.full((100, 100), 10, dtype="uint8")
190-
image[10:50, 20:80] = 80
190+
image[10:50, 20:80] = 200
191191
image[disk((75, 75), 15)] = 140
192192
rr, cc = polygon([90, 60, 90], [10, 30, 50])
193-
image[rr, cc] = 200
193+
image[rr, cc] = 80
194194
if version.parse(skimage.__version__) < version.parse("0.21"):
195195
image = img_as_ubyte(random_noise(image, var=0.0005, seed=6))
196196
else:
197197
image = img_as_ubyte(random_noise(image, var=0.0005, rng=6))
198198
viewer.add_image(image)
199199
```
200200

201-
![](fig/manual-thresholding-exercise-shapes.png){alt="Test image containing a
202-
rectangle, circle and triangle"}
201+
![](fig/shapes.png){alt="Test image containing a
202+
rectangle, circle and triangle" width="50%"}
203+
203204

204205
Create a mask for each shape by choosing thresholds based on the image's
205206
histogram.
@@ -228,30 +229,30 @@ viewer.add_labels(mask)
228229
First, we show a histogram for the image by selecting the 'image' layer, then:
229230
`Plugins > napari Matplotlib > Histogram`
230231

231-
![](fig/manual-thresholding-exercise-histogram.png){alt="Histogram of the
232+
![](fig/shapes-histogram.png){alt="Histogram of the
232233
shape image"}
233234

234235
By moving the left contrast limits node we can figure out what each peak
235236
represents. You should see that the peaks from left to right are:
236237

237238
- background
238-
- rectangle
239-
- circle
240239
- triangle
240+
- circle
241+
- rectangle
241242

242243
Then we set thresholds for each (as below). Note that you may not have exactly
243244
the same threshold values as we use here! There are many different values that
244245
can give good results, as long as they fall in the gaps between the peaks in the
245246
image histogram.
246247

247248
```python
248-
rectangle = (image > 53) & (image < 110)
249+
rectangle = image > 171
249250
viewer.add_labels(rectangle)
250251

251252
circle = (image > 118) & (image < 166)
252253
viewer.add_labels(circle)
253254

254-
triangle = image > 171
255+
triangle = (image > 53) & (image < 110)
255256
viewer.add_labels(triangle)
256257
```
257258

@@ -676,7 +677,7 @@ spread of pixel values in both the background and your class of interest. In
676677
effect, it's trying to find two peaks in the image histogram and place a
677678
threshold in between them.
678679

679-
This means it's only suitable for images that show two clear peaks in their
680+
This means it's most suitable for images that show two clear peaks in their
680681
histogram (also known as a 'bimodal' histogram). Other images may require
681682
different automated thresholding methods to produce a good result.
682683

@@ -688,8 +689,7 @@ For this exercise, we'll use the same example image as the [manual thresholding
688689
exercise](#manual-thresholds). If you don't have that image open, run the top
689690
code block in that exercise to open the image:
690691

691-
![](fig/manual-thresholding-exercise-shapes.png){alt="Test image containing a
692-
rectangle, circle and triangle"}
692+
![](fig/shapes.png){alt="Test image containing a rectangle, circle and triangle" width="50%"}
693693

694694
Try some of the other automatic thresholding options provided by the
695695
`napari-skimage` plugin. Set the 'method' to different options in
@@ -713,26 +713,14 @@ row of the layer controls.
713713

714714
## Solution
715715

716-
Otsu thresholding chooses a threshold that separates the background
717-
from the three shapes:
718-
719-
![](fig/otsu-shapes.png){alt="Mask of shapes (brown) overlaid on shapes image -
720-
made with Otsu thresholding"}
721-
722-
Li and mean thresholding gives a very similar result.
723-
724-
Yen gives a different result - isolating the triangle and circle from the rest
725-
of the image. Some of the pixels in the rectangle are also labelled, but only
726-
in patchy areas:
727-
728-
![](fig/yen-shapes.png){alt="Mask of shapes (brown) overlaid on shapes image -
729-
made with Yen thresholding"}
716+
![](fig/shapes-thresholds.png){alt="Masks via automated thresholding"}
730717

731-
Finally, Sauvola gives a completely different result, including a large number
732-
of pixels from the background:
718+
- **Otsu**: The mask does not include the low‑intensity triangle.
719+
- **Mean**: Generally good, but on close inspection a few darker triangle pixels are still missed.
720+
- **Li**: This looks great! The mask includes all pixels of the three shapes, while excluding the background.
721+
- **Yen**: Includes the shapes but also includes some background.
722+
- **Sauvola**: A substantial amount of background is included here.
733723

734-
![](fig/sauvola-shapes.png){alt="Mask of shapes (brown) overlaid on shapes
735-
image - made with Sauvola thresholding" width="60%"}
736724

737725
The important point is that different automatic thresholding methods will work
738726
well for different kinds of images, and depending on which part of an image you

0 commit comments

Comments
 (0)