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