Skip to content

Commit d32a01a

Browse files
committed
General clarifications, simplifications and figure corrections. Using imshow from matplotlib instead of skimage (deprecated). Setting default colormap.
1 parent ef64c2d commit d32a01a

13 files changed

Lines changed: 307 additions & 224 deletions

episodes/01-opening-and-checking-an-image.md

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,18 @@ Python has loaded and stored the image as a Numpy `array` object of numbers, and
5151
to it, which is why we get a matrix of numbers printed to the screen.
5252

5353
If we want to see what the image looks like, we need tell Python to display it
54-
as an image. We can do this with the `imshow` function from skimage, which can
55-
be imported and called in a similar way to `imread`:
54+
as an image. We can do this with the `imshow` function from matplotlib, which you
55+
may already be familiar with as a library for drawing plots and graphs, but it can
56+
also display images.
5657

5758
```python
58-
from skimage.io import imshow
59-
imshow(image)
59+
import matplotlib.pyplot as plt
60+
61+
plt.set_cmap('gray') # by default, single-channel images will now be displayed in greyscale
62+
plt.imshow(image)
6063
```
6164

62-
You should see the image displayed below the current cell:
65+
You should now see the image displayed below the current cell:
6366

6467
![](fig/1_1_imshow.jpg){alt='Displaying an image with imshow'}
6568

@@ -79,7 +82,7 @@ are the X and Y axes. The third axis in most cases will represent a number of ch
7982
We can select a single channel by **indexing** the array:
8083

8184
```python
82-
imshow(image[:, :, 2])
85+
plt.imshow(image[:, :, 2])
8386
```
8487

8588
Here, we select the entire X and Y axes using `:` with no numbers around them, and
@@ -121,7 +124,7 @@ Next we can use `.T` to return a **transposed** version of the image. Running
121124

122125
```python
123126
channel = image[:, :, 1]
124-
imshow(channel.T)
127+
plt.imshow(channel.T)
125128
```
126129

127130
![](fig/1_2_transpose.jpg){alt='Transposed image'}
@@ -174,25 +177,22 @@ Running `image.nbytes` shows that it takes up 786432 bytes, or ~786 kilobytes, o
174177
## Displaying one channel at a time
175178

176179
We've seen from exercise 1 that we can view single channels by indexing the array. We can also show all
177-
channels together using matplotlib. You may already be familiar with matplotlib as a library for drawing
178-
plots and graphs, but it can also display images.
179-
180-
We can diaply a group of images together using a matplotlib figure:
180+
channels together using a matplotlib figure:
181181

182182
```python
183-
import matplotlib
184-
matplotlib.pyplot.figure(figsize=(12, 6)) # figure size, in inches
183+
import matplotlib.pyplot as plt
184+
plt.figure(figsize=(12, 6)) # figure size, in inches
185185
nchannels = 3
186186

187187
for i in range(nchannels):
188188
# Use subplot() to create a multi-image figure with 1 row and 3 columns. We need to increment i by 1
189189
# because range() counts from 0 but subplot() assumes you're counting from 1.
190-
matplotlib.pyplot.subplot(1, nchannels, i+1)
191-
matplotlib.pyplot.imshow(image[:, :, i])
192-
matplotlib.pyplot.title('Channel %s' % i) # add a plot title
193-
matplotlib.pyplot.axis(False) # we just want to show the image, so turn off the axis labels
190+
plt.subplot(1, nchannels, i+1)
191+
plt.imshow(image[:, :, i])
192+
plt.title('Channel %s' % i) # add a plot title
193+
plt.axis(False) # we just want to show the image, so turn off the axis labels
194194

195-
matplotlib.pyplot.show()
195+
plt.show()
196196
```
197197

198198
![](fig/1_4_all_channels.jpg){alt='All image channels'}
@@ -204,7 +204,7 @@ Another useful metric in image analysis is an image's histogram. This can be plo
204204
the image and passing it to matplotlib:
205205

