-
Notifications
You must be signed in to change notification settings - Fork 23
/
prepare.py
228 lines (199 loc) · 9.58 KB
/
prepare.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
#
# prepare.py
# Prepare data for boostedcascade.
#
# Author : Donny
#
import numpy as np
import scipy.misc
import os
import math
def transformToData(image, wndW, wndH, padX, padY):
"""Scan the image and get subimage of size = [wndW, wndH],
padding of each subimage is [padX, padY].
"""
h, w = image.shape
data = []
for y in range(0,h-wndH,padY):
for x in range(0,w-wndW,padX):
data.append(image[y:y+wndH, x:x+wndW])
return data
def transformToDataWithScale(image, wndW, wndH, padX, padY, min_size=0.0, max_size=1.0, step=0.5):
height, width = image.shape
data = []
if min_size * min(width, height) < 24:
min_size = 24.0 / min(width, height)
assert max_size > min_size
assert step > 0.0 and step < 1.0
si = max_size
while True:
scaledimg = scipy.misc.imresize(image, size=(int(si*height), int(si*width)), mode='F')
scaleddata = transformToData(scaledimg, wndW, wndH, padX, padY)
data.extend(scaleddata)
if si <= min_size: break
si = si * step
if si < min_size: si = min_size
return data
def generateNonface(srcpath, destpath, imgsize, scanpad=(48,48)):
"""Generate non-face images in srcpath, and save to destpath.
"""
if not isinstance(imgsize, tuple):
raise ValueError("imgsize must be tuple")
if not isinstance(scanpad, tuple):
raise ValueError("scanpad must be tuple")
for file_or_dir in os.listdir(srcpath):
abs_srcpath = os.path.abspath(os.path.join(srcpath, file_or_dir))
abs_destpath = os.path.abspath(os.path.join(destpath, file_or_dir))
if os.path.isdir(abs_srcpath):
os.makedirs(abs_destpath, exist_ok=True)
generateNonface(abs_srcpath, abs_destpath, imgsize, scanpad)
else:
if file_or_dir.endswith('.jpg'):
print('Processing non-face image %s' % file_or_dir)
image = scipy.misc.imread(abs_srcpath, flatten=False, mode='F')
outname, ext = os.path.splitext(abs_destpath)
data = transformToDataWithScale(image, imgsize[0], imgsize[1], scanpad[0], scanpad[1])
for ind in range(len(data)):
scipy.misc.imsave(outname + '-' + str(ind) + ext, data[ind])
def generateFace(srcpath, destpath, listpath, verbose=False):
"""Generate face images in srcpath, described by listfiles in listpath,
and save to destpath.
"""
cnt_miss = 0
faceind = 0
for facelist in os.listdir(listpath):
if facelist.endswith('-ellipseList.txt'):
print('Processing facelist %s' % facelist)
abs_facelist = os.path.abspath(os.path.join(listpath,facelist))
with open(abs_facelist) as f:
allline = f.readlines()
allline = [l.rstrip('\n') for l in allline]
il = 0
while il < len(allline):
imgfilename = allline[il]; il+=1
if not imgfilename:
break
if verbose: print('Processing face image %s.jpg' % imgfilename)
try:
image = scipy.misc.imread(os.path.join(srcpath,imgfilename + '.jpg'), mode='F')
except FileNotFoundError:
if verbose: print('Face image %s not found.' % imgfilename)
cnt_miss += 1
facecnt = int(allline[il]); il+=1+facecnt
continue
height, width = image.shape
imgpad = int(max(height, width)/2)
image = np.pad(image, [(imgpad,imgpad), (imgpad,imgpad)],
mode='constant', constant_values=0) # Pad image
facecnt = int(allline[il]); il+=1
for i in range(facecnt):
ellipse = allline[il]; il+=1
major_radius, minor_radius, angle, ctx, cty, acc = \
map(float, ellipse.split())
radian = angle*math.pi/180
# May get some noise around, but it's fine.
# There is noise when detecting.
h = int(math.cos(radian)*major_radius*2)
w = int(math.cos(radian)*minor_radius*2)
if h < w: h = w
else: w = h
y = int(cty - h/2 + imgpad)
x = int(ctx - w/2 + imgpad)
try:
outimgname = os.path.basename(imgfilename) + '-' + str(faceind) + '.jpg'
scipy.misc.imsave(os.path.join(destpath, outimgname),
image[y:y+h, x:x+w])
faceind += 1
if verbose: print('Face image %s generated.' % outimgname)
except Exception as expt:
print(expt)
print(x,y,w,h, ' ',width, height)
print('Faces generation done with %d faces generated and %d faces lost.' % (faceind, cnt_miss))
return faceind, cnt_miss
def stretchFace(srcpath, destpath, imgsize, verbose=False):
"""Stretch faces to
"""
print('Stretching faces...')
for ognface in os.listdir(srcpath):
if ognface.endswith('.jpg'):
if verbose: print('Stretching face image %s' % ognface)
image = scipy.misc.imread(os.path.join(srcpath, ognface), mode='F')
image = scipy.misc.imresize(image, size=imgsize, mode='F') # TODO size=(height, width)
scipy.misc.imsave(os.path.join(destpath, ognface), image)
print('Face stretching done.')
def generateNoFaceFromFaceBk(srcpath, destpath, listpath, imgsize, scanpad, verbose=False):
"""Generate no-face images from the background of images contain faces.
"""
os.makedirs(destpath, exist_ok=True)
if not isinstance(imgsize, tuple):
raise ValueError("imgsize must be tuple")
if not isinstance(scanpad, tuple):
raise ValueError("scanpad must be tuple")
cnt_miss = 0
nofaceind = 0
for facelist in os.listdir(listpath):
if facelist.endswith('-ellipseList.txt'):
print('Processing facelist %s' % facelist)
abs_facelist = os.path.abspath(os.path.join(listpath,facelist))
with open(abs_facelist) as f:
allline = f.readlines()
allline = [l.rstrip('\n') for l in allline]
il = 0
while il < len(allline):
imgfilename = allline[il]; il+=1
if not imgfilename:
break
if verbose: print('Processing face image %s.jpg' % imgfilename)
try:
image = scipy.misc.imread(os.path.join(srcpath,imgfilename + '.jpg'), mode='F')
except FileNotFoundError:
if verbose: print('Face image %s not found.' % imgfilename)
cnt_miss += 1
facecnt = int(allline[il]); il+=1+facecnt
continue
height, width = image.shape
facecnt = int(allline[il]); il+=1
for i in range(facecnt):
ellipse = allline[il]; il+=1
major_radius, minor_radius, angle, ctx, cty, acc = \
map(float, ellipse.split())
radian = angle*math.pi/180
# May get some noise around, but it's fine.
# There is noise when detecting.
h = int(math.cos(radian)*major_radius*2)
w = int(math.cos(radian)*minor_radius*2)
if h < w: h = w
else: w = h
y = int(cty - h/2)
if y < 0: y = 0
elif y >= height: y = height - 1
x = int(ctx - w/2)
if x < 0: x = 0
elif x >= width: x = width - 1
image[y:y+h, x:x+w] = 0 # crop out face
outimgname = os.path.join(destpath, os.path.basename(imgfilename))
# data = transformToData(image, imgsize[0], imgsize[1], scanpad[0], scanpad[1])
data = transformToDataWithScale(image, imgsize[0], imgsize[1], scanpad[0], scanpad[1])
for ind in range(len(data)):
scipy.misc.imsave(outimgname + '-' + str(ind) + '.jpg', data[ind])
nofaceind += 1
print('Faces generation done with %d no-faces generated and %d face images lost.' % (nofaceind, cnt_miss))
return nofaceind, cnt_miss
if __name__ == '__main__':
DetectWndW = 24
DetectWndH = 24
DetectPadX = 12
DetectPadY = 12
ScanPadX = 48
ScanPadY = 48
generateNonface('db/non-faces', 'data/non-faces-ex',
imgsize=(DetectWndW, DetectWndH),
scanpad=(ScanPadX, ScanPadY))
# generateFace('db/faces', 'db/pure-faces', 'db/FDDB-folds')
# stretchFace('db/pure-faces', 'data/faces',
# imgsize=(DetectWndW, DetectWndH))
# generateNoFaceFromFaceBk('db/faces',
# 'data/non-faces/facebk-ex',
# 'db/FDDB-folds',
# imgsize=(DetectWndW, DetectWndH),
# scanpad=(ScanPadX, ScanPadY))