Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

📚 The CoCalc Library - books, templates and other resources

132971 views
License: OTHER
1
2
3
4
```python
5
%matplotlib inline
6
```
7
8
# Images are numpy arrays
9
10
Images are represented in ``scikit-image`` using standard ``numpy`` arrays. This allows maximum inter-operability with other libraries in the scientific Python ecosystem, such as ``matplotlib`` and ``scipy``.
11
12
Let's see how to build a grayscale image as a 2D array:
13
14
15
16
```python
17
import numpy as np
18
from matplotlib import pyplot as plt
19
20
random_image = np.random.random([500, 500])
21
22
plt.imshow(random_image, cmap='gray', interpolation='nearest');
23
```
24
25
26
![png](0_images_are_arrays_files/0_images_are_arrays_2_0.png)
27
28
29
The same holds for "real-world" images:
30
31
32
33
```python
34
from skimage import data
35
36
coins = data.coins()
37
38
print(type(coins), coins.dtype, coins.shape)
39
plt.imshow(coins, cmap='gray', interpolation='nearest');
40
```
41
42
```output
43
<class 'numpy.ndarray'> uint8 (303, 384)
44
```
45
46
47
![png](0_images_are_arrays_files/0_images_are_arrays_4_1.png)
48
49
50
A color image is a 3D array, where the last dimension has size 3 and represents the red, green, and blue channels:
51
52
53
54
```python
55
cat = data.chelsea()
56
print("Shape:", cat.shape)
57
print("Values min/max:", cat.min(), cat.max())
58
59
plt.imshow(cat, interpolation='nearest');
60
```
61
62
```output
63
Shape: (300, 451, 3)
64
Values min/max: 0 231
65
```
66
67
68
![png](0_images_are_arrays_files/0_images_are_arrays_6_1.png)
69
70
71
These are *just numpy arrays*. Making a red square is easy using just array slicing and manipulation:
72
73
74
75
```python
76
cat[10:110, 10:110, :] = [255, 0, 0] # [red, green, blue]
77
plt.imshow(cat);
78
```
79
80
81
![png](0_images_are_arrays_files/0_images_are_arrays_8_0.png)
82
83
84
Images can also include transparent regions by adding a 4th dimension, called an *alpha layer*.
85
86
## Data types and image values
87
88
In literature, one finds different conventions for representing image values:
89
90
```
91
0 - 255 where 0 is black, 255 is white
92
0 - 1 where 0 is black, 1 is white
93
```
94
95
96
``scikit-image`` supports both conventions--the choice is determined by the
97
data-type of the array.
98
99
E.g., here, I generate two valid images:
100
101
102
103
```python
104
linear0 = np.linspace(0, 1, 2500).reshape((50, 50))
105
linear1 = np.linspace(0, 255, 2500).reshape((50, 50)).astype(np.uint8)
106
107
print("Linear0:", linear0.dtype, linear0.min(), linear0.max())
108
print("Linear1:", linear1.dtype, linear1.min(), linear1.max())
109
110
fig, (ax0, ax1) = plt.subplots(1, 2)
111
ax0.imshow(linear0, cmap='gray')
112
ax1.imshow(linear1, cmap='gray');
113
```
114
115
```output
116
Linear0: float64 0.0 1.0
117
Linear1: uint8 0 255
118
```
119
120
121
![png](0_images_are_arrays_files/0_images_are_arrays_12_1.png)
122
123
124
The library is designed in such a way that any data-type is allowed as input,
125
as long as the range is correct (0-1 for floating point images, 0-255 for unsigned bytes,
126
0-65535 for unsigned 16-bit integers).
127
128
This is achieved through the use of a few utility functions, such as ``img_as_float`` and ``img_as_ubyte``:
129
130
131
132
```python
133
from skimage import img_as_float, img_as_ubyte
134
135
image = data.chelsea()
136
137
image_float = img_as_float(image)
138
image_ubyte = img_as_ubyte(image)
139
140
print("type, min, max:", image_float.dtype, image_float.min(), image_float.max())
141
print("type, min, max:", image_ubyte.dtype, image_ubyte.min(), image_ubyte.max())
142
143
print("231/255 =", 231/255.)
144
```
145
146
```output
147
type, min, max: float64 0.0 0.905882352941
148
type, min, max: uint8 0 231
149
231/255 = 0.9058823529411765
150
```
151
152
Your code would then typically look like this:
153
154
155
156
```python
157
def my_function(any_image):
158
float_image = img_as_float(any_image)
159
# Proceed, knowing image is in [0, 1]
160
```
161
162
We recommend using the floating point representation, given that
163
``scikit-image`` mostly uses that format internally.
164
165
## Displaying images using matplotlib
166
167
Before we get started, a quick note about plotting images---specifically, plotting gray-scale images with Matplotlib. First, let's grab an example image from `scikit-image`.
168
169
170
171
```python
172
from skimage import data
173
174
image = data.camera()
175
```
176
177
Also, we'll want to make sure we have numpy and matplotlib imported.
178
179
180
181
```python
182
import matplotlib.pyplot as plt
183
import numpy as np
184
```
185
186
If we plot a gray-scale image using the old default colormap "jet"
187
(it's been replaced by Viridis in Matplotlib >= 1.5), and a gray-scale
188
colormap, "gray", you can easily see the difference:
189
190
191
192
```python
193
fig, (ax_jet, ax_gray) = plt.subplots(ncols=2, figsize=(10, 5))
194
195
ax_jet.imshow(image, cmap='jet')
196
ax_gray.imshow(image, cmap='gray');
197
```
198
199
200
![png](0_images_are_arrays_files/0_images_are_arrays_22_0.png)
201
202
203
We can get a better idea of the ill effects by zooming into the man's face.
204
205
206
207
```python
208
face = image[80:160, 200:280]
209
fig, (ax_jet, ax_gray) = plt.subplots(ncols=2)
210
ax_jet.imshow(face, cmap='jet')
211
ax_gray.imshow(face, cmap='gray');
212
```
213
214
215
![png](0_images_are_arrays_files/0_images_are_arrays_24_0.png)
216
217
218
Notice how the face looks distorted and splotchy with the "jet" colormap. Also, this colormap distorts the concepts of light and dark, and there are artificial boundaries created by the different color hues. Is that a beauty mark on the man's upper lip? No, it's just an artifact of this ridiculous colormap.
219
220
Here's another example:
221
222
223
224
```python
225
X, Y = np.ogrid[-5:5:0.1, -5:5:0.1]
226
R = np.exp(-(X**2 + Y**2) / 15)
227
228
fig, (ax_jet, ax_gray) = plt.subplots(1, 2)
229
ax_jet.imshow(R, cmap='jet')
230
ax_gray.imshow(R, cmap='gray');
231
```
232
233
234
![png](0_images_are_arrays_files/0_images_are_arrays_26_0.png)
235
236
237
Woah! See all those non-existing contours?
238
239
You can set both the method of interpolation and colormap used
240
explicitly in the ``imshow`` command:
241
242
243
244
```python
245
plt.imshow(R, cmap='gray', interpolation='nearest');
246
```
247
248
249
![png](0_images_are_arrays_files/0_images_are_arrays_28_0.png)
250
251
252
Otherwise, you can add the following setting at the top of any script
253
to change the default colormap:
254
255
256
257
```python
258
plt.rcParams['image.cmap'] = 'gray'
259
```
260
261
Don't worry: color images are unaffected by this change.
262
263
In addition, we'll set the interpolation to 'nearest neighborhood' so
264
that it's easier to distinguish individual pixels in your image (the
265
default is 'bicubic'--see the exploration below).
266
267
268
269
```python
270
plt.rcParams['image.interpolation'] = 'nearest'
271
```
272
273
For reference, let's look at the images above using Matplotlib's new 'viridis' and 'magma' colormaps (requires matplotlib >= 1.5).
274
275
276
277
```python
278
fig, axes = plt.subplots(2, 2, figsize=(10, 10))
279
280
axes[0, 0].imshow(R, cmap='jet')
281
axes[0, 1].imshow(R, cmap='viridis')
282
axes[1, 0].imshow(R, cmap='magma')
283
axes[1, 1].imshow(R, cmap='gray');
284
```
285
286
287
![png](0_images_are_arrays_files/0_images_are_arrays_34_0.png)
288
289
290
### Interactive demo: interpolation and color maps
291
292
If you are viewing this tutorial from inside a Jupyter notebook, the
293
following code will display an interactive widget for exploring
294
different colormaps and types of interpolation.
295
296
297
298
```python
299
from IPython.html.widgets import interact, fixed
300
from matplotlib import cm as colormaps
301
import matplotlib.colors
302
import inspect
303
304
@interact(image=fixed(face),
305
cmap=sorted([c for c in dir(colormaps)
306
if not c.endswith('_r') and
307
isinstance(getattr(colormaps, c),
308
matplotlib.colors.Colormap)],
309
key=lambda x: x.lower()),
310
reverse_cmap=False,
311
interpolation=['nearest', 'bilinear', 'bicubic',
312
'spline16', 'spline36', 'hanning', 'hamming',
313
'hermite', 'kaiser', 'quadric', 'catrom',
314
'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos'])
315
def imshow_params(image, cmap='jet', reverse_cmap=False, interpolation='bicubic'):
316
fig, axes = plt.subplots(1, 5, figsize=(15, 4))
317
318
if reverse_cmap:
319
cmap = cmap + '_r'
320
321
axes[0].imshow(image, cmap='gray', interpolation='nearest')
322
axes[0].set_title('Original')
323
324
axes[1].imshow(image[:5, :5], cmap='gray', interpolation='nearest')
325
axes[1].set_title('Top 5x5 block')
326
axes[1].set_xlabel('No interpolation')
327
328
axes[2].imshow(image, cmap=cmap, interpolation=interpolation)
329
axes[2].set_title('%s colormap' % cmap)
330
axes[2].set_xlabel('%s interpolation' % interpolation)
331
332
axes[3].imshow(image[:5, :5], cmap=cmap, interpolation=interpolation)
333
axes[3].set_title('%s colormap' % cmap)
334
axes[3].set_xlabel('%s interpolation' % interpolation)
335
336
axes[4].imshow(R, cmap=cmap, interpolation=interpolation)
337
axes[4].set_title('%s colormap' % cmap)
338
axes[4].set_xlabel('%s interpolation' % interpolation)
339
340
for ax in axes:
341
ax.set_xticks([])
342
ax.set_yticks([])
343
```
344
345
346
![png](0_images_are_arrays_files/0_images_are_arrays_36_0.png)
347
348
349
## Image I/O
350
351
Mostly, we won't be using input images from the scikit-image example data sets. Those images are typically stored in JPEG or PNG format. Since scikit-image operates on NumPy arrays, *any* image reader library that provides arrays will do. Options include matplotlib, pillow, imageio, imread, etc.
352
353
scikit-image conveniently wraps many of these in the `io` submodule, and will use whatever option is available:
354
355
356
357
```python
358
from skimage import io
359
360
image = io.imread('../../images/balloon.jpg')
361
362
print(type(image))
363
plt.imshow(image);
364
```
365
366
```output
367
<class 'numpy.ndarray'>
368
```
369
370
371
![png](0_images_are_arrays_files/0_images_are_arrays_38_1.png)
372
373
374
We also have the ability to load multiple images, or multi-layer TIFF images:
375
376
377
378
```python
379
ic = io.imread_collection('../../images/*.png')
380
381
print(type(ic), '\n\n', ic)
382
```
383
384
```output
385
<class 'skimage.io.collection.ImageCollection'>
386
387
['../../images/chapel_floor.png', '../../images/clock_motion.png', '../../images/fingers.png', '../../images/snakes.png', '../../images/zebrafish-spinal-cord-color.png', '../../images/zebrafish-spinal-cord.png']
388
```
389
390
391
392
```python
393
f, axes = plt.subplots(nrows=1, ncols=len(ic), figsize=(15, 10))
394
395
for i, image in enumerate(ic):
396
axes[i].imshow(image, cmap='gray')
397
axes[i].axis('off')
398
```
399
400
401
![png](0_images_are_arrays_files/0_images_are_arrays_41_0.png)
402
403
404
## Exercises
405
406
### Draw the letter H
407
408
Define a function that takes as input an RGB image and a pair of coordinates (row, column), and returns the image (optionally a copy) with green letter H overlaid at those coordinates. The coordinates should point to the top-left corner of the H.
409
410
The arms and strut of the H should have a width of 3 pixels, and the H itself should have a height of 24 pixels and width of 20 pixels.
411
412
Start with the following template:
413
414
415
416
```python
417
def draw_H(image, coords, color=(0.8, 0.8, 0.8), in_place=True):
418
out = image.copy()
419
# your code goes here
420
return out
421
```
422
423
Test your function like so:
424
425
426
427
```python
428
cat = data.chelsea()
429
cat_H = draw_H(cat, (50, -50))
430
plt.imshow(cat_H);
431
```
432
433
434
![png](0_images_are_arrays_files/0_images_are_arrays_45_0.png)
435
436
437
### RGB intensity plot
438
439
Plot the intensity of each channel of the image along a given row.
440
Start with the following template:
441
442
```
443
def plot_intensity(image, row):
444
# Fill in the three lines below
445
red_values = ...
446
green_values = ...
447
blue_values = ...
448
449
plt.figure()
450
plt.plot(red_values, 'r')
451
plt.plot(green_values, 'g')
452
plt.plot(blue_values, 'b')
453
454
pass
455
```
456
457
458
Test your function using:
459
460
```
461
plot_intensity(cat, 50)
462
plot_intensity(cat, 100)
463
```
464
465
466