206206
```python
207-
matplotlib.pyplot.hist(image[:, :, 0].flatten(), bins=256)
207+
plt.hist(image[:, :, 0].flatten(), bins=256)
208208
```
209209

210210
First, we need to select a single channel - since different channels may represent different cell organelles
@@ -226,26 +226,26 @@ Starting with displaying a single histogram for one channel:
226226
```python
227227
channel_idx = 0
228228
channel = image[:, :, channel_idx]
229-
matplotlib.pyplot.hist(channel.flatten(), bins=255)
230-
matplotlib.pyplot.title('Channel %s' % channel_idx)
231-
matplotlib.pyplot.show()
229+
plt.hist(channel.flatten(), bins=255)
230+
plt.title('Channel %s' % channel_idx)
231+
plt.show()
232232
```
233233

234234
We could call this three times, each with a different value for `channel_idx`, or we can use
235235
a **for loop**:
236236

237237
```python
238-
matplotlib.pyplot.figure(figsize=(12, 6)) # figure size, in inches
238+
plt.figure(figsize=(12, 6)) # figure size, in inches
239239
nchannels = image.shape[-1]
240240

241241
for i in range(nchannels):
242242
channel = image[:, :, i]
243243

244-
matplotlib.pyplot.subplot(1, nchannels, i+1)
245-
matplotlib.pyplot.hist(channel.flatten(), bins=255)
246-
matplotlib.pyplot.title('Channel %s' % i) # add a plot title
244+
plt.subplot(1, nchannels, i+1)
245+
plt.hist(channel.flatten(), bins=255)
246+
plt.title('Channel %s' % i) # add a plot title
247247

248-
matplotlib.pyplot.show()
248+
plt.show()
249249
```
250250
![](fig/1_5_histograms.jpg){alt='All image channels'}
251251

@@ -314,7 +314,7 @@ the X and Y axes, while the second number looks like a number of colour channels
314314
looks like either a time series or a Z axis. We can show a single frame with:
315315

316316
```python
317-
imshow(image[0, 0, :, :])
317+
plt.imshow(image[0, 0, :, :])
318318
```
319319

320320
![](fig/1_6_nd2_image_frame.jpg){alt='ND2 image'}
@@ -337,14 +337,15 @@ The `imshow()` function can take extra arguments in addition to the image to dis
337337
of these is called `cmap`, which can apply alternate lookup tables (a.k.a. colour maps):
338338

339339
```python
340-
imshow(image[0, 0, :, :], cmap='gray')
340+
plt.imshow(image[0, 0, :, :], cmap='viridis')
341341
```
342342

343343
Skimage uses lookup tables from the plotting library matplotlib. A list of available tables
344344
can be obtained with:
345345

346346
```python
347-
print(sorted(matplotlib.colormaps))
347+
from matplotlib import colormaps
348+
print(sorted(colormaps))
348349
```
349350

350351
::::::::::::::::::::::::::::::::::::: challenge
@@ -361,16 +362,16 @@ is one possible solution:
361362
```python
362363
# you'll need to run this again if you overwrote your `image` variable
363364
image = imread('data/FluorescentCells_3channel.tif')
364-
matplotlib.pyplot.figure(figsize=(12, 6))
365+
plt.figure(figsize=(12, 6))
365366

366-
matplotlib.pyplot.subplot(1, 3, 1)
367-
imshow(image[:, :, 0], cmap='Blues')
367+
plt.subplot(1, 3, 1)
368+
plt.imshow(image[:, :, 0], cmap='Blues')
368369

369-
matplotlib.pyplot.subplot(1, 3, 2)
370-
imshow(image[:, :, 1], cmap='Oranges')
370+
plt.subplot(1, 3, 2)
371+
plt.imshow(image[:, :, 1], cmap='Oranges')
371372

372-
matplotlib.pyplot.subplot(1, 3, 3)
373-
imshow(image[:, :, 2], cmap='YlOrBr')
373+
plt.subplot(1, 3, 3)
374+
plt.imshow(image[:, :, 2], cmap='YlOrBr')
374375
```
375376

