@@ -7,20 +7,16 @@ questions:
7
7
objectives :
8
8
- " Explain why applying a low-pass blurring filter to an image is beneficial."
9
9
- " Apply a Gaussian blur filter to an image using skimage."
10
- - " Explain what often happens if we pass unexpected values to a Python
11
- function."
12
10
keypoints :
13
11
- " Applying a low-pass blurring filter smooths edges and removes noise from
14
12
an image."
15
13
- " Blurring is often used as a first step before we perform
16
- [Thresholding]({{ page.root }}./07-thresholding.md),
17
- [Edge Detection]({{ page.root }}./08-edge-detection), or before we find the
18
- [Contours]({{ page.root }}./09-contours) of an image."
14
+ [Thresholding]({{ page.root }}/07-thresholding) or
15
+ [Edge Detection]({{ page.root }}/../_extras/edge_detection.md)."
19
16
- " The Gaussian blur can be applied to an image with the
20
17
`skimage.filters.gaussian()` function."
21
18
- " Larger sigma values may remove more noise, but they will also remove detail
22
19
from an image."
23
- - " The `float()` function can be used to parse a string into an float."
24
20
---
25
21
26
22
In this episode, we will learn how to use skimage functions to blur images.
@@ -36,9 +32,9 @@ background of the image ends and the object begins.
36
32
37
33
When we blur an image, we make the color transition from one side of an edge in the image to another
38
34
smooth rather than sudden. The effect is to average out rapid changes in pixel intensity. A blur is
39
- a very common operation we need to perform before other tasks such as edge detection. There are
40
- several different blurring functions in the ` skimage.filters ` module, so we will focus on just one
41
- here, the * Gaussian blur* .
35
+ a very common operation we need to perform before other tasks such as
36
+ [ thresholding ] ({{ page.root }}/07-thresholding). There are several different blurring functions
37
+ in the ` skimage.filters ` module, so we will focus on just one here, the * Gaussian blur* .
42
38
43
39
> ## Filters
44
40
>
@@ -194,121 +190,30 @@ order to calculate the color channel values for the blurred image.
194
190

