A very MIT signals problem

I've always found signals and systems interesting, as it is one of the most power tools out there. Signals and systems can be used to describe many different problems because it is simply an abstraction which describes a physical, mathematical, or computational system by the way it transforms an input signal into an output signal. It's often studied by electrical engineers because it has many direct applications to signal processing and communication systems, but there are lots of applications in other fields.

The signals and systems intro class at MIT, 6.003, is one of the most dreaded and disliked Course 6 classes. The class used to be required for all Course 6-ers, both EE and CS majors, but now that the EE/CS department has switched to a new curriculum, it's only required for double E's. It's a bit unclear where I fall in the Course 6 spectrum, but most of my friends think I'm crazy for having enjoyed 003.

I took 003 in Fall 2009 with Professor Denny Freeman. His approach deviated from the usual approach to the class by

  1. reordering the topics so that Laplace transforms were taught before Fourier transforms and
  2. introducing the concept of "Engineering Design Problems."

The "Engineering Design Problems," or EDPs for short, aimed to show 003 students some tangible applications of the material, and they were open-ended questions which typically required some amount of programming. For most people, these problems made them a bit more excited about signals and systems, but for me, this was all about getting excited about writing little pieces of code.

The most "MIT" EDP was assigned near the end of term:

The following images have been blurred. Figure out a way to sharpen each image to identify the following buildings:

Blurred Buildings assigned

You might be able to guess what some of those buildings are without even seeing the larger images the course staff included in the assignment. (b1 certainly is the most distinctive.)

Of course, there are many ways to blur an image, but looking at this from the simplest 6.003 perspective, it's most likely that either the rows or columns were blurred by a system with a single pole. After all, Denny Freeman is a big fan of Occam's Razor. Running with this assumption, such a system would have a system function with the following form:

H_{blur}(z)=\frac{1-p}{1-pz^{-1}},

where p is the system's only pole. This system would be stable if |p|<1. More importantly, if this system were a low-pass filter, i.e. if 0<p<1, it would blur the image.

You can deblur a system blurred by a single pole by applying a system with a single zero:

H_{deblur}(z)=\frac{1-pz^{-1}}{1-p},

where p is this system's only zero and has the same value as the pole in H_{blur}(z).

Since we will want to write code to deblur the image, we will want to get the difference equation corresponding to H_{deblur}(z) to apply to the rows or columns of the blurred images. The corresponding difference equation is:

y_{deblur}[n]=\frac{1}{1-p}(x[n]-px[n-1]).

Now that we may have figured out what's going on generally, let's look closely at image a1:

Blurred Building a1

The blurring in image a1 looks to be primarly horizontal, which means rows of the image's pixels would have been passed through the low-pass filter. To deblur this image, we should try to pass rows of pixels through the deblurring different equation, y_{deblur}[n]. The rows were processed either casually or anti-causally, i.e. left to right or right to left, respectively.

At this point, we really just have to dive into writing some code. The first deblurring code I wrote was a Python script to deblur a blurred_image from left to right with a pole p and save it to deblurred_image:

import Image
import os

def deblur_left2right(blurred_image, deblurred_image, p):
    original = Image.open(blurred_image)
    new_image = Image.new('L',[original.size[0],original.size[1]],0)
    original_pixels = original.load()
    new_pixels = new_image.load()

    for j in range(original.size[1]):
        new_pixels[0,j] = original_pixels[0,j]
        for i in range(original.size[0])[1:]:
            new_pixels[i,j] = (original_pixels[i,j]-p*original_pixels[i-1,j])/(1-p)

    new_image.save(deblurred_image)

After playing with different values for p, it was apparent that images a1 and a2 were blurred from left to right with a pole at 0.985, so deblurring them with a system with a zero at 0.985 returned the original images. Here is the unblurred version of a1:

Unblurred Building a1

As you can see, a1 is building 68.

The buildings in the second row, b1 and b2, had their columns blurred from bottom to top with a pole at 0.985, and the third row, c1 and c2, had their columns blurred from top to bottom with a pole at 0.985. You can change the for loops in the Python script to deblur in other directions. I encourage you to also see what happens when you change the value of p.

Even with "cute" EDPs like this one, 003 last fall was still all about grungy math - signals and systems often are. However, students who hadn't decided that the class would be too terrible before even stepping into 34-101 for the first lecture seemed to enjoy playing with some of the more tangible applications of signals and systems and got a lot out of the class. Hopefully, more people can come to appreciate this class in its own right, and maybe fewer people will shy away from being an EE because they fear 003.