# Eigenfaces Tutorial

The main purpose behind writing this tutorial was to provide a more detailed set of instructions for someone who is trying to implement an eigenface based face detection or recognition systems. It is assumed that the reader is familiar (at least to some extent) with the eigenface technique as described in the original M. Turk and A. Pentland papers (see "References" for more details).

#### 1. Introduction

The idea behind eigenfaces is similar (to a certain extent) to the one behind the periodic signal representation as a sum of simple oscillating functions in a Fourier decomposition. The technique described in this tutorial, as well as in the original papers, also aims to represent a face as a linear composition of the base images (called the eigenfaces).

The recognition/detection process consists of initialization, during which the eigenface basis is established and face classification, during which a new image is projected onto the "face space" and the resulting image is categorized by the weight patterns as a known-face, an unknown-face or a non-face image.

#### 2. Demonstration

To download the software shown in video for 32-bit x86 platform, click here. It was compiled using Microsoft Visual C++ 2008 and uses GSL for Windows.

#### 3. Establishing the Eigenface Basis

First of all, we have to obtain a training set of $M$ grayscale face images $I_1, I_2, ..., I_M$. They should be:

1. face-wise aligned, with eyes in the same level and faces of the same scale,
2. normalized so that every pixel has a value between 0 and 255 (i.e. one byte per pixel encoding), and
3. of the same $N \times N$ size.

So just capturing everything formally, we want to obtain a set $\{ I_1, I_2, ..., I_M \}$, where \begin{align} I_k = \begin{bmatrix} p_{1,1}^k & p_{1,2}^k & ... & p_{1,N}^k \\ p_{2,1}^k & p_{2,2}^k & ... & p_{2,N}^k \\ \vdots \\ p_{N,1}^k & p_{N,2}^k & ... & p_{N,N}^k \end{bmatrix}_{N \times N} \end{align} and $0 \leq p_{i,j}^k \leq 255.$

Once we have that, we should change the representation of a face image $I_k$ from a $N \times N$ matrix, to a $\Gamma_k$ point in $N^2$-dimensional space. Now here is how we do it: we concatenate all the rows of the matrix $I_k$ into one big vector of dimension $N^2$. Can it get any more simpler than that? Continue reading

# White Man's Blues

Due to the fact that I have found time to record these videos, I'm starting to suspect that my vacations have prolonged quite a bit... And I still have more than a week left.

Status update: apparently I have been awarded the Simon Gray prize by the Department of Philosophy at the University of Edinburgh. That, a KAL industrial scholarship, a couple of other prizes... I almost regret having decided to leave.

Anyway, here's the video. Try to figure out which is worse: my playing or my webcam's video quality.

Education

# Edinburgh University, Computer Science and Artificial Intelligence, Semester II

Labs @ Edinburgh University

As I have promised earlier, here's the second part of my impressions about the individual courses in the first year of Computer Science and Artificial Intelligence at the University of Edinburgh. Hopefully you will find it useful, e.g. when choosing your outside courses, preparing for the exams or simply getting a taste of the CS undergraduate life in the University of Edinburgh.

Once again, please bear in mind that all what is written below represents only my personal opinion.

Innovation and Enterprise for Scientists and Engineers
Professor: Khaled Benkrid

Lectures: a brilliant introduction to the main components and aspects of modern entrepreneurship, definitely one of the most interesting business courses that I’ve been to so far. Not only will you get the basic theoretic concepts of the modern business (like industry, marketing, operational, financial analyses, risk assessment), but you’ll also put them into practice while writing a business plan for your own idea, which will then account for 50% of your final grade.

What’s more, you’ll get the guest talks of local entrepreneurs (either spin-offs from the university, or related in some other way), an overview of the legal system regarding UK start-ups and businesses (PLCs, sole-traders, etc) and on top of that – it will all be related to the science and engineering (with Dr. Benkrid being a computer scientist himself!).
All in all – a highly inspiring, exciting and recommended course!

