Image Blurring

One type of data that may not immediately seem manipulatable with Python is image data. Yet, that is exactly what you will do in this assignment! Large quantities of image data are collected every day: telescopes gather images of distant galaxies, satellites take photos of the earth’s surface, your car license plate is photographed as you cross the 520-bridge, and video cameras collect footage as you enter a bank.

One way we process images is by adding filters. Blurring is a type of image filter. Blurring can be used to reduce the level of noise in an image and prepare it for further processing. Most images are stored in a computer as large rectangular grids of pixels. Many filters, such as blur, can be applied to an image by changing each pixel value to a weighted combination of the neighboring pixels, called a convolution. The matrix of weights used is called the kernel of the transformation.

Info

Wikipedia has more information about image processing with convolution, but this reading is optional and not required to complete this assignment.

Your program will read in black and white images, and output a blurred version of that image. The grayscale images we will use can be thought of as a rectangular grid of pixels where each pixel is represented by an integer value from 0 to 255 (0=black, 255=white). Each location in the grid represents one pixel in the image.

Note

Color images are represented differently. Each pixel has three values, one each for red, green, and blue. We will not process color images in this assignment, but we provide a Python program to convert color images into black and white images so that you can run the program on any image you choose.

The Algorithm

One simple way we can blur images is to take each pixel value in the original grid, convert them to a new value, and return the output in a new grid. We can calculate the new value by taking the average of that pixel and the 8 pixels that surround it.

Important

Instead of using regular division / in the formula, we will use integer division by using //. This is so we can get a whole number between 0 and 255.

For example, consider the pixel grid below:

1    5   61
4    3    2
10   11  100

If we are calculating the average of the center pixel (with value 3), its average would be computed by adding all 8 surrounding values to 3 and then dividing the sum by 9. So, the value stored in the new blurred grid would be:

1+5+61+4+3+2+10+11+1009=1979=21 \frac{1 + 5 + 61 + 4 + 3 + 2 + 10 + 11 + 100}{9} = \frac{197}{9} = 21

Your code will need to examine each pixel in the pixel grid, calculate the average value for that pixel, and store that value in the same location in the new grid using the algorithm described above. For any pixel location where its surrounding 8 pixels fall outside of the image (for example, a pixel on the edge of the image), you should substitute those values with 0. In the example above, if that 3 x 3 grid actually represented our entire image, we would calculate a new value for the upper right (northeast) corner (the value 61) as

0+0+0+5+61+0+3+2+09=719=7 \frac{0 + 0 + 0 + 5 + 61 + 0 + 3 + 2 + 0}{9} = \frac{71}{9} = 7

Below, we show a few images represented by grids as well as the result of blurring each image. Remember that we are using truncating integer division.

Original Image 1:

1    2    3
4    5    6
7    8    9

Blurred Image 1:

1    2    1
3    5    3
2    4    3

Original Image 2:

1  1  1  1  1  1
1  1  1  1  1  1
1  1  1  1  1  1
1  1  1  1  1  1

Blurred Image 2:

0  0  0  0  0  0
0  1  1  1  1  0
0  1  1  1  1  0
0  0  0  0  0  0

Original Image 3:

10  10  10  10
10  10  10  10
10  10  10  10
10  10  10  10
10  10  10  10

Blurred Image 3:

4   6   6   4
6  10  10   6
6  10  10   6
6  10  10   6
4   6   6   4