1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23   
 24   
 25   
 26   
 27   
 28   
 29   
 30   
 31   
 32   
 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   
 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   
 79       
 80       
 81      faces = face_detect(im) 
 82      return locate_eyes(im,faces) 
  83       
 84       
 85       
 86       
 87       
 88       
 89       
 90       
 91       
 92       
 93       
 94       
 95       
 96   
 97  if __name__ == "__main__": 
 98       
 99      options, args = parseOptions() 
100       
101       
102       
103       
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       
115      if options.sample != None: 
116          image_names = random.sample(image_names,options.sample) 
117       
118       
119       
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       
126      ilog = None 
127      if options.log_dir != None: 
128          print "Creating Image Log..." 
129          ilog = pv.ImageLog(options.log_dir) 
130       
131       
132      face_detect = CascadeDetector(image_scale=1.3*options.scale) 
133      locate_eyes = FilterEyeLocator() 
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           
182           
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