Exam: well… it all can’t be that interesting. Continue reading

Education

# University of Cambridge, Wolfson College

University of Cambridge, Wolfson College

So, it's finally official. In less than two months time I'll be reading Computer Science at the University of Cambridge, Wolfson College. Hopefully that's the last university in my universities chain - all in all there are not many better places to go to. Not many at all.

I'm already looking forward to it. To the legendary supervision sessions, to the world class experts in the field, to the competitiveness amongst the students. I'm sure I will finally arrive at the place where I'll be the average guy between the best one's... not the other way around.

(I'm not convinced that the latter applies to the basketball team, though. Well, I guess we'll find that out pretty soon).

Confirmation Letter. Cambridge University, Wolfson College, 2009.

Education

# Edinburgh University, Computer Science and Artificial Intelligence, Semester I

The exam results came back and the first year is finally over, therefore I have decided to share my impressions about the individual lectures in the first two semesters. Hopefully it will help someone to choose one subject over another, not to make the same mistakes when preparing for the exams that I did, or simply to get the taste of the first year in college. Please bear in mind that all what is written below represents only my personal, highly subjective opinion.

Functional Programming

Lectures: a wonderful introduction to the functional programming. Amazing teaching skills and professor's authority in the classroom - from ripping a T-shirt to reveal a big superman-lambda, to being one of the principal engineers and designers of the Haskell programming language - 10 out of 10.

Exam: Final grade is made by a programming class test (10%) and a final exam (90%). The programming class test is pretty straightforward - three simple tasks to test one's basic knowledge of Haskell (things you need to know are the syntax, because it's done on paper, list comprehension, recursion and simple library functions). The final exam is done in front of computer with plenty of time (2 hours) for three simple tasks (e.g. take a list of integers and return the sum of the cubes of the positive numbers in that list). The only catch is that the same problem has to be solved in a couple of different ways: using basic functions, using list comprehension, using recursion and using the higher-order functions, however... at the end of the day - it's still the same problem.

My advice in succeding in this subject: participate in the class' programming competition (see this years competition and my entry). If you'll manage to get something done - you won't need to spend any more time to prepare for the final exam, and I can hardly imagine how you'd get less than an A (my personal result - 99). Continue reading

Development

# SMRP6400/SMDK64X0 IIC synchronization problems

Debugging Samsung SMRP6400

Since last week we have spent quite some time debugging Samsung SMRP6400/SMDK64X0 IIC drivers, I thought I might share with one particular example here. It is both a good showcase of the hardware/software synchronization issues and since the bugs are in the latest version of the drivers shipped together with the development platforms, it might save someone from additional headaches.

So, while working on the drivers for IIC one of our automated tests to make sure that IIC still works was to write some data on the bus, do an immediate read-back and verify that both data written and read back matches; something similar to this:

UCHAR outData[3] = { REGISTER, DATA_BYTE_1, DATA_BYTE2 };
UCHAR inData[2] = { 0, 0 };

if ((inData[0] != DATA_BYTE_1) || (inData[1] != DATA_BYTE_2))
{
DEBUGMSG(ERROR_MSG,
(TEXT("Immediate write/read data mismatch: data sent [0x%X " \
"0x%X] differs from the data received [0x%X, 0x%X]."),
DATA_BYTE_1, DATA_BYTE_2, inData[0], inData[1]));
}

However, after we added some IIC read calls from another hardware driver it started spitting fire throwing the following error message:

Immediate write/read data mismatch: data sent [0xCA, 0xFE]
differs from the data received [0xCA, 0xFE].

Now this clearly meant we had a serious problem: the error message was saying that the data does not match, which obviously was not the case as shown by the message text!

Since we were pretty confident about our side of things, as well as the readings from the scope, it seemed like a good time to start looking at the Samsung IIC drivers (and especially s3c64X0_iic_lib.cpp). The driver structure there is pretty straightforward: the first read/write byte on the bus triggers the hardware IRQ, which is mapped to SysIntr triggering a transfer event; then any subsequent call to a read/write function blocks waiting for a transfer-done event, which is triggered when the last byte is read/written in the IST.

