-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
289 lines (268 loc) · 10.2 KB
/
main.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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
import cv2
import tensorflow as tf
import numpy as np
from face_processes.facedetection.face_detection import FaceDetection
from face_processes.landmarkdetection.landmark_detection import LandmakDetector
from face_processes.maskgenerator import MaskGenerator
from model import Trainer
from modelevaluation import ModelEval
from utils import *
import os
class pipeline:
def __init__(self, model_dir: str) -> None:
self.face_detector = FaceDetection()
self.mask_generator = MaskGenerator()
if model_dir is not None:
self.model = tf.keras.models.load_model(model_dir)
def train(
self,
data_dir: dict[str, str],
model_name: str,
batch_size: int,
patch_size: tuple[int, int],
train_num_epochs: int,
tune_num_epochs: int,
tune_from: int,
lr: float,
augmentation: bool,
aug_config: dict[float, tuple[float, float], str, tuple[float, float]],
save_to_dir: str,
):
"""
Trains the models proposed in the paper:
Params:
data_dir: a dictionary containes 'training': train dataset, 'validation': validation dataset
model_name: 'small' or 'larg'
batch_size
patch_size: image size
train_num_epochs: number of epochs in train process
tune_num_epochs: number of epochs in tune process
tune_from: the bottom of the layers you want to fine tune
lr: learning rate
augmentation: do you want to augment data?
aug_config: augentation configuration
save_to_dir: the directory to save result
"""
trainer = Trainer(
data_dir["training"], data_dir["validation"], batch_size, patch_size
)
trainer.load_data()
trainer.model(model_name, augmentation, aug_config)
train_history, self.model = trainer.train(train_num_epochs, lr)
trainer.plot_train_process(save_to_dir)
if tune_num_epochs is not None:
tune_history, self.model = trainer.fine_tune(tune_from, tune_num_epochs)
trainer.plot_whole_process(save_to_dir)
if save_to_dir is not None:
trainer.save_model(save_to_dir)
trainer.save_history(train_history, save_to_dir)
if tune_num_epochs is not None:
trainer.save_history(tune_history, save_to_dir)
def evaluate_model(
self, testdata_dir: str, patch_size: tuple[int, int], confusion_matrix: bool
) -> None:
"""
evaluates a trained model with a test dataset
Params:
testdata_dir: the directory of test data
patch_size: the size of each image
confusion_matrix: Do you want a confusion matrix?
"""
evaluator = ModelEval(testdata_dir, patch_size, self.model)
evaluator.load_data()
evaluator.evaluat()
if confusion_matrix:
evaluator.confusion_matrix()
def run_model(self, img_dir: str, save_to_dir: bool, save_path: str):
"""
Uses a trained network to detecet the gender of people in an image
Params:
img_dir: Diretion of image
save_to_dir: do you want to save result?
save_path: the directory to save results there
"""
img = cv2.imread(img_dir)
face = self.face_detector.detect(img)
for i in range(len(face)):
x = face[i].left()
y = face[i].top()
x1 = face[i].right()
y1 = face[i].bottom()
image = img[y:y1, x:x1]
image = cv2.resize(image, (240, 240))
image = tf.keras.applications.efficientnet.preprocess_input(image)
image = tf.expand_dims(image, axis=0)
predict = self.model.predict(image)
predictions = tf.where(predict < 0.5, 0, 1)
predictions = np.argmax(predictions, axis=1)
if predictions == [1]:
cv2.rectangle(img, (x, y), (x1, y1), (255, 0, 0), 2)
cv2.putText(
img,
"male",
(x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
(
255,
0,
),
2,
)
elif predictions == [0]:
cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)
cv2.putText(
img,
"Female",
(x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
(0, 0, 255),
2,
)
cv2.imshow(img)
cv2.waitKey(0)
if save_to_dir:
if save_path is not None:
directory_maker(save_path)
cv2.imwrite(
os.path.join(save_path, "gender_detection_result.png"), img
)
else:
cv2.imwrite("gender_detection_result.png", img)
def detect_faces(
self,
img_dir: str,
save_to_dir: bool,
destination_directory: str,
flow_from_dir: bool,
prefix: str,
):
"""
Usage of face detection class
Params:
img_dir: Diretion of image or the diretory of images when flow_from_directory
save_to_dir: do you want to save result?
destination_directory: destination directory to save results.
flow_from_directory: if you want to flow from directory
prefix: the prefix you want to save files in flow_from_directory
"""
if flow_from_dir:
self.face_detector.flow_from_directory(
img_dir, destination_directory, prefix
)
else:
img = cv2.imread(img_dir)
rects = self.face_detector.detect(img)
for i in range(len(rects)):
cv2.rectangle(
img,
(rects[i].left(), rects[i].top()),
(rects[i].right(), rects[i].bottom()),
(255, 0, 0),
2,
)
if save_to_dir:
if destination_directory is not None:
directory_maker(destination_directory)
cv2.imwrite(
os.path.join(
destination_directory, "face_detection_result.png"
),
img,
)
else:
cv2.imwrite("face_detection_result.png", img)
cv2.imshow(img)
cv2.waitKey(0)
def detect_face_landmarks(
self,
image_dir: str,
num_landmark: int,
save_to_dir: bool,
destination_directory: str,
flow_from_directory: bool,
prefix: str,
):
"""
Usage of landmark detection class
Params:
image_dir: Diretion of image if flow from directory the directory containing images
num_landmark: the number of landmark that you want to be deteted (5 or 68)
save_to_dir: do you want to save result?
destination_directory: destination directory to save results.
flow_from_directory: if you want to find the landmark of faces of images of a directory
prefix: the prefix you want to save images with.
"""
landmark_detector = LandmakDetector(num_landmark)
if flow_from_directory:
landmark_detector.flow_from_directory(
image_dir, destination_directory, prefix
)
else:
img = cv2.imread(image_dir)
rects = self.face_detector.detect(img)
for i in range(len(rects)):
coords = landmark_detector.detect(img, rects[i])
for x, y in coords:
cv2.circle(img, (int(x), int(y)), 1, (0, 0, 255), -1)
if save_to_dir:
if destination_directory is not None:
directory_maker(destination_directory)
cv2.imwrite(
os.path.join(
destination_directory, "landmark_detection_result.png"
),
img,
)
else:
cv2.imwrite("landmark_detection_result.png", img)
cv2.imshow(img)
cv2.waitKey(0)
def generate_masked_faces(
self,
low_threshold: float,
high_threshold: float,
kernel_size: int,
image_dir: str,
save_to_dir: bool,
save_directory: str,
flow_from_directory: bool,
prefix: str,
):
"""
Usage of masked face generator
Params:
low_threshold
high_threshold
kernel_size: The size of the Sobel kernel to be used
image_dir: the image directory of the directory of images in flow from directory
save_to_dir: do you want to save result?
save_directory: destination directory to save results.
flow_from_directory: whether you want to flow from directory or not
prefix: the prefix you want to save you files with in flow from directory
"""
if flow_from_directory:
self.mask_generator.flow_from_directory(
low_threshold,
high_threshold,
kernel_size,
image_dir,
save_directory,
prefix,
)
else:
img = cv2.imread(image_dir)
masked_face = self.mask_generator.mask_generator(
img, low_threshold, high_threshold, kernel_size
)
if save_to_dir:
if save_directory is not None:
directory_maker(save_directory)
cv2.imwrite(
os.path.join(save_directory, "masked_face.png"), masked_face
)
else:
cv2.imwrite("masked_face.png", masked_face)
cv2.imshow(masked_face)
cv2.waitKey(0)