CSE 455: Project 4: Eigenfaces

Dan Gnanapragasam

Face recognition with eigenfaces

Overview

Face recognition is an important problem in computer vision. For this project, we implemented face recognition with eigenfaces. First, we took a set of sample faces (as w x h images) which could be treated as vectors in wh dimensional space. Thus, the faces form a lower dimensional space embedded in this larger space (wh dimensional space). To find a basis for the smaller space, we can use PCA ( principle component analysis ). In this, we compute a matrix, A, of dimension (wh x m) from the input faces where m is the number of faces. Then, by computing the eigenvectors of AAT, we can compute a basis for the space of faces. Then, by taking the vectors with the largest eigenvalues, we can approximate the space of faces with a small number of basis vectors. Then, we can represent a face, x as x = xaverage + a1 v1 + ... + ak vk where the vs are eigenvectors and the as are coefficients. As we can see, this process can be sped up by considering the eigenvectors of ATA.

Implementation

There are several methods in the code that important for the computation of eigenfaces.

Challenges

The hardest part of this project was dealing with the horrible documentation of the code. The mathematics was easy enough to follow, but the hardest bug to find was due to the fact that Image::Crop and Face::SubImage did not do the same thing, though their method signatures seemed to suggest that they would.

Experiments

Testing Recognition with Cropped Class Images

In this experiment we computed 10 eigenfaces from our set of faces. The faces are shown below, along with the average face.

With these eigenfaces, we achieved an accuracy of 24 out of 33 images.

Graphing the performance of the recognizer against the number of eigenfaces yields the graph below:

Questions

  1. As the number of eigenfaces increase, the number of faces that are correctly recognized tends to increase with a few small decreases of 1 face recognized. However, the increase is highest for the first few faces and plateaus around face 5. This follows the intution behind the ordering of our eigenfaces: The vectors that we add initially are the most important as they have the highest eigenvalues. The later eigenfaces have lower eigenvalues and thus are not as important to the overall representation of the face. There's not a clear answer as to how many eigenfaces are needed. It's pretty clear that, beyond 20 eigenfaces, the gain is virtually nonexistent. However. Note that the performance at 9 eigenvectors is at least as good as the performance of 10 to 20 eigenvectors and is often much better.
  2. Many of the recognition errors were reasonably small in the the actual matching face was pretty high up on the list. An instance of this is when the algorithm mistook the following face for this image rather than Note that the lips in the first and second image are similar where as the lips differ between the first and third images. Additionally, the curvature of the bottom left of the image of the first two images makes it unsurprising that algorithm made a mistake here.

Cropping and finding faces

In this experiment, we computed 10 eigenfaces and then used them to crop elf.tga, shown below:

The cropped image looks like this

The algorithm also recognizes two faces as shown below

I decided that I couldn't find a portrait of myself on the web, so I just cropped a test image so that it looked like a portrait. The image is shown below

Below are results from all of the groups

And here is the test image

Questions

  1. For the elf image, I scaled from 0.45 to 0.55 by 0.01 as the instructions stated. For the group shots, I scaled from 0.5 to 1 by 0.1. For the test image and the portrait derived from the test image, I scaled from 0.1 to 0.5 by 0.01.
  2. I was fortunate enough to not have any errors in the final images. However, when I used an improper scale, I often found some errors, in the image. To deal with these errors, I varied the scale range, which made it much easier to find faces. Earlier, my algorithm only achieved 50% accuracy on the group images. However, this accuracy increased to 100% on the group images after I used image.crop instead of face.subImage when I extracted a candidate face in findFaces. This is

Verify Face

In this experiment, we created a set of 6 eigenfaces and a userbase from the set of netural faces. Then, we ran the recognition method against a smiling face belonging to that person and a smiling face that belongs to another person.

Questions

  1. I wrote a script to do the experiment listed above. Then, I collected the MSEs over several runs. With a little bit of scripting, I was able to sort the MSEs for the proper matches and the mismatches. Thus, I had two ascending lists of errors. To find the error that minimize the total number of misclassifcations, for each MSE in the list of proper matches, I computed the error rate given a threshold at that MSE (in both the proper matches and the mismatches) and then took the lowest error rate over all thresholds. The best MSE threshold was 100000.
  2. Using the best threshold, I correctly recognized 29 of the 33 faces, falsely rejecting 4 of the 33 faces. I also correctly rejected 28 of the 33 faces, falsely rejected 5 of the faces.

Extra Credit

A small speedup

Computing the eigenvectors of AAT is very costly as it is a wh x wh matrix. For a 50x50 image, this is a 2500 dimensional space. As most matrix operations are O(n2) or O(n3), this is incredibly expensive.

Given that we can vary the size of the image, but the number of training images is fixed, we should instead compute the eigenvectors of ATA, which is an m x m matrix. By doing this, we can easily vary the height and width of the eigenfaces. This works because the rank of AAT is equal to the rank of ATA.

Morphing faces

We can treat any two faces as vectors x and y in the space. Then, we can draw a line between the two vector by using the equation tx + (1-t)y. Thus, by evaluation this function at points between the two faces, we can morph one face into another as shown below. In this animation, we morph from my face into my friend's face and beyond. Note that you will need a browser with Javascript to view this animation.