-
Notifications
You must be signed in to change notification settings - Fork 0
/
faces.py
232 lines (181 loc) · 7.04 KB
/
faces.py
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
import os
import fnmatch
from os.path import join
import Image
import numpy
import sys
sys.path.append("c_faces")
try:
import c_faces
except ImportError:
c_faces = None
def integrate_image(table):
"""Creates integral image/summed area table in place."""
for c in xrange(table.shape[1]):
for r in xrange(table.shape[0]):
accum = 0
if r > 0:
table[r, c] += table[r-1, c]
if c > 0:
table[r, c] += table[r, c-1]
if r > 0 and c > 0:
table[r, c] -= table[r-1, c-1]
class IntegratedImage(object):
"""Provides Python Imaging Library style coordinates for the image
backed by a numpy array.
"""
def __init__(self, table):
self.table = table
def __getitem__(self, coord):
assert(coord[0] >= 0)
assert(coord[1] >= 0)
if coord[0] == 0 or coord[1] == 0:
return 0
return self.table[coord[0] - 1, coord[1] - 1]
def __repr__(self):
return repr(self.table)
@property
def shape(self):
return self.table.shape
def mid_top(start, end):
assert (end[1] - start[1]) % 2 == 0
return (start[0], start[1] + ((end[1] - start[1]) / 2))
def mid_bot(start, end):
assert (end[1] - start[1]) % 2 == 0
return (end[0], start[1] + ((end[1] - start[1]) / 2))
def left_bot(start, end):
return (end[0], start[1])
def right_top(start, end):
return (start[0], end[1])
def left_mid(start, end):
assert (end[0] - start[0]) % 2 == 0
return (start[0] + ((end[0] - start[0]) / 2), start[1])
def right_mid(start, end):
assert (end[0] - start[0]) % 2 == 0
return (start[0] + ((end[0] - start[0]) / 2), end[1])
def first_third_top(start, end):
assert (end[1] - start[1]) % 3 == 0
return (start[0], start[1] + ((end[1] - start[1]) / 3))
def second_third_top(start, end):
assert (end[1] - start[1]) % 3 == 0
return (start[0], start[1] + (2 * (end[1] - start[1]) / 3))
def first_third_bot(start, end):
assert (end[1] - start[1]) % 3 == 0
return (end[0], start[1] + ((end[1] - start[1]) / 3))
def second_third_bot(start, end):
assert (end[1] - start[1]) % 3 == 0
return (end[0], start[1] + (2 * (end[1] - start[1]) / 3))
def mid_mid(start, end):
assert (end[0] - start[0]) % 2 == 0
assert (end[1] - start[1]) % 2 == 0
return (start[0] + ((end[0] - start[0]) / 2), start[1] + ((end[1] - start[1]) / 2))
def feature_a(img, start, end):
assert(start[0] < end[0])
assert(start[1] + 1 < end[1])
return (-img[start]
+ 2 * img[mid_top(start, end)]
- img[right_top(start, end)]
+ img[left_bot(start, end)]
- 2 * img[mid_bot(start, end)]
+ img[end])
def feature_b(img, start, end):
assert(start[0] + 1 < end[0])
assert(start[1] < end[1])
return (img[start]
- img[right_top(start, end)]
- 2 * img[left_mid(start, end)]
+ 2 * img[right_mid(start, end)]
+ img[left_bot(start, end)]
- img[end])
def feature_c(img, start, end):
assert(start[0] < end[0])
assert(start[1] + 2 < end[1])
return (-img[start]
+ 2 * img[first_third_top(start, end)]
- 2 * img[second_third_top(start, end)]
+ img[right_top(start, end)]
+ img[left_bot(start, end)]
- 2 * img[first_third_bot(start, end)]
+ 2 * img[second_third_bot(start, end)]
- img[end])
def feature_d(img, start, end):
assert(start[0] + 1 < end[0])
assert(start[1] + 1 < end[1])
return (-img[start]
+ 2 * img[mid_top(start, end)]
- img[right_top(start, end)]
+ 2 * img[left_mid(start, end)]
- 4 * img[mid_mid(start, end)]
+ 2 * img[right_mid(start, end)]
- img[left_bot(start, end)]
+ 2 * img[mid_bot(start, end)]
- img[end])
def all_windows(start, end):
for start_row in xrange(start[0], end[0]):
for start_col in xrange(start[1], end[1]):
for end_row in xrange(start_row + 1, end[0] + 1):
for end_col in xrange(start_col + 1, end[1] + 1):
yield ((start_row, start_col), (end_row, end_col))
def all_feature_descriptors(all_start, all_end):
for start, end in all_windows(all_start, all_end):
if (end[1] - start[1]) % 2 == 0:
yield (0, start, end)
if (end[0] - start[0]) % 2 == 0:
yield (1, start, end)
if (end[1] - start[1]) % 3 == 0:
yield (2, start, end)
if (end[0] - start[0]) % 2 == 0 and (end[1] - start[1]) % 2 == 0:
yield (3, start, end)
def list_feature_descriptors(shape):
return list(all_feature_descriptors((0,0), shape))
feature_func_tuple = (feature_a, feature_b, feature_c, feature_d)
def select_feature(feature_idx, start, end, int_img):
return feature_func_tuple[feature_idx](int_img, start, end)
class LazyFeatureVec(object):
def __init__(self, int_img, feature_descriptors, c_backend):
self.int_img = int_img
self.feature_descriptors = feature_descriptors
self.c_backend = c_backend
def __getitem__(self, idx):
if isinstance(idx, slice):
return [select_feature(feature_func_idx, start, end, self.int_img)
for feature_func_idx, start, end in self.feature_descriptors[idx]]
feature_func_idx, start, end = self.feature_descriptors[idx]
if self.c_backend:
return c_faces.lazy_get_feature(feature_func_idx, start, end, self.int_img.table)
else:
return select_feature(feature_func_idx, start, end, self.int_img)
def __len__(self):
return len(self.feature_descriptors)
class Datum(object):
def __init__(self, img_path, label, features_vec):
assert label == 1 or label == -1
self.img_path = img_path
self.label = label
self.features = features_vec
def __repr__(self):
return ("Datum(img_path=%s, features=%s..., label=%s)" %
(self.img_path, self.features[:5], self.label))
def f_vec(features):
return numpy.array(features, dtype=numpy.int32)
def load_datum(path, label, feature_descriptors, c_backend):
img = Image.open(path)
img = img.convert("L")
ar = f_vec(img)
integrate_image(ar)
int_img = IntegratedImage(ar)
return Datum(path,
label,
LazyFeatureVec(int_img, feature_descriptors, c_backend))
def load_data_dir(dir, label, feature_descriptors, data_out, max_load=5, c_backend=False):
if c_faces is None and c_backend:
print ("C++ backend not found. Please compile the c_backend with " +
"build.sh or run without -c flag.")
exit(1)
for root, dirs, files in os.walk(dir):
for name in fnmatch.filter(files, "*.bmp"):
rel_path = join(root, name)
data_out.append(load_datum(rel_path, label, feature_descriptors, c_backend))
max_load -= 1
if not max_load:
break