Skip to content

Commit 37b874e

Browse files
authored
Update 06-blurring.md
Add section about visualizing image blur effects as discussed in datacarpentry#221
1 parent 06c4504 commit 37b874e

File tree

1 file changed

+135
-1
lines changed

1 file changed

+135
-1
lines changed

episodes/06-blurring.md

+135-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,141 @@ fig, ax = plt.subplots()
327327
plt.imshow(blurred)
328328
```
329329

330-
![](fig/gaussian-blurred.png){alt='Original image'}
330+
![](fig/gaussian-blurred.png){alt='Blurred image'}
331+
332+
## Visualizing Blurring
333+
334+
Somebody said once "an image is worth a thousand words".
335+
What is actually happening to the image pixels when we apply blurring may be
336+
difficult to grasp, let's now visualize the effects of blurring from a different
337+
perspective.
338+
339+
Let's use the petri-dish image from previous episodes:
340+
341+
![Original Petri dish image](fig/colonies-01.jpg){alt='Bacteria colony'}
342+
343+
What we want to see here is the pixel intensities from a lateral perspective,
344+
we want to see the profile of intensities .
345+
For instance, let's look for the intensities of the pixels along the horizontal
346+
directory at `Y=150`:
347+
348+
```python
349+
import matplotlib.pyplot as plt
350+
import imageio.v3 as iio
351+
import skimage.color
352+
353+
# read colonies color image and convert to grayscale:
354+
#
355+
image = iio.imread('data/colonies-01.tif')
356+
image_gray = skimage.color.rgb2gray(image)
357+
358+
# define the pixels we want to view the intensities (profile)
359+
#
360+
xmin, xmax = (0, image_gray.shape[1])
361+
ymin = ymax = 150
362+
363+
# view the image indicating the profile pixels position
364+
#
365+
fig,ax = plt.subplots()
366+
ax.imshow(image_gray, cmap='gray')
367+
ax.plot([xmin,xmax], [ymin,ymax], color='red')
368+
```
369+
370+
![
371+
Grayscale Petri dish image marking selected pixels for profiling
372+
](fig/petri-selected-pixels-marker.jpg){
373+
alt='Bacteria colony image with selected pixels marker'
374+
}
375+
376+
We are using the grayscale version of the image for simplicity.
377+
The intensity of those pixels we can see with a simple line plot:
378+
379+
```python
380+
# Just rename our "Y" variables for a better reading
381+
#
382+
Y = ymin = ymax
383+
384+
# Select the vector of pixels along "Y"
385+
#
386+
image_gray_pixels_slice = image_gray[Y, :]
387+
388+
# Guarantee the intensity values are in the [0:255] range (unsigned integers)
389+
#
390+
image_gray_pixels_slice = img_as_ubyte(image_gray_pixels_slice)
391+
392+
fig = plt.figure()
393+
ax = fig.add_subplot()
394+
395+
ax.plot(image_gray_pixels_slice, color='red')
396+
ax.set_ylim(255, 0)
397+
ax.set_ylabel('L')
398+
ax.set_xlabel('X')
399+
```
400+
401+
![
402+
Intensities profile line plot of pixels along Y=150 in original image
403+
](fig/petri-original-intensities-plot.jpg){
404+
alt='Pixel intensities profile in original image'
405+
}
406+
407+
And now, how does the same set of pixels look in the corresponding *blurred* image:
408+
409+
```python
410+
# First, let's create a blurred version of (grayscale) image
411+
#
412+
from skimage.filters import gaussian
413+
414+
image_blur = gaussian(image_gray, sigma=3)
415+
416+
# Like before, plot the pixels profile along "Y"
417+
#
418+
image_blur_pixels_slice = image_blur[Y,:]
419+
image_blur_pixels_slice = img_as_ubyte(image_blur_pixels_slice)
420+
421+
fig = plt.figure()
422+
ax = fig.add_subplot()
423+
424+
ax.plot(image_blur_pixels_slice, 'red')
425+
ax.set_ylim(255, 0)
426+
ax.set_ylabel('L')
427+
ax.set_xlabel('X')
428+
```
429+
430+
![
431+
Intensities profile of pixels along Y=150 in *blurred* image
432+
](fig/petri-blurred-intensities-plot.jpg){
433+
alt='Pixel intensities profile in blurred image'
434+
}
435+
436+
And that is why *blurring* is also called *smoothing*.
437+
This is how low-pass filters affect neighbouring pixels.
438+
439+
Now that we saw the effects of blurring an image from
440+
two different perspective, front and lateral, let's take
441+
yet another look using a 3D visualization.
442+
443+
The code to generate these pictures, though, is out of the
444+
scope of this episode.
445+
446+
![
447+
A 3D plot of pixel intensities across the whole Petri dish image before blurring.
448+
[Explore how this plot was created with matplotlib](LINKTOGIST).
449+
Image credit: [Carlos H Brandt](https://github.com/chbrandt/).
450+
](fig/3D_petri_before_blurring.png){
451+
alt='3D surface plot showing pixel intensities across the whole example Petri dish image before blurring'
452+
}
453+
454+
![
455+
A 3D plot of pixel intensities after Gaussian blurring of the Petri dish image.
456+
Note the 'smoothing' effect on the pixel intensities of the colonies in the image,
457+
and the 'flattening' of the background noise at relatively low pixel intensities throughout the image.
458+
[Explore how this plot was created with matplotlib](LINKTOGIST).
459+
Image credit: [Carlos H Brandt](https://github.com/chbrandt/).
460+
](fig/3D_petri_after_blurring.png){
461+
alt='3D surface plot illustrating the smoothing effect on pixel intensities across the whole example Petri dish image after blurring'
462+
}
463+
464+
331465

332466
::::::::::::::::::::::::::::::::::::::: challenge
333467

0 commit comments

Comments
 (0)