376377
![](fig/1_7_colormaps.jpg){alt='ND2 image'}

episodes/02-applying-filters.md

Lines changed: 49 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,19 @@ kernel = square(3) # create a 3x3 square kernel
4545
There are other shapes of kernel that can be used, and are documented
4646
[here](https://scikit-image.org/docs/stable/api/skimage.morphology.html).
4747

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).)
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+
51+
```python
52+
from skimage.morphology import footprint_rectangle
53+
kernel = square((3, 3)) # also a 3x3 square kernel
54+
```
5055

5156
::::::::::::::::::::::::::::::::::::: challenge
5257
## Exercise 6: Applying filters
5358

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):
59+
Look at the documentation pages for the mean and Gaussian filters above. Load a frame from the second channel
60+
of the test image [skimage.data.cells3d](https://scikit-image.org/docs/stable/api/skimage.data.html#skimage.data.cells3d):
5661

5762
```python
5863
from skimage.data import cells3d
@@ -75,30 +80,30 @@ How do the different methods compare?
7580
from skimage.data import cells3d
7681
from skimage.filters import gaussian
7782
from skimage.filters.rank import mean
78-
from skimage.morphology import square
83+
from skimage.morphology.footprints import square
7984

8085
image = cells3d()[30, 1, :, :]
81-
matplotlib.pyplot.figure(figsize=(10, 12))
86+
plt.figure(figsize=(10, 12))
8287

83-
matplotlib.pyplot.subplot(3, 2, 1)
84-
imshow(image)
85-
matplotlib.pyplot.title('Original')
88+
plt.subplot(3, 2, 1)
89+
plt.imshow(image)
90+
plt.title('Original')
8691

87-
matplotlib.pyplot.subplot(3, 2, 2)
88-
imshow(mean(image, footprint=square(3)))
89-
matplotlib.pyplot.title('3x3 mean filter')
92+
plt.subplot(3, 2, 2)
93+
plt.imshow(mean(image, footprint=square(3)))
94+
plt.title('3x3 mean filter')
9095

91-
matplotlib.pyplot.subplot(3, 2, 3)
92-
imshow(mean(image, footprint=square(9)))
93-
matplotlib.pyplot.title('9x9 mean filter')
96+
plt.subplot(3, 2, 3)
97+
plt.imshow(mean(image, footprint=square(9)))
98+
plt.title('9x9 mean filter')
9499

95-
matplotlib.pyplot.subplot(3, 2, 4)
96-
imshow(gaussian(image, sigma=1))
97-
matplotlib.pyplot.title('Gaussian blur, σ=1')
100+
plt.subplot(3, 2, 4)
101+
plt.imshow(gaussian(image, sigma=1))
102+
plt.title('Gaussian blur, σ=1')
98103

99-
matplotlib.pyplot.subplot(3, 2, 5)
100-
imshow(gaussian(image, sigma=5))
101-
matplotlib.pyplot.title('Gaussian blur, σ=5')
104+
plt.subplot(3, 2, 5)
105+
plt.imshow(gaussian(image, sigma=5))
106+
plt.title('Gaussian blur, σ=5')
102107
```
103108

104109
![](fig/2_1_filters.jpg){alt='Filters'}
@@ -131,46 +136,34 @@ and display:
131136
- image with a rolling ball of radius 50 applied
132137
- the image with the radius=50 rolling ball subtracted from it
133138

134-
How long does it take to compute?
135-
136139
:::::::::::::::::::::::: solution
137140

138141
Compute time can be found using Python's datetime library:
139142

140143
```python
141-
import datetime
142144
from skimage.data import coins
143145
from skimage.restoration import rolling_ball
144146

145147
image = coins()
146-
matplotlib.pyplot.figure(figsize=(10, 12))
148+
plt.figure(figsize=(10, 8))
147149

148-
t0 = datetime.datetime.now()
149-
matplotlib.pyplot.subplot(2, 2, 1)
150-
imshow(image)
151-
matplotlib.pyplot.title('Original')
150+
plt.subplot(2, 2, 1)
151+
plt.imshow(image, cmap='gray')
152+
plt.title('Original')
152153

153-
t1 = datetime.datetime.now()
154-
matplotlib.pyplot.subplot(2, 2, 2)
154+
plt.subplot(2, 2, 2)
155155
rolling_ball_100 = rolling_ball(image, radius=100)
156-
imshow(rolling_ball_100)
157-
matplotlib.pyplot.title('Rolling ball, r=100')
156+
plt.imshow(rolling_ball_100, cmap='gray')
157+
plt.title('Rolling ball, r=100')
158158

159-
t2 = datetime.datetime.now()
160-
matplotlib.pyplot.subplot(2, 2, 3)
159+
plt.subplot(2, 2, 3)
161160
rolling_ball_50 = rolling_ball(image, radius=50)
162-
imshow(rolling_ball_50)
163-
matplotlib.pyplot.title('Rolling ball, r=50')
164-
165-
t3 = datetime.datetime.now()
166-
matplotlib.pyplot.subplot(2, 2, 4)
167-
imshow(image - rolling_ball_50)
168-
matplotlib.pyplot.title('Original - rolling ball r50')
169-
170-
print('Original image:', t1 - t0)
171-
print('Rolling ball 100:', t2 - t1)
172-
print('Rolling ball 50:', t3 - t2)
173-
print('Total:', t3 - t0)
161+
plt.imshow(rolling_ball_50, cmap='gray')
162+
plt.title('Rolling ball, r=50')
163+
164+
plt.subplot(2, 2, 4)
165+
plt.imshow(image - rolling_ball_50)
166+
plt.title('Original - rolling ball r50')
174167
```
175168

176169
![](fig/2_2_rolling_ball.jpg){alt='Rolling ball'}
@@ -195,7 +188,7 @@ filter. This eliminates the need to manually select two sigma values as with Dif
195188
::::::::::::::::::::::::::::::::::::: challenge
196189
## Exercise 8: Dogs and logs
197190

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)
191+
Load a frame from the second channel of [skimage.data.cells3d()](https://scikit-image.org/docs/stable/api/skimage.data.html#skimage.data.cells3d)
199192
again:
200193

201194
```python
@@ -216,22 +209,22 @@ Display a figure of:
216209

217210
```python
218211
from skimage.data import cells3d
219-
from skimage.filters import difference_of_gaussians, laplace
212+
from skimage.filters import gaussian, difference_of_gaussians, laplace
220213

221214
image = cells3d()[30, 1, :, :]
222-
matplotlib.pyplot.figure(figsize=(10, 12))
215+
plt.figure(figsize=(10, 12))
223216

224-
matplotlib.pyplot.subplot(2, 2, 1)
217+
plt.subplot(2, 2, 1)
225218
imshow(image)
226-
matplotlib.pyplot.title('Original')
219+
plt.title('Original')
227220

228-
matplotlib.pyplot.subplot(2, 2, 2)
221+
plt.subplot(2, 2, 2)
229222
imshow(difference_of_gaussians(image, 1, 2), cmap='gray')
230-
matplotlib.pyplot.title('Difference of Gaussians')
223+
plt.title('Difference of Gaussians')
231224

232-
matplotlib.pyplot.subplot(2, 2, 3)
225+
plt.subplot(2, 2, 3)
233226
imshow(laplace(gaussian(image, sigma=2)), cmap='gray')
234-
matplotlib.pyplot.title('Laplacian of Gaussian')
227+
plt.title('Laplacian of Gaussian')
235228
```
236229

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

0 commit comments

Comments
 (0)