Package pyvision :: Package face :: Module PCA
[hide private]
[frames] | no frames]

Source Code for Module pyvision.face.PCA

  1  # PyVision License 
  2  # 
  3  # Copyright (c) 2006-2008 David S. Bolme 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  #  
 10  # 1. Redistributions of source code must retain the above copyright 
 11  # notice, this list of conditions and the following disclaimer. 
 12  #  
 13  # 2. Redistributions in binary form must reproduce the above copyright 
 14  # notice, this list of conditions and the following disclaimer in the 
 15  # documentation and/or other materials provided with the distribution. 
 16  #  
 17  # 3. Neither name of copyright holders nor the names of its contributors 
 18  # may be used to endorse or promote products derived from this software 
 19  # without specific prior written permission. 
 20  #  
 21  #  
 22  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 23  # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 24  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 25  # A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR 
 26  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 27  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 28  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 29  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 30  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 31  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 32  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 33   
 34  #import os.path 
 35  #from PIL.Image import ANTIALIAS 
 36  #import scipy as sp 
 37  import numpy as np 
 38  import os 
 39  import unittest 
 40  #from scipy.signal import fft2 
 41   
 42  from pyvision.face.FaceRecognizer import FaceRecognizer 
 43  from pyvision.analysis.FaceAnalysis import FaceRecognitionTest 
 44  import pyvision.vector.PCA 
 45  #from pyvision.other.normalize import * 
 46  #from pyvision.types.img import Image 
 47  #from pyvision.types.Point import Point 
 48  from pyvision.analysis.face import EyesFile 
 49  #from pyvision.analysis.roc import * 
 50  #from pyvision.types.Affine import * 
 51   
 52  import pyvision as pv 
 53   
 54  PCA_L1      = 1 
 55  PCA_L2      = 2 
 56  PCA_COS     = 3 
 57   
 58  PCA_NO_NORM   = 1 
 59  PCA_MEAN_STD_NORM  = 2 
 60  PCA_MEAN_UNIT_NORM = 3 
 61  PCA_UNIT_NORM = 4 
 62   
