Skip to content

Commit ef64c2d

Browse files
committed
Updates to pisode 2, notes on running carpentries workbench
1 parent 1044f5c commit ef64c2d

4 files changed

Lines changed: 135 additions & 79 deletions

File tree

episodes/02-applying-filters.md

Lines changed: 117 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
2+
23
title: 'Applying Filters'
3-
teaching: 10
4+
teaching: 40
45
exercises: 3
56
---
67

@@ -11,7 +12,6 @@ exercises: 3
1112
::::::::::::::::::::::::::::::::::::: objectives
1213
- Apply mean and Gaussian filters to an image
1314
- Select one of these filtered images to use for processing in subsequent chapters
14-
- Todo: Discuss Difference of Gaussian and Laplacian of Gaussian algorithms
1515
::::::::::::::::::::::::::::::::::::::::::::::::
1616

1717
## Filters
@@ -26,7 +26,7 @@ Here are two to get started:
2626

2727
A mean filter will, for each pixel:
2828

29-
- Create a kernel of pixels around it, in a size/shape of the user's choosing
29+
- Create a **kernel** of pixels around it, in a size/shape of the user's choosing
3030
- Take the mean of all pixels within this kernel
3131
- Assign this new value to the pixel
3232

@@ -35,75 +35,96 @@ The kernel in this case can be considered analogous to a 2-dimensional sliding w
3535
A Gaussian filter is similar to a mean filter, except that pixels near the centre of
3636
the kernel will have a greater effect on the result.
3737