195
191
196
192
skimage has built-in functions to perform blurring for us, so we do not have to
197
- perform all of these mathematical operations ourselves. The following Python
198
- program shows how to use the skimage Gaussian blur function.
193
+ perform all of these mathematical operations ourselves. Let's work through
194
+ an example of blurring an image with the skimage Gaussian blur function.
199
195
196
+ First, we load the image, and display it:
200
197
~~~
201
- """
202
- * Python script to demonstrate Gaussian blur.
203
- *
204
- * usage: python GaussBlur.py <filename > <sigma >
205
- """
206
198
import skimage.io
199
+ import matplotlib.pyplot as plt
207
200
import skimage.filters
208
- import sys
201
+ %matplotlib widget
209
202
210
- # get filename and kernel size from command line
211
- filename = sys.argv[ 1]
212
- sigma = float(sys.argv[ 2] )
213
- ~~~
214
- {: .language-python}
215
-
216
- In this case, the
217
- program takes two command-line parameters. The first is the filename of the
218
- image to filter, and the second is the sigma of the Gaussian.
219
-
220
- In the program, we first import the required libraries, as we
221
- have done before. Then, we read the two command-line arguments. The first, the
222
- filename, should be familiar code by now. For the sigma argument, we have
223
- to convert the second argument from a string, which is how all arguments are
224
- read into the program, into a float, which is what we will use for our
225
- sigma. This is done with the
226
-
227
- `sigma = float(sys.argv[2])`
228
-
229
- line of code. The `float()` function takes a string as its parameter, and returns
230
- the floating point number equivalent.
231
-
232
- > ## What happens if the `float()` parameter does not look like a number? (10 min - optional, not included in timing)
233
- >
234
- > In the program fragment, we are using the `float()` function to *parse* the
235
- > second command-line argument, which comes in to the program as a string,
236
- > and convert it into a floating point number. What happens if the second command-line
237
- > argument does not look like a number? Let us perform an experiment to find
238
- > out.
239
- >
240
- > Write a simple Python program to read one command-line argument, convert the
241
- > argument to a floating point number, and then print out the result. Then, run your program
242
- > with an integer argument, again with a floating point number argument,
243
- > and then one more time with some non-numeric arguments.
244
- > For example, if your program is named `float_arg.py`, you might perform these
245
- > runs:
246
- >
247
- > ~~~
248
- > python float_arg.py 3.14159
249
- > python float_arg.py puppy
250
- > python float_arg.py 13
251
- > ~~~
252
- > {: .language-bash}
253
- >
254
- > What does `float()` do if it receives a string that cannot be parsed into an
255
- > integer?
256
- >
257
- > > ## Solution
258
- > >
259
- > > Here is a simple program to read in one command-line argument, parse it as
260
- > > and integer, and print out the result:
261
- > >
262
- > > ~~~
263
- > > """
264
- > > * Read a command-line argument, parse it as an integer, and
265
- > > * print out the result.
266
- > > *
267
- > > * usage: python float_arg.py <argument>
268
- > > """
269
- > > import sys
270
- > >
271
- > > value = float(sys.argv[1])
272
- > > print("Your command-line argument is:", value)
273
- > > ~~~
274
- > > {: .language-python}
275
- > >
276
- > > Executing this program with the three command-line arguments suggested
277
- > > above produces this output:
278
- > >
279
- > > ~~~
280
- > > Your command-line argument is: 3.14159
281
- > >
282
- > > Traceback (most recent call last):
283
- > > File "float_arg.py", line 9, in <module>
284
- > > value = float(sys.argv[1])
285
- > > ValueError: could not convert string to float: 'puppy'
286
- > >
287
- > > Your command-line argument is: 13.0
288
- > > ~~~
289
- > > {: .output}
290
- > >
291
- > > You can see that if we pass in an invalid value to the `float()` function,
292
- > > the Python interpreter halts the program and prints out an error message,
293
- > > describing what the problem was.
294
- > > Note also that the integer value, 13, passed as an argument was converted to
295
- > > a floating point number and is subsequently displayed as `13.0`.
296
- > {: .solution}
297
- {: .challenge}
298
-
299
- Next, the program reads and displays the original, unblurred image. This should
300
- also be very familiar to you at this point.
203
+ image = skimage.io.imread("data/gaussian-original.png")
301
204
302
- ~~~
303
- # read and display original image
304
- image = skimage.io.imread(fname=filename )
305
- skimage.io.imshow(image )
205
+ # display the image
206
+ fig, ax = plt.subplots()
207
+ plt.imshow(image )
208
+ plt.show( )
306
209
~~~
307
210
{: .language-python}
211
+ 
308
212
309
- Now we apply the average blur:
310
-
213
+ Next, we apply the gaussian blur:
311
214
~~~
215
+ sigma = 3.0
216
+
312
217
# apply Gaussian blur, creating a new image
313
218
blurred = skimage.filters.gaussian(
314
219
image, sigma=(sigma, sigma), truncate=3.5, multichannel=True)
@@ -318,55 +223,39 @@ blurred = skimage.filters.gaussian(
318
223
The first two parameters to `skimage.filters.gaussian()` are the image to blur,
319
224
`image`, and a tuple defining the sigma to use in y- and x-direction,
320
225
`(sigma, sigma)`. The third parameter `truncate` gives the radius of the kernel
321
- in terms of sigmas. A Gaussian is defined from -infinity to +infinity. A
322
- discrete Gaussian can only approximate the real function. The `truncate`
323
- parameter steers at what distance to the center of the function it is not
324
- approximated any more. In the above example we set `truncate` to 3.5. With a
325
- `sigma` of 1.0 the resulting kernel size would be 7.
326
- The default value for `truncate` in sklearn is 4.0.
327
- The last parameter is to tell skimage how to interpret our image, that has three
226
+ in terms of sigmas. A Gaussian function is defined from -infinity to +infinity, but
227
+ our kernel (which must have a finite, smaller size) can only approximate the real function.
228
+ Therefore, we must choose a certain distance from the centre of the function where we stop
229
+ this approximation, and set the final size of our kernel. In the above example, we set
230
+ `truncate` to 3.5, which means the kernel size will be 2 * sigma * 3.5. For example,
231
+ for a `sigma` of 1.0 the resulting kernel size would be 7, while for a
232
+ `sigma` of 2.0 the kernel size would be 14. The default value for `truncate` in scikit-image is 4.0.
233
+
234
+ The last parameter to `skimage.filters.gaussian()` tells skimage to interpret our image, that has three
328
235
dimensions, as a multichannel color image.
329
- After the blur filter has been executed, the program wraps things up by
330
- displaying the blurred image in a new window.
236
+
237
+ Finally, we display the blurred image:
331
238
332
239
~~~
333
240
# display blurred image
334
- skimage.io.imshow(blurred)
241
+ fig, ax = plt.subplots()
242
+ plt.imshow(blurred)
243
+ plt.show()
335
244
~~~
336
245
{: .language-python}
337
-
338
- Here is a constructed image to use as the input for the preceding program.
339
-
340
- 
341
-
342
- When the program runs, it displays the original image, applies the filter,
343
- and then shows the blurred result. The following image is the result after
344
- applying a filter with a sigma of 3.0.
345
-
346
- 
246
+ 
347
247
348
248
> ## Experimenting with sigma values (10 min)
349
249
>
350
- > Navigate to the `code/06-blurring/` directory
351
- > and execute the `GaussBlur.py` script, which contains the program shown
352
- > above. Execute it with two command-line parameters, like this:
353
- >
354
- > ~~~
355
- > python GaussBlur.py data/gaussian-original.png 1.0
356
- > ~~~
357
- > {: .language-bash}
358
- >
359
- > Remember that the first command-line argument is the name of the file to
360
- > filter, and the second is the sigma value. Now, experiment with the sigma
361
- > value, running the program with smaller and larger values.
250
+ > Try running the code above with a range of smaller and larger sigma values.
362
251
> Generally speaking, what effect does the sigma value have on the
363
252
> blurred image?
364
253
>
365
254
> > ## Solution
366
255
> >
367
256
> > Generally speaking, the larger the sigma value, the more blurry the result.
368
257
> > A larger sigma will tend to get rid of more noise in the image, which will
369
- > > help for other operations we will cover soon, such as edge detection .
258
+ > > help for other operations we will cover soon, such as thresholding .
370
259
> > However, a larger sigma also tends to eliminate some of the detail from
371
260
> > the image. So, we must strike a balance with the sigma value used for
372
261
> > blur filters.
@@ -375,51 +264,27 @@ applying a filter with a sigma of 3.0.
375
264
376
265
> ## Experimenting with kernel shape (10 min - optional, not included in timing)
377
266
>
378
- > Now, modify the `GaussBlur.py` program so that it takes *three*
379
- > command-line parameters instead of two. The first parameter should still be
380
- > the name of the file to filter. The second and third parameters should be the
381
- > sigma values in y- and x-direction for the Gaussian to use, so that the
382
- > resulting kernel is rectangular instead of square. The new version of the
383
- > program should be invoked like this:
384
- >
385
- > ~~~
386
- > python GaussBlur.py data/gaussian-original.png 1.0 2.0
387
- > ~~~
388
- > {: .language-bash}
389
- >
390
- > Using the program like this utilizes a Gaussian with a sigma of 1.0 in y-
391
- > direction and 2.0 in x-direction for blurring
267
+ > Now, try running the code above with different sigmas in the y and x direction.
268
+ > For example, a sigma of 1.0 in the y direction, and 6.0 in the x direction.
269
+ > What is the effect on the blurred image?
392
270
>
393
271
> > ## Solution
394
272
> >
395
273
> > ~~~
396
- > > """
397
- > > * Python script to demonstrate Gaussian blur.
398
- > > *
399
- > > * usage: python GaussBlur.py <filename> <sigma_y> <sigma_x>
400
- > > """
401
- > > import skimage.io
402
- > > import skimage.filters
403
- > > import sys
404
- > >
405
- > > # get filename and kernel size from command line
406
- > > filename = sys.argv[1]
407
- > > sigma_y = float(sys.argv[2])
408
- > > sigma_x = float(sys.argv[3])
409
- > >
410
- > > # read and display original image
411
- > > image = skimage.io.imread(fname=filename)
412
- > > skimage.io.imshow(image)
413
- > >
414
- > > # apply Gaussian blur, creating a new image
274
+ > > # apply Gaussian blur, with a sigma of 1.0 in the y direction, and 6.0 in the x direction
415
275
> > blurred = skimage.filters.gaussian(
416
- > > image, sigma=(sigma_y, sigma_x ), truncate=3.5, multichannel=True
276
+ > > image, sigma=(1.0, 6.0 ), truncate=3.5, multichannel=True
417
277
> > )
418
278
> >
419
279
> > # display blurred image
420
- > > skimage.io.imshow(blurred)
280
+ > > fig, ax = plt.subplots()
281
+ > > plt.imshow(blurred)
282
+ > > plt.show()
421
283
> > ~~~
422
284
> > {: .language-python}
285
+ > > 
286
+ > > This produces a kernel that is rectangular instead of square. Notice that the image
287
+ > > is much more blurred in the x direction than the y direction.
423
288
> {: .solution}
424
289
{: .challenge}
425
290
@@ -431,19 +296,3 @@ For other kinds of noise, e.g. "salt and pepper" or "static" noise, a
431
296
median filter is typically used.
432
297
See the [`skimage.filters` documentation](https://scikit-image.org/docs/dev/api/skimage.filters.html#module-skimage.filters)
433
298
for a list of available filters.
434
-
435
- > ## Blurring the bacteria colony images (15 min)
436
- >
437
- > As we move further into the workshop, we will see that in order to complete
438
- > the colony-counting morphometric challenge at the end, we will need to read
439
- > the bacteria colony images as grayscale, and blur them, before moving on to
440
- > the tasks of actually counting the colonies. Create a Python program to read
441
- > one of the colony images (with the filename provided as a command-line
442
- > parameter) as grayscale, and then apply a Gaussian blur to the image. You
443
- > should also provide the sigma for the blur as a second command-line
444
- > parameter. Do not alter the original image. As a reminder, the images are:
445
- >
446
- > - `data/colonies-01.tif`
447
- > - `data/colonies-02.tif`
448
- > - `data/colonies-03.tif`
449
- {: .challenge}
0 commit comments