63 -class PCA(FaceRecognizer):
64 ''' This is a basic implementation of PCA''' 65
66 - def __init__(self, face_size=(128,128), left_eye=pv.Point(32,52), right_eye=pv.Point(96,52), normalize=PCA_MEAN_STD_NORM, measure=PCA_COS, whiten=True, drop_front=2, basis_vectors=100):
67 '''Crate a PCA classifier''' 68 FaceRecognizer.__init__(self) 69 70 self.face_size = face_size 71 self.pca = pyvision.vector.PCA.PCA() 72 self.norm = normalize 73 self.trained = False 74 75 self.whiten = whiten 76 self.drop_front = drop_front 77 self.basis_vectors = basis_vectors 78 self.measure = measure 79 self.left_eye = left_eye 80 self.right_eye = right_eye
81
82 - def cropFace(self,im,eyes):
83 left,right = eyes 84 affine = pv.AffineFromPoints(left,right,self.left_eye,self.right_eye,self.face_size) 85 im = affine.transformImage(im) 86 return im
87 88 #def addTraining(self,img,rect=None,eyes=None): 89 # ''' ''' 90 # assert not self.trained 91 # 92 # img = self.cropFace(img,eyes) 93 # vec = self.computeVector(img) 94 # self.pca.addFeature(vec) 95
96 - def computeFaceRecord(self,img,rect=None,eyes=None):
97 '''Given an image and face detection box, compute a face identification record''' 98 assert self.trained 99 100 img = self.cropFace(img,eyes) 101 vec = self.computeVector(img) 102 fir = self.pca.project(vec,whiten=True) 103 if self.measure == PCA_COS: 104 scale = np.sqrt((fir*fir).sum()) 105 fir = (1.0/scale)*fir 106 return fir
107
108 - def computeVector(self,img):
109 '''Creates a vector from a face''' 110 #face = img.asPIL().crop(rect.box()).resize(self.face_size,ANTIALIAS) 111 vec = img.asMatrix2D().flatten() 112 113 if self.norm == PCA_MEAN_STD_NORM: 114 vec = pv.meanStd(vec) 115 if self.norm == PCA_MEAN_UNIT_NORM: 116 vec = pv.meanUnit(vec) 117 if self.norm == PCA_UNIT_NORM: 118 vec = pv.unit(vec) 119 120 return vec
121
122 - def train(self):
123 '''Train the PCA classifier''' 124 assert self.trained == False 125 126 for img,_,eyes,_ in self.training_data: 127 img = self.cropFace(img,eyes) 128 vec = self.computeVector(img) 129 self.pca.addFeature(vec) 130 131 self.pca.train( drop_front=self.drop_front, number=self.basis_vectors) 132 133 self.trained = True
134 135
136 - def similarity(self,fir1,fir2):
137 '''Compute the similarity of two faces''' 138 assert self.trained == True 139 140 if self.measure == PCA_L1: 141 return (np.abs(fir1-fir2)).sum() 142 143 if self.measure == PCA_L2: 144 return np.sqrt(((fir1-fir2)*(fir1-fir2)).sum()) 145 146 if self.measure == PCA_COS: 147 return (fir1*fir2).sum() 148 149 raise NotImplementedError("Unknown distance measure: %d"%self.measure)
150 151
152 - def getBasis(self):
153 basis = self.pca.getBasis() 154 images = [] 155 156 print basis.shape 157 r,_ = basis.shape 158 for i in range(r): 159 im = basis[i,:] 160 im = im.reshape(self.face_size) 161 im = pv.Image(im) 162 images.append(im) 163 print len(images) 164 return images
165 166 167 168 SCRAPS_FACE_DATA = os.path.join(pyvision.__path__[0],"data","csuScrapShots") 169 170 PCA_SIZE = (64,64) 171
172 -class _TestFacePCA(unittest.TestCase):
173
174 - def setUp(self):
175 self.images = [] 176 self.names = [] 177 178 self.eyes = EyesFile(os.path.join(SCRAPS_FACE_DATA,"coords.txt")) 179 for filename in self.eyes.files(): 180 img = pv.Image(os.path.join(SCRAPS_FACE_DATA, filename + ".pgm")) 181 self.images.append(img) 182 self.names.append(filename) 183 184 self.assert_( len(self.images) == 173 )
185 186
187 - def test_pca_scraps(self):
188 face_test = FaceRecognitionTest.FaceRecognitionTest(name='PCA_CSUScraps',score_type=FaceRecognitionTest.SCORE_TYPE_HIGH) 189 pca = PCA(drop_front=2,basis_vectors=55) 190 191 for im_name in self.eyes.files(): 192 im = pv.Image(os.path.join(SCRAPS_FACE_DATA, im_name + ".pgm")) 193 rect = self.eyes.getFaces(im_name) 194 eyes = self.eyes.getEyes(im_name) 195 pca.addTraining(im,rect=rect[0],eyes=eyes[0]) 196 197 pca.train() 198 199 face_records = {} 200 for im_name in self.eyes.files(): 201 im = pv.Image(os.path.join(SCRAPS_FACE_DATA, im_name + ".pgm")) 202 rect = self.eyes.getFaces(im_name) 203 eyes = self.eyes.getEyes(im_name) 204 fr = pca.computeFaceRecord(im,rect=rect[0],eyes=eyes[0]) 205 face_records[im_name] = fr 206 207 for i_name in face_records.keys(): 208 scores = [] 209 for j_name in face_records.keys(): 210 similarity = pca.similarity(face_records[i_name],face_records[j_name]) 211 scores.append((j_name,similarity)) 212 face_test.addSample(i_name,scores) 213 214 #print face_test.rank1_bounds 215 self.assertAlmostEqual(face_test.rank1_rate,0.43930635838150289) 216 self.assertAlmostEqual(face_test.rank1_bounds[0],0.3640772723094895) 217 self.assertAlmostEqual(face_test.rank1_bounds[1],0.51665118592791259) 218 219 roc = face_test.getROCAnalysis() 220 221 # Test based of fpr=0.01 222 _ = roc.getFAR(far=0.01)
223 #TODO: does not work... 224 #self.assertAlmostEqual(1.0-roc_point.frr,0.16481069042316257) 225 226 # Test the equal error rate 227 #fp,tp,th = roc.findEqualError() 228 #self.assertAlmostEqual(tp,0.68819599109131402) 229