Eigenfaces

Report by Ankit Gupta


Top 10 eigen faces from the cropped non smiling faces
Average face
(Face of the common man)


Face recognition using eigenfaces

The following graph plots the number of correct matches out of the 21 smiling faces using a database constructed from non-smiling database. It turns out that the last eigenvector is zero which indicates that the matrix is rank deficient. Hence the graph has only been plotted from the number of eigenfaces varying from 1 to 19.





How many eigenfaces to use?

From the graph we see that as we increase the number of eigenfaces considered, the recognition improves but later on it is seen to saturate. Using more number of eigenfaces requires more time while recognition. So there is a trade off between the speed and accuracy. I also think that using more and more eigenfaces will tend to overfit the system which might not be good when we want to detect faces which are not in the database.

The number of eigenfaces to be used can be decided by looking at the eigenvalues. The eigenvectors corresponding to small eigenvalues only contain information about detailed differences in comparison to a higher level discrimination by the eigenvectors with larger eigenvalues. We can choose to remove the vectors with smaller eigenvalues without affecting the results by a great amount. Hence one way to do this will be to sort the eigenvalues in descending order and plot them as shown below.




As seen, the change in the eigenvalues diminishes after around the index 10 or 11. Hence this might be the good choice for the number of eigenvectors to be used.

What about recognition errors?

As observed from the recognition accuracy graph, we do get a lot of wrong matches. Most of the times, the correct answer did appear among the top few results for the match.

Examples:

query rank 1 rank 2
(correct)

query rank 1 rank 4
(correct)

In the second example, the matched faces do look quite similar. (Maybe that's an understatement!)

The mistakes are sometimes good as in the second example and bad as in the first example. In general, it is observed that the system does a reasonable job.

Face detection using eigenfaces

Generating Skin image

I implemented a naive skin detection system first based on the color range values. The color constraints on a pixel to be a skin pixel are -

(R>=1.2*G) AND (G<=8*B) && (G>=0.9*B) && (R<=2.8*G)

To take care of the color noise, I check this constraint over a 11X11 patch centered around that pixel and accordingly make it a potential candidate for a face. This detection works quite well as seen below:



Original Image



"Skin" image (gray values indicate face detection error)

This criterion for skin was empirically set and it is not validated over a big database. Ideally, we need to do some kind of learning on the data we are processing since a single skin color model will not fit people from any geographical location. This is noted in one of the examples later.

Generating Facial Skin image

For face detection, I go one step further and filter potential face candidates based on the number of skin pixels in the patch. This stage is useful to remove the effect of color aggregation in the patch-based method in the previous stage. This threshold has been empirically set to 0.1. So the assumption is that any rectangular patch can be a face only if it has 90% skin pixels inside it. The threshold of 0.1 is quite strict in the sense that it does not allow people to have facial hair. If we want to take care of that, we have to loosen this criterion by increasing the threshold. Thus this threshold can be seen as the maximum portion of face covered with hair.

The skin image after this filtering looks like the following:



"Facial Skin" image (gray values indicate face detection error). Facial hair threshold: 0.1
Notice that most false positives from the skin image go away

Detecting faces from the "Facial Skin" image

Now that we have the potential candidates, we compute the errors on forward and back projections of the candidate on the eigenspace. We choose the top results from this. Also, we take care that any two resulting faces do not overlap with each other much. This overlap is checked by computing distance between the centres of the patches. If this distance is less than 50 pixels, then we choose the better one and discard the other. This threshold has been hardcoded as of now and will have to depend on the expected density of faces in the image.

The following image shows the detected faces in the image (scale: 0.3, top 15 faces).



Top 15 detected faces (has some false positives)

To see the effect of the facial hair threshold, consider the following image:

Has no "facial skin" with threshold 0.1 Faces detected after threshold increased to 0.4

min_scale=0.45, max_scale=0.55, step=0.01


Examples of cropped faces:





min_scale=0.45
max_scale=0.55
step=0.01




min_scale=0.3
max_scale=0.5
step=0.1




min_scale=0.3
max_scale=0.5
step=0.1


More examples of face detection in group photos



min_scale=0.45, max_scale=0.55, step=0.01, facial_threshold=0.1




min_scale=0.65, max_scale=0.85, step=0.1, facial_threshold=0.4. In this example, I had to augment the skin criterion with a minimum threshold on RGB each. Also, the left most face does not appear in the top 9 faces because of a false positive else where. But it does come up when we choose top 10 faces instead. Also, it seems having illumination changes on the face makes a difference. Here the faces are illuminated from their left side and where this effect is more, the system makes some mistakes.


Choice of scale parameters: In most of my experiments, the following parameters worked well: min_scale=0.3 max_scale=0.7 step=0.05. This is an exhaustive interval over which my images worked well. The interval and step size can be varied by having some estimates about the size of the faces in the image.

Mistakes in face detection - Face detection is not fool proof. During the experimentation I did observe false positives which in turn cause some proper faces to not appear in the final rankings. This is mainly because of the loose training of the system. I also tried using a normalization phase before PCA where I multiplied the MSE by the ratio of distance from mean to standard deviation. But somehow I did not observe an improvement. I think that was the case because the standard deviation is computed only on a small set of observations and is not accurate. There are many parameters in the system and I think that using priors from the data will improve the system.

Face morphing


Click here to see movie


Click here to see movie Click here to see movie

Exaggerating the differences between the two faces by making them move away from each other in the eigenspace just seems to increase contrast. It does not make much sense to me.

Extra Credit

1. Skin detection using color cues
2. Facial skin detection using voting based mechanism on skin patches
3. Implemented the speedup mentioned on the course web page for computing eigenfaces
4. Face morphing