Everything looks sane up to the point where a transfer-done event is signalled from the IST (pseudocode, not the original code below, due to the legal issues):

static HANDLE ghTransferEvent;
static HANDLE ghTransferDone;
static DWORD IICSysIntr;

...

static DWORD IST(LPVOID lpContext)
{
BOOL bTransferDone = FALSE;

while (TRUE) {
WaitForSingleObject(ghTransferEvent, INFINITE);

switch (IIC_BUS_STATUS) {
// receive bytes and store them in the buffer
break;

case MASTER_TRANSMIT:
// transmit bytes from the buffer in memory
if (LAST_BYTE) bTransferDone = TRUE;
break;

InterruptDone(IICSysIntr);

if (bTransferDone) {
SetEvent(ghTransferDone);
}
}
}
}

Two major problems with this code are:

1. The bTransferDone variable is never set from the IIC read, and hence the transfer-done event for bus reads is never triggered,
2. After the bTransferDone is set from the IIC write, it is never reset, hence the transfer-done event is triggered after reading/writing single byte on the bus in all subsequent transactions.

That explains the initial test case failure: during the write/immediate read data comparison the data arrives exactly between the if statement and the following printout, thus triggering the error message, but printing the correct data to the output due to the early signal of the event.

The way to solve this is also straightforward: make sure that the bTransferDone variable is cleared after the transfer-done event is triggered, and make sure that master-receive mode sets the bTransferDone variable after reading the last byte of the transaction from the IIC bus.

In pseudocode it would look similar to:

static DWORD IST(LPVOID context)
{
BOOL bTransferDone = FALSE;

while (TRUE) {
WaitForSingleObject(ghTransferEvent, INFINITE);

switch (IIC_BUS_STATUS) {
// receive bytes and store them in the buffer
if (LAST_BYTE) bTransferDone = TRUE;
break;

case MASTER_TRANSMIT:
// transmit bytes from the buffer in memory
if (LAST_BYTE) bTransferDone = TRUE;
break;

InterruptDone(IICSysIntr);

if (bTransferDone) {
bTransferDone = FALSE;
SetEvent(ghTransferDone);
}
}
}
}

The lesson of the day (quoting my colleague) is: "The first rule about multithreading - you're wrong".

At work. Wolfson Microelectronics PLC, 2009

Life

# Diversity Visa

"Green Card"

It all comes at once.

A couple of days ago I received a call from Lithuania: there was a letter from U.S. waiting for me at home. After some discussion it became clear that I was one of the 100 000 selected to compete for 55 000 DV's ("Green Cards").

After some short initial joy, problems and worries started to creep in: one has to cross the U.S. border in six months after getting a DV - something which I'm not keen doing at all, because I'll be studying in Cambridge University at that time, and since I've worked quite hard to get there, it's priority #1 in the list.

One possible solution would be to go to U.S. for the summer and then comeback for a school year, but... we'll see how that goes, it might introduce some additional problems (about which I'm not fully aware at the moment). It would be nice to visit some old friends though...

Anyway, I'll try to keep the whole process documented here as well - it might give someone a good estimate of trouble involved in getting a DV (and help me to track the overall progress as well).

Thanks for reading and stay tuned - there will be more.

Boston, U.S.A. (09/2007)

Miscellaneous

# Welcome

Hello, and welcome.

My name is Manfred Zabarauskas (about me), I'm the only owner, writer and editor of this blog.

I'll do my best to make your experience here valuable, by helping you not to fall in the same traps in software development, offering you my point of view about the things in the world, or simply allowing you to find out more about me in case you have met me in the real life.

Since only God makes no mistakes (does he?), my apologies in advance for all the wrong steps that I'll make and learn from on the way. A very warm welcome once again, and I'll hope you'll enjoy this blog as much as I do.