<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Manfredas Zabarauskas&#039; Blog &#187; eigenfaces</title>
	<atom:link href="http://blog.zabarauskas.com/tag/eigenfaces/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.zabarauskas.com</link>
	<description>We are what we repeatedly do; excellence, then, is not an act but a habit. -- Aristotle</description>
	<lastBuildDate>Tue, 29 Nov 2011 03:23:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Eigenfaces Tutorial</title>
		<link>http://blog.zabarauskas.com/eigenfaces-tutorial/</link>
		<comments>http://blog.zabarauskas.com/eigenfaces-tutorial/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 16:43:22 +0000</pubDate>
		<dc:creator>Manfredas Zabarauskas</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[eigenface]]></category>
		<category><![CDATA[eigenfaces]]></category>
		<category><![CDATA[face detection]]></category>
		<category><![CDATA[face recognition]]></category>
		<category><![CDATA[pca]]></category>
		<category><![CDATA[pentland]]></category>
		<category><![CDATA[turk]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.zabarauskas.com/?p=286</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p><i>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). </i></p>
<h3>Introduction</h3>
<p>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 <a href="http://en.wikipedia.org/wiki/Fourier_series" target="_blank">Fourier decomposition</a>. 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).</p>
<p>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.</p>
<h3>Demonstration</h3>
<p>To <a href="http://www.zabarauskas.com/downloads/Eigenfaces.zip">download</a> the software shown in video for 32-bit x86 platform, click <a href="http://www.zabarauskas.com/downloads/Eigenfaces.zip">here</a>. It was compiled using Microsoft Visual C++ 2008 and uses <a href="http://www.gnu.org/software/gsl/" target="_blank">GSL</a> for Windows.</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/YWRiF7FAuKE&#038;hl=en&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/YWRiF7FAuKE&#038;hl=en&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<h3>Establishing the Eigenface Basis</h3>
<p>First of all, we have to obtain a training set of <script type='math/tex'>M</script> grayscale face images  <script type='math/tex'>I_1, I_2, ..., I_M</script>. They should be:</p>
<ol>
<li> face-wise aligned, with eyes in the same level and faces of the same scale,</li>
<li> normalized so that every pixel has a value between 0 and 255 (i.e. one byte per pixel encoding), and</li>
<li>of the same <script type='math/tex'>N \times N</script> size.</li>
</ol>
<p>So just capturing everything formally, we want to obtain a set <script type='math/tex'>\{ I_1, I_2, ..., I_M \}</script>, where \begin{align} I_k = \begin{bmatrix} p_{1,1}^k &#038; p_{1,2}^k &#038; ... &#038; p_{1,N}^k \\ p_{2,1}^k &#038; p_{2,2}^k &#038; ... &#038; p_{2,N}^k \\ \vdots \\ p_{N,1}^k &#038; p_{N,2}^k &#038; ... &#038; p_{N,N}^k \end{bmatrix}_{N \times N} \end{align} and <script type='math/tex'>0 \leq p_{i,j}^k \leq 255.</script></center></p>
<p>Once we have that, we should change the representation of a face image <script type='math/tex'>I_k</script> from a <script type='math/tex'>N \times N</script> matrix, to a <script type='math/tex'>\Gamma_k</script> point in <script type='math/tex'>N^2</script>-dimensional space. Now here is how we do it: <span id="more-286"></span>we concatenate all the rows of the matrix <script type='math/tex'>I_k</script> into one big vector of dimension <script type='math/tex'>N^2</script>. Can it get any more simpler than that?</p>
<p>This is how it looks formally:</p>
<p><center><script type='math/tex'>\Gamma_k = \begin{bmatrix} p_{1,1}^k \\ p_{1,2}^k \\ \vdots \\ p_{1,N}^k \\ p_{2,1}^k \\ p_{2,2}^k \\ \vdots \\ p_{2,N}^k \\ \vdots \\ p_{N,1}^k \\ p_{N,2}^k \\ \vdots \\ p_{N,N}^k \end{bmatrix}_{N \times 1}</script>, where  <script type='math/tex'>k = 1, ..., M</script> and <script type='math/tex'>p_{i,j}^k \in I_k</script></center></p>
<p>Since we are much more interested in the characteristic features of those faces, let's subtract everything what is common between them, i.e. the <strong>average face</strong>.<br />
The average face of the previous mean-adjusted images can be defined as <script type='math/tex'>\Psi = {{1}\over{M}} \sum_{i=1}^{M} \Gamma_i</script>, then each face differs from the average by the vector <script type='math/tex'>\Phi_i = \Gamma_i - \Psi</script>.</p>
<p>Now we should attempt to find a set of orthonormal vectors which best describe the distribution of our data. The necessary steps in this at a first glance daunting task would seem to be:</p>
<ol>
<li>Obtain a <a href="http://en.wikipedia.org/wiki/Covariance_matrix" target="_blank">covariance matrix</a><br />
<script type='math/tex'>C = {{1}\over{M}} \sum_{i=1}^{M} \Phi_i \Phi_i^T = AA^T</script>, where <script type='math/tex'>A = \left[ \Phi_1 \Phi_2 ... \Phi_M \right]</script>.</li>
<li>Find the eigenvectors <script type='math/tex'>u_k</script> and eigenvalues <script type='math/tex'>\lambda_k</script> of <script type='math/tex'>C</script>.</li>
</ol>
<p>However, note two things here: <script type='math/tex'>A</script> is of the size <script type='math/tex'>N^2 \times M</script> and hence the matrix <script type='math/tex'>C</script> is of the size <script type='math/tex'>N^2 \times N^2</script>. To put things into perspective - if your image size is <script type='math/tex'>128 \times 128</script>, then the size of the matrix <script type='math/tex'>C</script> would be <script type='math/tex'>16384 \times 16384</script>. Determining eigenvectors and eigenvalues for a matrix this size would be an absolutely intractable task!</p>
<p>So how do we go about it? A simple mathematical trick: first let's calculate the inner product matrix <script type='math/tex'>L = A^T A</script>, of the size <script type='math/tex'>M \times M</script>. Then let's find it's eigenvectors <script type='math/tex'>v_i, i = 1, ..., M</script> of <script type='math/tex'>L</script> (of the <script type='math/tex'>M</script>-th dimension). Now observe, that if <script type='math/tex'>L v_i = \lambda_i v_i</script>, then</p>
<p><center>\begin{array} {rcl} A L v_i &#038;=&#038; \lambda_i A v_i \Rightarrow \\ A A^T A v_i &#038;=&#038; \lambda_i A v_i \Rightarrow \\ C A v_i &#038;=&#038; \lambda_i A v_i, \end{array}</center></p>
<p>and hence <script type='math/tex'>u_i = A v_i</script> and <script type='math/tex'>\lambda_i</script> are respectively the <script type='math/tex'>M</script> eigenvectors (of <script type='math/tex'>N^2</script>-th dimension) and eigenvalues of <script type='math/tex'>C</script>. Make sure to normalize <script type='math/tex'>u_i</script>, such that <script type='math/tex'>\left\| u_i \right\| = 1</script>.</p>
<p>We will call these eigenvectors <script type='math/tex'>u_i</script> the <strong>eigenfaces</strong>. Scale them to 255 and render on the screen, to see why.</p>
<p>It turns out that quite a few eigenfaces with the smallest eigenvalues can be discarded, so leave only the <script type='math/tex'>R \leq M</script> ones with the largest eigenvalues (i.e. only the ones making the greatest contribution to the variance of the original image set) and chuck them into the matrix <script type='math/tex'>U = \left[ u_1 u_2 ... u_R \right]_{N^2 \times R}</script></p>
<p>After you have done that - congratulations! We won't need anything else, but the matrix <script type='math/tex'>U</script> for the next steps - face detection and classification.</p>
<h3>Face Classification Using Eigenfaces</h3>
<p>Once the eigenfaces are created, a new face image <script type='math/tex'>\Gamma</script> can be transformed into it's eigenface components by a simple operation:</p>
<p><center><script type='math/tex'>\Omega = U^T (\Gamma - \Psi) =  \begin{bmatrix} \omega_1 \\ \omega_2 \\ \vdots \\ \omega_R \end{bmatrix}_{R \times 1}</script>.</center></p>
<p>The weights <script type='math/tex'>\omega_i \in \Omega</script> describe the contribution of each eigenface in representing the input face image. We can use this vector for <strong>face recognition</strong> by finding the smallest <a href="http://en.wikipedia.org/wiki/Euclidean_distance">Euclidean distance</a> <script type='math/tex'>\epsilon_{rec}</script> between the input face and training faces weight vectors, i.e. by calculating <script type='math/tex'>\epsilon_{rec} = min \left\| \Omega - \Omega_i \right\|</script>. If <script type='math/tex'>\epsilon_{rec} < \Theta_{rec}</script>, where <script type='math/tex'>\Theta_{rec}</script> is a treshold chosen heuristically, then we can say that the input image is recognized as the image with which it gives the lowest score.</p>
<p>The weights vector can also be used for an unknown <strong>face detection</strong>, exploiting the fact that the images of faces do not change radically when projected into the face space, while the projection of non-face images appear quite different. To do so, we can calculate the distance <script type='math/tex'>\epsilon_{det}</script> from the mean-adjusted input image <script type='math/tex'>\Phi = \Gamma - \Psi</script> and its projection onto face space <script type='math/tex'>\Phi_f = \sum_{i=1}^R \omega_i u_i </script>, i.e. <script type='math/tex'>\epsilon_{det} = \left\| \Phi - \Phi_f \right\|</script>. Again, if <script type='math/tex'>\epsilon_{det} < \Theta_{det}</script> for some treshold <script type='math/tex'>\Theta_{det}</script> (also obtained heuristically, for example, by observing <script type='math/tex'>\epsilon_{det}</script> for an input set consisting only of face images and a set of non-face images) we can conclude that the input image is a face.</p>
<h3>References</h3>
<p>1. Face Recognition Using Eigenfaces, Matthew A. Turk and Alex P. Pentland, MIT Vision and Modeling Lab, CVPR ‘91.<br />
2. Eigenfaces for Recognition, Matthew A. Turk and Alex P. Pentland, Journal of Cognitive Neuroscience ‘91.<br />
3. <a href="http://www.scholarpedia.org/article/Eigenfaces" target="_blank">Eigenfaces</a>. Sheng Zhang and Matthew Turk (2008), Scholarpedia, 3(9):4244. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zabarauskas.com/eigenfaces-tutorial/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>

<!-- www.000webhost.com Analytics Code -->
<script type="text/javascript" src="http://analytics.hosting24.com/count.php"></script>
<noscript><a href="http://www.hosting24.com/"><img src="http://analytics.hosting24.com/count.php" alt="web hosting" /></a></noscript>
<!-- End Of Analytics Code -->

