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 import time
36 import math
37
38 import pyvision as pv
39 from pyvision.analysis.FaceAnalysis.FaceDetectionTest import face_from_eyes,is_success
40
42 '''
43 BUGFIX: 20080813 Bailey Draper found a bug that the field dl in the full
44 report was really dl^2.
45 '''
46 - def __init__(self,name=None,threshold=0.25, test_detect=True):
47 ''''''
48 self.name = name
49 self.table = pv.Table()
50 self.summary_table = pv.Table()
51 self.face_successes = 0
52 self.both25_successes = 0
53 self.left25_successes = 0
54 self.right25_successes = 0
55 self.both10_successes = 0
56 self.left10_successes = 0
57 self.right10_successes = 0
58 self.both05_successes = 0
59 self.left05_successes = 0
60 self.right05_successes = 0
61 self.bothsse = 0.0
62 self.rightsse = 0.0
63 self.leftsse = 0.0
64 self.pixels = 0
65 self.images = 0
66 self.faces = 0
67 self.start_time = time.time()
68 self.stop_time = None
69 self.test_detect = test_detect
70 self.sample_id = 0
71
72 - def addSample(self, truth_eyes, detected_eyes, im=None, annotate=False):
73 ''''''
74 self.images += 1
75
76 if isinstance(im,pv.Image):
77 name = im.filename
78 if self.pixels != None:
79 self.pixels += im.asPIL().size[0] * im.asPIL().size[1]
80 elif isinstance(im,str):
81 name = im
82 self.pixels = None
83 else:
84 name = "%d"%self.sample_id
85 self.pixels = None
86 self.sample_id += 1
87
88 self.stop_time = time.time()
89
90 for tl,tr in truth_eyes:
91 tface = face_from_eyes(tl,tr)
92
93 detect_face = False
94 eye_dist = None
95 detect_b25 = False
96 detect_b10 = False
97 detect_b05 = False
98 detect_l25 = False
99 detect_l10 = False
100 detect_l05 = False
101 detect_r25 = False
102 detect_r10 = False
103 detect_r05 = False
104 eye_dist = None
105 tl_x = None
106 tl_y = None
107 tr_x = None
108 tr_y = None
109 pl_x = None
110 pl_y = None
111 pr_x = None
112 pr_y = None
113 dlx = None
114 dly = None
115 dl2 = None
116 dl = None
117 dlfrac= None
118 drx = None
119 dry = None
120 dr2 = None
121 dr = None
122 drfrac= None
123 deye = None
124 dmean = None
125
126 for pl,pr in detected_eyes:
127 dface = face_from_eyes(pl,pr)
128
129 if not self.test_detect or is_success(tface,dface):
130 tl_x = tl.X()
131 tl_y = tl.Y()
132 tr_x = tr.X()
133 tr_y = tr.Y()
134 eye_dist = math.sqrt((tl_x-tr_x)*(tl_x-tr_x) + (tl_y-tr_y)*(tl_y-tr_y))
135 pl_x = pl.X()
136 pl_y = pl.Y()
137 pr_x = pr.X()
138 pr_y = pr.Y()
139
140 detect_face = True
141
142 eye_dist = math.sqrt((tl_x-tr_x)*(tl_x-tr_x) + (tl_y-tr_y)*(tl_y-tr_y))
143
144 dlx = pl_x-tl_x
145 dly = pl_y-tl_y
146 dl2 = dlx*dlx + dly*dly
147 dl = math.sqrt(dl2)
148 dlfrac = dl/eye_dist
149
150 drx = pr_x-tr_x
151 dry = pr_y-tr_y
152 dr2 = drx*drx + dry*dry
153 dr = math.sqrt(dr2)
154 drfrac = dr/eye_dist
155
156 deye = max(drfrac,dlfrac)
157
158 dmean = 0.5*(dr+dl)
159
160 detect_l25 = 0.25 > dlfrac
161 detect_l10 = 0.10 > dlfrac
162 detect_l05 = 0.05 > dlfrac
163 detect_r25 = 0.25 > drfrac
164 detect_r10 = 0.10 > drfrac
165 detect_r05 = 0.05 > drfrac
166 detect_b25 = 0.25 > deye
167 detect_b10 = 0.10 > deye
168 detect_b05 = 0.05 > deye
169
170 break
171
172 self.table.setElement(self.faces,'name',name)
173 self.table.setElement(self.faces,'detect_face',detect_face)
174 self.table.setElement(self.faces,'detect_l25',detect_l25)
175 self.table.setElement(self.faces,'detect_l10',detect_l10)
176 self.table.setElement(self.faces,'detect_l05',detect_l05)
177 self.table.setElement(self.faces,'detect_r25',detect_r25)
178 self.table.setElement(self.faces,'detect_r10',detect_r10)
179 self.table.setElement(self.faces,'detect_r05',detect_r05)
180 self.table.setElement(self.faces,'detect_b25',detect_b25)
181 self.table.setElement(self.faces,'detect_b10',detect_b10)
182 self.table.setElement(self.faces,'detect_b05',detect_b05)
183 self.table.setElement(self.faces,'eye_dist',eye_dist)
184
185 self.table.setElement(self.faces,'truth_lx',tl_x)
186 self.table.setElement(self.faces,'truth_ly',tl_y)
187 self.table.setElement(self.faces,'truth_rx',tr_x)
188 self.table.setElement(self.faces,'truth_ry',tr_y)
189
190 self.table.setElement(self.faces,'pred_lx',pl_x)
191 self.table.setElement(self.faces,'pred_ly',pl_y)
192 self.table.setElement(self.faces,'pred_rx',pr_x)
193 self.table.setElement(self.faces,'pred_ry',pr_y)
194
195 self.table.setElement(self.faces,'dlx',dlx)
196 self.table.setElement(self.faces,'dly',dly)
197
198 self.table.setElement(self.faces,'dl',dl)
199 self.table.setElement(self.faces,'dlfrac',dlfrac)
200 self.table.setElement(self.faces,'drx',drx)
201 self.table.setElement(self.faces,'dry',dry)
202
203 self.table.setElement(self.faces,'dr',dr)
204 self.table.setElement(self.faces,'drfrac',drfrac)
205 self.table.setElement(self.faces,'deye',deye)
206 self.table.setElement(self.faces,'dmean',dmean)
207
208 self.faces += 1
209 if dlfrac != None:
210 self.bothsse += dlfrac**2 + drfrac**2
211 self.leftsse += dlfrac**2
212 self.rightsse += drfrac**2
213
214 if detect_face: self.face_successes += 1
215 if detect_b25: self.both25_successes += 1
216 if detect_l25: self.left25_successes += 1
217 if detect_r25: self.right25_successes += 1
218 if detect_b10: self.both10_successes += 1
219 if detect_l10: self.left10_successes += 1
220 if detect_r10: self.right10_successes += 1
221 if detect_b05: self.both05_successes += 1
222 if detect_l05: self.left05_successes += 1
223 if detect_r05: self.right05_successes += 1
224
225
227 self.face_rate = float(self.face_successes)/self.faces
228 self.face_ci = pv.cibinom(self.faces,self.face_successes,alpha=0.05)
229 self.both25_rate = float(self.both25_successes)/self.faces
230 self.both25_ci = pv.cibinom(self.faces,self.both25_successes,alpha=0.05)
231 self.both10_rate = float(self.both10_successes)/self.faces
232 self.both10_ci = pv.cibinom(self.faces,self.both10_successes,alpha=0.05)
233 self.both05_rate = float(self.both05_successes)/self.faces
234 self.both05_ci = pv.cibinom(self.faces,self.both05_successes,alpha=0.05)
235 self.left25_rate = float(self.left25_successes)/self.faces
236 self.left25_ci = pv.cibinom(self.faces,self.left25_successes,alpha=0.05)
237 self.left10_rate = float(self.left10_successes)/self.faces
238 self.left10_ci = pv.cibinom(self.faces,self.left10_successes,alpha=0.05)
239 self.left05_rate = float(self.left05_successes)/self.faces
240 self.left05_ci = pv.cibinom(self.faces,self.left05_successes,alpha=0.05)
241 self.right25_rate = float(self.right25_successes)/self.faces
242 self.right25_ci = pv.cibinom(self.faces,self.right25_successes,alpha=0.05)
243 self.right10_rate = float(self.right10_successes)/self.faces
244 self.right10_ci = pv.cibinom(self.faces,self.right10_successes,alpha=0.05)
245 self.right05_rate = float(self.right05_successes)/self.faces
246 self.right05_ci = pv.cibinom(self.faces,self.right05_successes,alpha=0.05)
247 if self.face_successes > 0:
248 self.bothrmse = math.sqrt(self.bothsse/(2*self.face_successes))
249 self.leftrmse = math.sqrt(self.leftsse/self.face_successes)
250 self.rightrmse = math.sqrt(self.rightsse/self.face_successes)
251 self.elapse_time = self.stop_time - self.start_time
252 self.time_per_image = self.elapse_time / self.images
253 self.time_per_face = self.elapse_time / self.faces
254
255
256
258 ''''''
259 self.finish()
260 self.summary_table.setElement('FaceRate','Estimate',self.face_rate)
261 self.summary_table.setElement('FaceRate','Lower95',self.face_ci[0])
262 self.summary_table.setElement('FaceRate','Upper95',self.face_ci[1])
263 self.summary_table.setElement('Both25Rate','Estimate',self.both25_rate)
264 self.summary_table.setElement('Both25Rate','Lower95',self.both25_ci[0])
265 self.summary_table.setElement('Both25Rate','Upper95',self.both25_ci[1])
266 self.summary_table.setElement('Both10Rate','Estimate',self.both10_rate)
267 self.summary_table.setElement('Both10Rate','Lower95',self.both10_ci[0])
268 self.summary_table.setElement('Both10Rate','Upper95',self.both10_ci[1])
269 self.summary_table.setElement('Both05Rate','Estimate',self.both05_rate)
270 self.summary_table.setElement('Both05Rate','Lower95',self.both05_ci[0])
271 self.summary_table.setElement('Both05Rate','Upper95',self.both05_ci[1])
272 self.summary_table.setElement('BothRMSE','Estimate',self.bothrmse)
273 self.summary_table.setElement('Left25Rate','Estimate',self.left25_rate)
274 self.summary_table.setElement('Left25Rate','Lower95',self.left25_ci[0])
275 self.summary_table.setElement('Left25Rate','Upper95',self.left25_ci[1])
276 self.summary_table.setElement('Left10Rate','Estimate',self.left10_rate)
277 self.summary_table.setElement('Left10Rate','Lower95',self.left10_ci[0])
278 self.summary_table.setElement('Left10Rate','Upper95',self.left10_ci[1])
279 self.summary_table.setElement('Left05Rate','Estimate',self.left05_rate)
280 self.summary_table.setElement('Left05Rate','Lower95',self.left05_ci[0])
281 self.summary_table.setElement('Left05Rate','Upper95',self.left05_ci[1])
282 self.summary_table.setElement('LeftRMSE','Estimate',self.leftrmse)
283 self.summary_table.setElement('Right25Rate','Estimate',self.right25_rate)
284 self.summary_table.setElement('Right25Rate','Lower95',self.right25_ci[0])
285 self.summary_table.setElement('Right25Rate','Upper95',self.right25_ci[1])
286 self.summary_table.setElement('Right10Rate','Estimate',self.right10_rate)
287 self.summary_table.setElement('Right10Rate','Lower95',self.right10_ci[0])
288 self.summary_table.setElement('Right10Rate','Upper95',self.right10_ci[1])
289 self.summary_table.setElement('Right05Rate','Estimate',self.right05_rate)
290 self.summary_table.setElement('Right05Rate','Lower95',self.right05_ci[0])
291 self.summary_table.setElement('Right05Rate','Upper95',self.right05_ci[1])
292 self.summary_table.setElement('RightRMSE','Estimate',self.rightrmse)
293 self.summary_table.setElement('ElapsedTime','Estimate',self.elapse_time)
294 self.summary_table.setElement('ImageTime','Estimate',self.time_per_image)
295 self.summary_table.setElement('FaceTime','Estimate',self.time_per_face)
296 self.summary_table.setElement('ImageCount','Estimate',self.images)
297 self.summary_table.setElement('FaceCount','Estimate',self.faces)
298 return self.summary_table
299
302
304 ''' One line summary of the test '''
305 self.finish()
306 return "EyeDetectionTest(name:%s,FaceRate:%0.4f,Both10Rate:%0.4f,Left10Rate:%0.4f,Right10Rate:%0.4f,BothRMSE:%0.4f,NFaces:%d,Time:%0.2f)"%(self.name,self.face_rate,self.both10_rate,self.left10_rate,self.right10_rate,self.bothrmse,self.faces,self.elapse_time)
307
308
310 '''
311 Create a summary table for a list containing FaceDetectionTest objects.
312 '''
313 print 'Creating summaries...'
314 summary25 = pv.Table()
315 summary25.setColumnFormat('Face_Rate','%0.4f')
316 summary25.setColumnFormat('Rate_25','%0.4f')
317 summary25.setColumnFormat('Lower95_25','%0.4f')
318 summary25.setColumnFormat('Upper95_25','%0.4f')
319 summary25.setColumnFormat('Time','%0.2f')
320 for test in tests:
321 print test.name
322 summary25.setElement(test.name,'Face_Rate',test.face_rate)
323 summary25.setElement(test.name,'Rate_25',test.both25_rate)
324 summary25.setElement(test.name,'Lower95_25',test.both25_ci[0])
325 summary25.setElement(test.name,'Upper95_25',test.both25_ci[1])
326 summary25.setElement(test.name,'Time',test.elapse_time)
327
328
329 summary10 = pv.Table()
330 summary10.setColumnFormat('Face_Rate','%0.4f')
331 summary10.setColumnFormat('Rate_10','%0.4f')
332 summary10.setColumnFormat('Lower95_10','%0.4f')
333 summary10.setColumnFormat('Upper95_10','%0.4f')
334 summary10.setColumnFormat('Time','%0.2f')
335 for test in tests:
336 summary10.setElement(test.name,'Face_Rate',test.face_rate)
337 summary10.setElement(test.name,'Rate_10',test.both10_rate)
338 summary10.setElement(test.name,'Lower95_10',test.both10_ci[0])
339 summary10.setElement(test.name,'Upper95_10',test.both10_ci[1])
340 summary10.setElement(test.name,'Time',test.elapse_time)
341
342
343 summary05 = pv.Table()
344 summary05.setColumnFormat('Face_Rate','%0.4f')
345 summary05.setColumnFormat('Rate_05','%0.4f')
346 summary05.setColumnFormat('Lower95_05','%0.4f')
347 summary05.setColumnFormat('Upper95_05','%0.4f')
348 summary05.setColumnFormat('Time','%0.2f')
349 for test in tests:
350 summary05.setElement(test.name,'Face_Rate',test.face_rate)
351 summary05.setElement(test.name,'Rate_05',test.both05_rate)
352 summary05.setElement(test.name,'Lower95_05',test.both05_ci[0])
353 summary05.setElement(test.name,'Upper95_05',test.both05_ci[1])
354 summary05.setElement(test.name,'Time',test.elapse_time)
355
356 return summary05,summary10,summary25
357