Package pyvision :: Package tools :: Module face_scan
[hide private]
[frames] | no frames]

Source Code for Module pyvision.tools.face_scan

  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  ''' 
 35  This tool scans a directory for image files and detects faces and eyes in those  
 36  images.  A CSV file is generated that has each face detection and ASEF eye  
 37  coordinates for each face detection. 
 38  ''' 
 39   
 40   
 41  import optparse 
 42  import csv 
 43  import os 
 44  import pyvision as pv 
 45  from pyvision.face.CascadeDetector import CascadeDetector 
 46  from pyvision.face.FilterEyeLocator import FilterEyeLocator 
 47  import PIL 
 48  import random 
 49   
 50  EXTENSIONS = ["PGM","PPM","BMP","JPG","JPEG","GIF","PNG","TIF","TIFF"] 
 51   
52 -def parseOptions():
53 usage = "usage: %prog [options] <image_directory> <output.csv>" 54 parser = optparse.OptionParser(usage) 55 parser.add_option("--rotate", dest="rotate",default=False, 56 action="store_true", 57 help="Used to detection faces in images where the camera was turn while taking the photo. Tests all four rotations.") 58 parser.add_option("--scale", dest="scale",default=1.0,type='float', 59 help="Rescale the image before detection to improve performance.") 60 parser.add_option("--extension", dest="extension",default=None, 61 help="Attempt to process images with this extension.") 62 parser.add_option("--log", dest="log_dir",default=None, 63 help="Create a directory containing annotated images.") 64 parser.add_option("--log-scale", dest="log_scale",default=1.0,type='float', 65 help="Rescale images before they are logged.") 66 parser.add_option("--sample", dest="sample",default=None,type='int', 67 help="Randomly sample n images to process.") 68 parser.add_option("-v", "--verbose", 69 action="store_true", dest="verbose", 70 help="Turn on more verbose output.") 71 (options, args) = parser.parse_args() 72 if len(args) != 2: 73 parser.error("This program requires two arguments: a directory containing images and the name of a file to use for output.") 74 75 return options, args
76 77
78 -def processFaces(im,face_detect,locate_eyes):
79 80 # Run face detection 81 faces = face_detect(im) 82 return locate_eyes(im,faces)
83 #results = [] 84 #i = 0 85 #for face in faces: 86 # Run eye detection 87 # affine = pv.AffineFromRect(face, (128, 128)) 88 # face_im = affine.transformImage(im) 89 # cv_im = face_im.asOpenCVBW() 90 # eye1, eye2, corr1, corr2 = locate_eyes.locateEyes(cv_im) 91 # eye1, eye2 = affine.invertPoints([pv.Point(eye1), pv.Point(eye2)]) 92 # results.append([face,eye1,eye2]) 93 # i += 1 94 # 95 #return results 96 97 if __name__ == "__main__": 98 # Read in program arguments and options. 99 options, args = parseOptions() 100 101 #locator_filename = os.path.join(csu.__path__[0],'data','EyeLocatorASEF128x128.fel') 102 103 # Scan the directory for image files. 104 image_names = [] 105 for dirpath, dirnames, filenames in os.walk(args[0]): 106 for filename in filenames: 107 extension = filename.split('.')[-1] 108 extension = extension.upper() 109 110 if (options.extension==None and extension in EXTENSIONS) or (options.extension != None and options.extension.upper() == extension): 111 pathname = os.path.join(dirpath,filename) 112 image_names.append(pathname) 113 114 # If an integer is passed to the sample option then subselect the image names. 115 if options.sample != None: 116 image_names = random.sample(image_names,options.sample) 117 118 119 # Open the file to use as output. 120 f = open(args[1],'wb') 121 csv_file = csv.writer(f) 122 headers = ['image_name','detect_number','detect_x','detect_y','detect_width','detect_height','eye1_x','eye1_y','eye2_x','eye2_y'] 123 csv_file.writerow(headers) 124 125 # Create an image log if this is being saved to a file. 126 ilog = None 127 if options.log_dir != None: 128 print "Creating Image Log..." 129 ilog = pv.ImageLog(options.log_dir) 130 131 # For each image run face and eye detection 132 face_detect = CascadeDetector(image_scale=1.3*options.scale) 133 locate_eyes = FilterEyeLocator()#locator_filename) 134 135 c = 0 136 for pathname in image_names: 137 c += 1 138 139 im = pv.Image(pathname) 140 141 scale = options.log_scale 142 log_im = pv.AffineScale(scale,(int(scale*im.width),int(scale*im.height))).transformImage(im) 143 144 145 146 results = processFaces(im,face_detect,locate_eyes) 147 148 if options.rotate: 149 150 rot_image = pv.Image(im.asPIL().transpose(PIL.Image.ROTATE_90)) 151 more_results = processFaces(rot_image,face_detect,locate_eyes) 152 for face,eye1,eye2 in more_results: 153 results.append([pv.Rect(im.width-face.y-face.h, face.x, face.h, face.w), 154 pv.Point(im.width-eye1.Y(),eye1.X()), 155 pv.Point(im.width-eye2.Y(),eye2.X())]) 156 157 rot_image = pv.Image(im.asPIL().transpose(PIL.Image.ROTATE_180)) 158 more_results = processFaces(rot_image,face_detect,locate_eyes) 159 for face,eye1,eye2 in more_results: 160 results.append([pv.Rect(im.width - face.x - face.w, im.height-face.y-face.h, face.w, face.h), 161 pv.Point(im.width-eye1.X(),im.height-eye1.Y()), 162 pv.Point(im.width-eye2.X(),im.height-eye2.Y())]) 163 164 rot_image = pv.Image(im.asPIL().transpose(PIL.Image.ROTATE_270)) 165 more_results = processFaces(rot_image,face_detect,locate_eyes) 166 for face,eye1,eye2 in more_results: 167 results.append([pv.Rect(face.y, im.height-face.x-face.w, face.h, face.w), 168 pv.Point(eye1.Y(),im.height-eye1.X()), 169 pv.Point(eye2.Y(),im.height-eye2.X())]) 170 171 172 n_faces = 0 173 for face,eye1,eye2 in results: 174 csv_file.writerow([pathname,n_faces,face.x,face.y,face.w,face.h,eye1.X(),eye1.Y(),eye2.X(),eye2.Y()]) 175 if ilog != None: 176 log_im.annotateRect(scale*face) 177 log_im.annotatePoint(scale*eye1) 178 log_im.annotatePoint(scale*eye2) 179 n_faces += 1 180 181 #else: 182 # csv_file.writerow([pathname,"NA","NA","NA","NA","NA","NA","NA","NA","NA"]) 183 184 print "Processed %5d of %d: [%2d faces] %s "%(c,len(image_names),n_faces,pathname) 185 186 if ilog != None: 187 basename = os.path.basename(pathname) 188 basename = basename.split('.')[0] 189 ilog.log(log_im,label=basename) 190 191 if ilog != None: 192 ilog.show() 193