38+
You can create a kernel with skimage:
39+
40+
```python
41+
from skimage.morphology import square
42+
kernel = square(3) # create a 3x3 square kernel
43+
```
44+
45+
There are other shapes of kernel that can be used, and are documented
46+
[here](https://scikit-image.org/docs/stable/api/skimage.morphology.html).
47+
48+
(Note that as of skimage 0.25.0, the `square` function has been deprecated in
49+
favour of a new function, [footprint_rectangle](https://scikit-image.org/docs/stable/api/skimage.morphology.html#skimage.morphology.footprint_rectangle).)
50+
3851
::::::::::::::::::::::::::::::::::::: challenge
39-
## Exercise 7: Applying filters
52+
## Exercise 6: Applying filters
4053

41-
Look at the documentation pages for the mean and Gaussian filters above. Load the last channel
42-
of FluorescentCells_3channel.tif containing the nuclei, and build a figure displaying it in each
43-
of the following forms:
54+
Look at the documentation pages for the mean and Gaussian filters above. Load the second channel
55+
of the 30th frame of the test image [skimage.data.cells3d()](https://scikit-image.org/docs/stable/api/skimage.data.html#skimage.data.cells3d):
56+
57+
```python
58+
from skimage.data import cells3d
59+
60+
image = cells3d()[30, 1, :, :]
61+
```
62+
63+
Build a figure displaying this image in each of the following forms:
4464

4565
- original image
46-
- 5x5 square mean filter applied
47-
- 15x15 square mean filter
48-
- Gaussian filter of sigma = 3
66+
- mean filter using a 3x3 square kernel
67+
- mean filter using a 9x9 square kernel
68+
- Gaussian filter of sigma = 1
4969
- Gaussian filter of sigma = 5
5070

5171
How do the different methods compare?
5272

5373
:::::::::::::::::::::::: solution
5474
```python
55-
import skimage
56-
import matplotlib.pyplot as plt
57-
58-
img = imread('data/FluorescentCells_3channel.tif')[:, :, -1]
59-
60-
plt.figure(figsize=(10, 12))
61-
plt.subplot(3, 2, 1)
62-
plt.imshow(img)
63-
plt.title('Original')
64-
65-
plt.subplot(3, 2, 2)
66-
mean5x5 = skimage.filters.rank.mean(img, skimage.morphology.square(5))
67-
plt.imshow(mean5x5)
68-
plt.title('5x5 mean filter')
69-
70-
plt.subplot(3, 2, 3)
71-
mean15x15 = skimage.filters.rank.mean(img, skimage.morphology.square(15))
72-
plt.imshow(mean15x15)
73-
plt.title('15 x 15 mean filter')
74-
75-
plt.subplot(3, 2, 4)
76-
gauss3 = skimage.filters.gaussian(img, 3)
77-
plt.imshow(gauss3)
78-
plt.title('Gaussian blur, σ=3')
79-
80-
plt.subplot(3, 2, 5)
81-
gauss5 = skimage.filters.gaussian(img, 5)
82-
plt.imshow(gauss5)
83-
plt.title('Gaussian blur, σ=5')
75+
from skimage.data import cells3d
76+
from skimage.filters import gaussian
77+
from skimage.filters.rank import mean
78+
from skimage.morphology import square
79+
80+
image = cells3d()[30, 1, :, :]
81+
matplotlib.pyplot.figure(figsize=(10, 12))
82+
83+
matplotlib.pyplot.subplot(3, 2, 1)
84+
imshow(image)
85+
matplotlib.pyplot.title('Original')
86+
87+
matplotlib.pyplot.subplot(3, 2, 2)
88+
imshow(mean(image, footprint=square(3)))
89+
matplotlib.pyplot.title('3x3 mean filter')
90+
91+
matplotlib.pyplot.subplot(3, 2, 3)
92+
imshow(mean(image, footprint=square(9)))
93+
matplotlib.pyplot.title('9x9 mean filter')
94+
95+
matplotlib.pyplot.subplot(3, 2, 4)
96+
imshow(gaussian(image, sigma=1))
97+
matplotlib.pyplot.title('Gaussian blur, σ=1')
98+
99+
matplotlib.pyplot.subplot(3, 2, 5)
100+
imshow(gaussian(image, sigma=5))
101+
matplotlib.pyplot.title('Gaussian blur, σ=5')
84102
```
85103

86104
![](fig/2_1_filters.jpg){alt='Filters'}
87105

88-
Larger mean kernels and sigma values will result in a greater smoothing
89-
effect and a more blurred image.
106+
Larger kernels and sigma values will result in a greater smoothing
107+
effect and a more blurred image - as you can see, it is possible to
108+
over-blur the image.
90109
:::::::::::::::::::::::::::::::::
91110
:::::::::::::::::::::::::::::::::::::::::::::::
92111

93112
## Removing the background
94113

95-
Sometimes when we're trying to isolate the foreground from the background, the two
96-
are not entirely distinct from each other. In cases like this, a rolling ball
114+
Eventually we're going to want to isolate the foreground from the background. In some
115+
images, this may be difficult especially if the two are not entirely distinct from each
116+
other, or if the background is not a uniform shade. In cases like this, a rolling ball
97117
algorithm can be applied. The rolling ball estimates the background intensity of an
98118
image by using the pixel values to translate the image into a height map, and then
99119
rolling a ball of a given radius across it. Additional information on how it works
100120
can be found [here](https://www.researchgate.net/figure/Schematic-diagram-of-background-subtraction-by-the-rolling-ball-method-the-histogram_fig3_319985119).
101121

102122
::::::::::::::::::::::::::::::::::::: challenge
103-
## Exercise 8: Rolling ball background intensity
123+
## Exercise 7: Rolling ball background intensity
104124

105125
Look at the [scikit-image documentation](https://scikit-image.org/docs/stable/auto_examples/segmentation/plot_rolling_ball.html)
106-
on the rolling ball filter. Load the example image `skimage.data.coins` and display:
126+
on the rolling ball filter. Load the example image [skimage.data.coins](https://scikit-image.org/docs/stable/api/skimage.data.html#skimage.data.coins)
127+
and display:
107128

108129
- the original image
109130
- image with a rolling ball of radius 100 applied
@@ -118,36 +139,36 @@ Compute time can be found using Python's datetime library:
118139

119140
```python
120141
import datetime
121-
import skimage
122-
import matplotlib.pyplot as plt
142+
from skimage.data import coins
143+
from skimage.restoration import rolling_ball
144+
145+
image = coins()
146+
matplotlib.pyplot.figure(figsize=(10, 12))
123147

124-
img = skimage.data.coins()
125148
t0 = datetime.datetime.now()
149+
matplotlib.pyplot.subplot(2, 2, 1)
150+
imshow(image)
151+
matplotlib.pyplot.title('Original')
126152

127-
plt.subplot(2, 2, 1)
128-
plt.imshow(img)
129153
t1 = datetime.datetime.now()
130-
plt.title('Original')
154+
matplotlib.pyplot.subplot(2, 2, 2)
155+
rolling_ball_100 = rolling_ball(image, radius=100)
156+
imshow(rolling_ball_100)
157+
matplotlib.pyplot.title('Rolling ball, r=100')
131158

132-
plt.subplot(2, 2, 2)
133-
rolling_ball_100 = skimage.restoration.rolling_ball(img, radius=100)
134-
plt.imshow(rolling_ball_100)
135159
t2 = datetime.datetime.now()
136-
plt.title('Rolling ball, r=100')
160+
matplotlib.pyplot.subplot(2, 2, 3)
161+
rolling_ball_50 = rolling_ball(image, radius=50)
162+
imshow(rolling_ball_50)
163+
matplotlib.pyplot.title('Rolling ball, r=50')
137164

138-
plt.subplot(2, 2, 3)
139-
rolling_ball_50 = skimage.restoration.rolling_ball(img, radius=50)
140-
plt.imshow(rolling_ball_50)
141165
t3 = datetime.datetime.now()
142-
plt.title('Rolling ball, r=50')
143-
144-
plt.subplot(2, 2, 4)
145-
plt.imshow(img - rolling_ball_50)
146-
plt.title('Original - rolling ball r50')
166+
matplotlib.pyplot.subplot(2, 2, 4)
167+
imshow(image - rolling_ball_50)
168+
matplotlib.pyplot.title('Original - rolling ball r50')
147169

148-
plt.show()
149170
print('Original image:', t1 - t0)
150-
print('Rolling ball 100: ', t2 - t1)
171+
print('Rolling ball 100:', t2 - t1)
151172
print('Rolling ball 50:', t3 - t2)
152173
print('Total:', t3 - t0)
153174
```
@@ -164,44 +185,62 @@ the Gaussian filter.
164185

165186
In a [Difference of Gaussian](https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.difference_of_gaussians),
166187
two Gaussian filters are taken of the image, each with a different sigma value.
167-
The larger filter is then subtracted from the first to give an image where image
188+
The larger filter is then subtracted from the first to give an image where
168189
features are effectively highlighted by an area of high contrast.
169190

170191
In a Laplacian of Gaussian, a Gaussian-filtered image is supplied to a
171192
[Laplace](https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.laplace)
172193
filter. This eliminates the need to manually select two sigma values as with Difference of Gaussian.
173194

174195
::::::::::::::::::::::::::::::::::::: challenge
175-
## Exercise 9: Dogs and logs
196+
## Exercise 8: Dogs and logs
176197

177-
Load the image 'Ersi_organoid_WT2.nd2' and select the end channel of the 16th
178-
frame, i.e. `img[15, 2, :, :]`. Display a figure of:
198+
Load the second channel of the 30th frame of [skimage.data.cells3d()](https://scikit-image.org/docs/stable/api/skimage.data.html#skimage.data.cells3d)
199+
again:
200+
201+
```python
202+
from skimage.data import cells3d
203+
204+
image = cells3d()[30, 1, :, :]
205+
```
206+
207+
Display a figure of:
179208

180209
- The original image
181210
- Image with a Difference of Gaussians applied with sigma values 2 and 4
182211
- Image with a Laplacian of Gaussians applied. Note that the Laplace filter linked
183-
above does not perform the Gaussian filter for you.
212+
above does not perform the Gaussian filter for you, so you will need to pass the
213+
image through `gaussian()` first.
184214

185215
:::::::::::::::::::::::: solution
186216

187217
```python
188-
plt.subplot(1, 3, 1)
189-
imshow(img[15, 2, :, :])
218+
from skimage.data import cells3d
219+
from skimage.filters import difference_of_gaussians, laplace
220+
221+
image = cells3d()[30, 1, :, :]
222+
matplotlib.pyplot.figure(figsize=(10, 12))
223+
224+
matplotlib.pyplot.subplot(2, 2, 1)
225+
imshow(image)
226+
matplotlib.pyplot.title('Original')
190227

191-
plt.subplot(1, 3, 2)
192-
imshow(skimage.filters.difference_of_gaussians(img[15, 2, :, :], 2, 4))
228+
matplotlib.pyplot.subplot(2, 2, 2)
229+
imshow(difference_of_gaussians(image, 1, 2), cmap='gray')
230+
matplotlib.pyplot.title('Difference of Gaussians')
193231

194-
plt.subplot(1, 3, 3)
195-
imshow(skimage.filters.laplace(img[15, 2, :, :]))
232+
matplotlib.pyplot.subplot(2, 2, 3)
233+
imshow(laplace(gaussian(image, sigma=2)), cmap='gray')
234+
matplotlib.pyplot.title('Laplacian of Gaussian')
196235
```
197236

198237
![](fig/2_3_dogs_and_logs.jpg){alt='Dogs and logs'}
199238

200239
:::::::::::::::::::::::::::::::::
201240

202-
## Exercise 10: Choosing a filter
241+
## Exercise 9: Choosing a filter
203242

204-
Look at the images you produced in exercises 7 and 9, and select one to use in
243+
Look at the images you produced in exercises 6 and 8, and select one to use in
205244
subsequent chapters for thresholding and segmentation!
206245
:::::::::::::::::::::::::::::::::::::::::::::::
207246

episodes/fig/2_1_filters.jpg

-16 KB
Loading

episodes/fig/2_3_dogs_and_logs.jpg

-4.84 KB
Loading

instructors/instructor-notes.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,21 @@
22
title: Instructor Notes
33
---
44

5-
This is a placeholder file. Please add content here.
5+
# Building the course
6+
7+
Set up R:
8+
9+
conda create -p path/to/conda -c conda-forge r-base pandoc
10+
11+
Install sandpaper as per the [docs](https://carpentries.github.io/sandpaper-docs):
12+
13+
```r
14+
install.packages(c('sandpaper', 'varnish', 'pegboard'), c("https://carpentries.r-universe.dev/", getOption("repos")))
15+
```
16+
17+
To build and serve interactively:
18+
19+
```r
20+
library('sandpaper')
21+
sandpaper::serve()
22+
```

0 commit comments

Comments
 (0)