MP2: Image Filtering¶

In this lab, you'll filter an image using weighted-average filters and edge-detection filters.

In order to make sure everything works, you might want to go to the command line, and run

pip install -r requirements.txt

This will install the modules that are used on the autograder, including numpy, h5py, and the gradescope utilities.

In [1]:
import submitted
import importlib
import numpy as np
import matplotlib.pyplot as plt
import h5py
from PIL import Image
import matplotlib.figure
%matplotlib inline

Part 0: Load the data, and show the image¶

In [2]:
imagefile = 'image.jpg'
original = np.asarray(Image.open(imagefile)).astype('float64')
print('The image size is:')
print(original.shape)
The image size is:
(600, 800, 3)
In [3]:
imagefile = 'image.jpg'
original = np.asarray(Image.open(imagefile)).astype('float64')
fig = plt.figure(figsize=(10, 8))
ax = fig.subplots()
ax.imshow(original.astype(int))
ax.set_title('Here is the original image!')
Out[3]:
Text(0.5, 1.0, 'Here is the original image!')
No description has been provided for this image
In [4]:
fig = plt.figure(figsize=(10,8))
axs = fig.subplots(3,1,sharex=True)
axs[0].plot(original[300,:,0])
axs[0].set_title('Row 300 of the image, red color plane')
axs[1].plot(original[300,:,1])
axs[1].set_title('Row 300 of the image, green color plane')
axs[2].plot(original[300,:,2])
axs[2].set_title('Row 300 of the image, blue color plane')
Out[4]:
Text(0.5, 1.0, 'Row 300 of the image, blue color plane')
No description has been provided for this image

Part 1: Create a rectangular filter, and show it in a plot¶

In [5]:
importlib.reload(submitted)
help(submitted.todo_rectangular_filter)
Help on function todo_rectangular_filter in module submitted:

todo_rectangular_filter()
    Create 11 samples of a 7-sample rectangular filter,
    h[n]=1/7 for -3 <= n <= 3, h[n]=0 otherwise.
    Return 11 samples of both n_rect and h_rect.

In [6]:
importlib.reload(submitted)
(n_rect, h_rect) = submitted.todo_rectangular_filter()
fig = plt.figure(figsize=(10,8))
axs = fig.subplots(3,1,sharex=True)
axs[0].stem(n_rect, h_rect, markerfmt='D')
axs[0].set_title('Rectangular smoothing filter')
(n_step, x_step) = submitted.unit_step()
axs[1].stem(n_step, x_step, markerfmt='D')
axs[1].set_title('Unit step')
y_step = np.convolve(x_step, h_rect, mode='same')
axs[2].stem(n_step, y_step, markerfmt='D')
axs[2].set_title('Rectangular-smoothed Unit step')
Out[6]:
Text(0.5, 1.0, 'Rectangular-smoothed Unit step')
No description has been provided for this image

Part 2: Use h_rect to smooth the rows of the image¶

In [7]:
importlib.reload(submitted)
help(submitted.todo_convolve_rows)
Help on function todo_convolve_rows in module submitted:

todo_convolve_rows(X, h)
    Convolve Y=X*h along the rows.
    Use mode='same', so that the output, Y, has the same size as X.

In [8]:
importlib.reload(submitted)
smoothed_rows = submitted.todo_convolve_rows(original, h_rect)
fig = plt.figure(figsize=(10, 8))
ax = fig.subplots()
ax.clear()
ax.imshow(smoothed_rows.astype(int))
ax.set_title('Image with rows smoothed by a length-7 rectangular smoother')
Out[8]:
Text(0.5, 1.0, 'Image with rows smoothed by a length-7 rectangular smoother')
No description has been provided for this image

Part 3: Use h_rect to smooth the columns of the image¶

In [9]:
importlib.reload(submitted)
help(submitted.todo_convolve_columns)
Help on function todo_convolve_columns in module submitted:

todo_convolve_columns(X, h)
    Convolve Y=X*h along the columns.
    Use mode='same', so that the output, Y, has the same size as X.

In [10]:
importlib.reload(submitted)
smoothed_image = submitted.todo_convolve_columns(smoothed_rows, h_rect)
fig = plt.figure(figsize=(10,8))
ax = fig.subplots()
ax.clear()
ax.imshow(smoothed_image.astype(int))
ax.set_title('Image with both rows and columns smoothed by a length-7 rectangle')
Out[10]:
Text(0.5, 1.0, 'Image with both rows and columns smoothed by a length-7 rectangle')
No description has been provided for this image

Step 4: create a backward-difference filter, and show it in a plot¶

In [11]:
importlib.reload(submitted)
help(submitted.todo_backward_difference)
Help on function todo_backward_difference in module submitted:

todo_backward_difference()
    Create 11 samples of a backward difference filter, h[n],
    such that the convolution y=x*h gives, as output, y[n]=x[n]-x[n-1].
    Note that you'll need to set h[n]=0 for most n; only a couple of
    samples will be nonzero.
    Return the n_array and the h_array.

In [12]:
importlib.reload(submitted)
(n_diff, h_diff) = submitted.todo_backward_difference()
fig = plt.figure(figsize=(10,8))
axs = fig.subplots(3,1,sharex=True)
axs[0].stem(n_diff, h_diff, markerfmt='D')
axs[0].set_title('Backward-Difference filter')
(n_step, x_step) = submitted.unit_step()
axs[1].stem(n_step, x_step, markerfmt='D')
axs[1].set_title('Unit step')
y_step = np.convolve(x_step, h_diff, mode='same')
axs[2].stem(n_step, y_step, markerfmt='D')
axs[2].set_title('Differenced Unit step')
Out[12]:
Text(0.5, 1.0, 'Differenced Unit step')
No description has been provided for this image

Step 5: create a Gaussian smoothing filter, and show it in a plot¶

In [13]:
importlib.reload(submitted)
help(submitted.todo_gaussian_smoother)
Help on function todo_gaussian_smoother in module submitted:

todo_gaussian_smoother(stdev=1)
    Create 11 samples of a Gaussian filter with a standard deviation of stdev.
    You might want to call the function gaussian(), which is defined at the
    top of this file.
    Return the n_array and the h_array.

In [14]:
importlib.reload(submitted)
stdev = 2
(n_gauss, h_gauss) = submitted.todo_gaussian_smoother(stdev)
fig = plt.figure(figsize=(10,8))
axs = fig.subplots(3,1,sharex=True)
axs[0].stem(n_gauss, h_gauss, markerfmt='D')
axs[0].set_title('Gaussian smoothing filter')
(n_step, x_step) = submitted.unit_step()
axs[1].stem(n_step, x_step, markerfmt='D')
axs[1].set_title('Unit step')
y_step = np.convolve(x_step, h_gauss, mode='same')
axs[2].stem(n_step, y_step, markerfmt='D')
axs[2].set_title('Gaussian-smoothed Unit step')
Out[14]:
Text(0.5, 1.0, 'Gaussian-smoothed Unit step')
No description has been provided for this image
In [15]:
importlib.reload(submitted)
smoothed_rows = submitted.todo_convolve_rows(original, h_gauss)
smoothed_image = submitted.todo_convolve_columns(smoothed_rows, h_gauss)
fig = plt.figure(figsize=(10, 8))
ax = fig.subplots()
ax.clear()
ax.imshow(smoothed_rows.astype(int))
ax.set_title('Image with rows smoothed by stdev=%g Gaussian smoother'%(stdev))
Out[15]:
Text(0.5, 1.0, 'Image with rows smoothed by stdev=2 Gaussian smoother')
No description has been provided for this image

Step 6: create a difference-of-Gaussians filter, and show it in a plot¶

In [16]:
importlib.reload(submitted)
help(submitted.todo_difference_of_gaussians)
Help on function todo_difference_of_gaussians in module submitted:

todo_difference_of_gaussians()
    Create 11 samples of a difference-of-Gaussians filter, h[n] is the
    difference between a unit-variance Gaussian centered at mu=0,
    minus a unit-variance Gaussian centered at mu=1.
    Return the n_array and the h_array.

In [17]:
importlib.reload(submitted)
(n_dog, h_dog) = submitted.todo_difference_of_gaussians()
fig = plt.figure(figsize=(10,8))
axs = fig.subplots(3,1,sharex=True)
axs[0].stem(n_dog, h_dog, markerfmt='D')
axs[0].set_title('Difference-of-Gaussians filter')
(n_step, x_step) = submitted.unit_step()
axs[1].stem(n_step, x_step, markerfmt='D')
axs[1].set_title('Unit step')
y_step = np.convolve(x_step, h_dog, mode='same')
axs[2].stem(n_step, y_step, markerfmt='D')
axs[2].set_title('DoG-filtered Unit step')
Out[17]:
Text(0.5, 1.0, 'DoG-filtered Unit step')
No description has been provided for this image

Step 7: Use DoG filter to compute Gx and Gy, then normalize¶

In [18]:
importlib.reload(submitted)
help(submitted.todo_normalize_colors)
Help on function todo_normalize_colors in module submitted:

todo_normalize_colors(X)
    Normalize the color planes of the image, so that
    each color plane has a maximum value of 1.0, and a minimum value of 0.0.

In [19]:
importlib.reload(submitted)
tmp = submitted.todo_convolve_rows(original, h_dog)
hgrad = submitted.todo_normalize_colors(np.abs(tmp))
tmp = submitted.todo_convolve_columns(original, h_dog)
vgrad = submitted.todo_normalize_colors(np.abs(tmp))
fig = plt.figure(figsize=(14,8))
axs = fig.subplots(1,2)
axs[0].imshow(hgrad)
axs[0].set_title('Horizontal grad magnitude')
axs[1].imshow(vgrad)
axs[1].set_title('Vertical grad magnitude')
Out[19]:
Text(0.5, 1.0, 'Vertical grad magnitude')
No description has been provided for this image

Step 8: Gradient magnitude¶

In [20]:
importlib.reload(submitted)
help(submitted.todo_gradient_magnitude)
Help on function todo_gradient_magnitude in module submitted:

todo_gradient_magnitude(GH, GV)
    Given the horizontal gradient GH and vertical gradient GV,
    compute and return the gradient magnitude GM=sqrt(GH**2 + GV**2)

In [21]:
importlib.reload(submitted)
tmp = submitted.todo_gradient_magnitude(hgrad, vgrad)        
gradient_magnitude = submitted.todo_normalize_colors(tmp)
fig = plt.figure(figsize=(10,8))
ax = fig.subplots()
ax.imshow(gradient_magnitude)
ax.set_title('Gradient magnitude')
Out[21]:
Text(0.5, 1.0, 'Gradient magnitude')
No description has been provided for this image

Step 9: Check your results¶

Before you upload your code to the autograder, you can check it using grade.py:

In [23]:
!python grade.py
........
----------------------------------------------------------------------
Ran 8 tests in 0.723s

OK

If you get