added dsdg without model file
Browse files- DSDG/DUM/Load_OULUNPUcrop_train.py +277 -0
- DSDG/DUM/Load_OULUNPUcrop_valtest.py +119 -0
- DSDG/DUM/make_dataset/crop_dataset.py +116 -0
- DSDG/DUM/models/CDCNs_u.py +266 -0
- DSDG/DUM/models/ResNet_u.py +114 -0
- DSDG/DUM/test.py +168 -0
- DSDG/DUM/train.py +289 -0
- DSDG/DUM/utils.py +431 -0
- DSDG/misc/__init__.py +2 -0
- DSDG/misc/util.py +109 -0
- DSDG/networks/__init__.py +32 -0
- DSDG/networks/generator.py +192 -0
- DSDG/networks/light_cnn.py +98 -0
- app.py +87 -17
- tddfa/TDDFA.py +6 -6
- tddfa/weights/mb1_120x120.onnx +3 -0
DSDG/DUM/Load_OULUNPUcrop_train.py
ADDED
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import print_function, division
|
2 |
+
import os
|
3 |
+
import torch
|
4 |
+
import pandas as pd
|
5 |
+
import cv2
|
6 |
+
import numpy as np
|
7 |
+
import random
|
8 |
+
import torch
|
9 |
+
from torch.utils.data import Dataset, DataLoader
|
10 |
+
from torchvision import transforms
|
11 |
+
import pdb
|
12 |
+
import math
|
13 |
+
import os
|
14 |
+
import copy
|
15 |
+
import imgaug.augmenters as iaa
|
16 |
+
|
17 |
+
# face_scale = 1.3 #default for test, for training , can be set from [1.2 to 1.5]
|
18 |
+
|
19 |
+
# data augment from 'imgaug' --> Add (value=(-40,40), per_channel=True), GammaContrast (gamma=(0.5,1.5))
|
20 |
+
seq = iaa.Sequential([
|
21 |
+
iaa.Add(value=(-40, 40), per_channel=True), # Add color
|
22 |
+
iaa.GammaContrast(gamma=(0.5, 1.5)) # GammaContrast with a gamma of 0.5 to 1.5
|
23 |
+
])
|
24 |
+
|
25 |
+
|
26 |
+
# array
|
27 |
+
class RandomErasing(object):
|
28 |
+
'''
|
29 |
+
Class that performs Random Erasing in Random Erasing Data Augmentation by Zhong et al.
|
30 |
+
-------------------------------------------------------------------------------------
|
31 |
+
probability: The probability that the operation will be performed.
|
32 |
+
sl: min erasing area
|
33 |
+
sh: max erasing area
|
34 |
+
r1: min aspect ratio
|
35 |
+
mean: erasing value
|
36 |
+
-------------------------------------------------------------------------------------
|
37 |
+
'''
|
38 |
+
|
39 |
+
def __init__(self, probability=0.5, sl=0.01, sh=0.05, r1=0.5, mean=[0.4914, 0.4822, 0.4465]):
|
40 |
+
self.probability = probability
|
41 |
+
self.mean = mean
|
42 |
+
self.sl = sl
|
43 |
+
self.sh = sh
|
44 |
+
self.r1 = r1
|
45 |
+
|
46 |
+
def __call__(self, sample):
|
47 |
+
img, map_x, spoofing_label = sample['image_x'], sample['map_x'], sample['spoofing_label']
|
48 |
+
|
49 |
+
if random.uniform(0, 1) < self.probability:
|
50 |
+
attempts = np.random.randint(1, 3)
|
51 |
+
for attempt in range(attempts):
|
52 |
+
area = img.shape[0] * img.shape[1]
|
53 |
+
|
54 |
+
target_area = random.uniform(self.sl, self.sh) * area
|
55 |
+
aspect_ratio = random.uniform(self.r1, 1 / self.r1)
|
56 |
+
|
57 |
+
h = int(round(math.sqrt(target_area * aspect_ratio)))
|
58 |
+
w = int(round(math.sqrt(target_area / aspect_ratio)))
|
59 |
+
|
60 |
+
if w < img.shape[1] and h < img.shape[0]:
|
61 |
+
x1 = random.randint(0, img.shape[0] - h)
|
62 |
+
y1 = random.randint(0, img.shape[1] - w)
|
63 |
+
|
64 |
+
img[x1:x1 + h, y1:y1 + w, 0] = self.mean[0]
|
65 |
+
img[x1:x1 + h, y1:y1 + w, 1] = self.mean[1]
|
66 |
+
img[x1:x1 + h, y1:y1 + w, 2] = self.mean[2]
|
67 |
+
|
68 |
+
return {'image_x': img, 'map_x': map_x, 'spoofing_label': spoofing_label}
|
69 |
+
|
70 |
+
|
71 |
+
# Tensor
|
72 |
+
class Cutout(object):
|
73 |
+
def __init__(self, length=50):
|
74 |
+
self.length = length
|
75 |
+
|
76 |
+
def __call__(self, sample):
|
77 |
+
img, map_x, spoofing_label = sample['image_x'], sample['map_x'], sample['spoofing_label']
|
78 |
+
h, w = img.shape[1], img.shape[2] # Tensor [1][2], nparray [0][1]
|
79 |
+
mask = np.ones((h, w), np.float32)
|
80 |
+
y = np.random.randint(h)
|
81 |
+
x = np.random.randint(w)
|
82 |
+
length_new = np.random.randint(1, self.length)
|
83 |
+
|
84 |
+
y1 = np.clip(y - length_new // 2, 0, h)
|
85 |
+
y2 = np.clip(y + length_new // 2, 0, h)
|
86 |
+
x1 = np.clip(x - length_new // 2, 0, w)
|
87 |
+
x2 = np.clip(x + length_new // 2, 0, w)
|
88 |
+
|
89 |
+
mask[y1: y2, x1: x2] = 0.
|
90 |
+
mask = torch.from_numpy(mask)
|
91 |
+
mask = mask.expand_as(img)
|
92 |
+
img *= mask
|
93 |
+
return {'image_x': img, 'map_x': map_x, 'spoofing_label': spoofing_label}
|
94 |
+
|
95 |
+
|
96 |
+
class Normaliztion(object):
|
97 |
+
"""
|
98 |
+
same as mxnet, normalize into [-1, 1]
|
99 |
+
image = (image - 127.5)/128
|
100 |
+
"""
|
101 |
+
|
102 |
+
def __call__(self, sample):
|
103 |
+
image_x, map_x, spoofing_label = sample['image_x'], sample['map_x'], sample['spoofing_label']
|
104 |
+
new_image_x = (image_x - 127.5) / 128 # [-1,1]
|
105 |
+
new_map_x = map_x / 255.0 # [0,1]
|
106 |
+
return {'image_x': new_image_x, 'map_x': new_map_x, 'spoofing_label': spoofing_label}
|
107 |
+
|
108 |
+
|
109 |
+
class RandomHorizontalFlip(object):
|
110 |
+
"""Horizontally flip the given Image randomly with a probability of 0.5."""
|
111 |
+
|
112 |
+
def __call__(self, sample):
|
113 |
+
image_x, map_x, spoofing_label = sample['image_x'], sample['map_x'], sample['spoofing_label']
|
114 |
+
|
115 |
+
new_image_x = np.zeros((256, 256, 3))
|
116 |
+
new_map_x = np.zeros((32, 32))
|
117 |
+
|
118 |
+
p = random.random()
|
119 |
+
if p < 0.5:
|
120 |
+
# print('Flip')
|
121 |
+
|
122 |
+
new_image_x = cv2.flip(image_x, 1)
|
123 |
+
new_map_x = cv2.flip(map_x, 1)
|
124 |
+
|
125 |
+
return {'image_x': new_image_x, 'map_x': new_map_x, 'spoofing_label': spoofing_label}
|
126 |
+
else:
|
127 |
+
# print('no Flip')
|
128 |
+
return {'image_x': image_x, 'map_x': map_x, 'spoofing_label': spoofing_label}
|
129 |
+
|
130 |
+
|
131 |
+
class ToTensor(object):
|
132 |
+
"""
|
133 |
+
Convert ndarrays in sample to Tensors.
|
134 |
+
process only one batch every time
|
135 |
+
"""
|
136 |
+
|
137 |
+
def __call__(self, sample):
|
138 |
+
image_x, map_x, spoofing_label = sample['image_x'], sample['map_x'], sample['spoofing_label']
|
139 |
+
|
140 |
+
# swap color axis because
|
141 |
+
# numpy image: (batch_size) x H x W x C
|
142 |
+
# torch image: (batch_size) x C X H X W
|
143 |
+
image_x = image_x[:, :, ::-1].transpose((2, 0, 1))
|
144 |
+
image_x = np.array(image_x)
|
145 |
+
|
146 |
+
map_x = np.array(map_x)
|
147 |
+
|
148 |
+
spoofing_label_np = np.array([0], dtype=np.long)
|
149 |
+
spoofing_label_np[0] = spoofing_label
|
150 |
+
|
151 |
+
return {'image_x': torch.from_numpy(image_x.astype(np.float)).float(),
|
152 |
+
'map_x': torch.from_numpy(map_x.astype(np.float)).float(),
|
153 |
+
'spoofing_label': torch.from_numpy(spoofing_label_np.astype(np.long)).long()}
|
154 |
+
|
155 |
+
|
156 |
+
class Spoofing_train_g(Dataset):
|
157 |
+
|
158 |
+
def __init__(self, info_list, root_dir, map_dir, transform=None):
|
159 |
+
|
160 |
+
# +1,1_1_21_1
|
161 |
+
self.landmarks_frame = pd.read_csv(info_list, delimiter=',', header=None)
|
162 |
+
self.root_dir = root_dir
|
163 |
+
self.map_dir = map_dir
|
164 |
+
self.transform = transform
|
165 |
+
|
166 |
+
def __len__(self):
|
167 |
+
return len(self.landmarks_frame)
|
168 |
+
|
169 |
+
def __getitem__(self, idx):
|
170 |
+
# 1_1_30_1
|
171 |
+
videoname = str(self.landmarks_frame.iloc[idx, 1])
|
172 |
+
image_path = os.path.join(self.root_dir, videoname)
|
173 |
+
map_path = os.path.join(self.map_dir, videoname)
|
174 |
+
image_x, map_x = self.get_single_image_x(image_path, map_path, videoname)
|
175 |
+
|
176 |
+
spoofing_label = self.landmarks_frame.iloc[idx, 0]
|
177 |
+
if spoofing_label == 1:
|
178 |
+
spoofing_label = 1 # real
|
179 |
+
else:
|
180 |
+
spoofing_label = 0
|
181 |
+
map_x = np.zeros((32, 32)) # fake
|
182 |
+
|
183 |
+
sample = {'image_x': image_x, 'map_x': map_x, 'spoofing_label': spoofing_label}
|
184 |
+
|
185 |
+
if self.transform:
|
186 |
+
sample = self.transform(sample)
|
187 |
+
return sample
|
188 |
+
|
189 |
+
def get_idx(self):
|
190 |
+
real_data_idx = []
|
191 |
+
fake_data_idx = []
|
192 |
+
i, j = 0, 0
|
193 |
+
for idx_all in range(self.__len__()):
|
194 |
+
videoname = str(self.landmarks_frame.iloc[idx_all, 1])
|
195 |
+
if videoname[:1] == 'p':
|
196 |
+
fake_data_idx.append(i)
|
197 |
+
i += 1
|
198 |
+
else:
|
199 |
+
real_data_idx.append(j)
|
200 |
+
j += 1
|
201 |
+
return real_data_idx, fake_data_idx
|
202 |
+
|
203 |
+
def get_single_image_x(self, images_path, maps_path, videoname):
|
204 |
+
|
205 |
+
frame_total = len([name for name in os.listdir(images_path) if os.path.isfile(os.path.join(images_path, name))])
|
206 |
+
# random choose 1 frame
|
207 |
+
|
208 |
+
image_id = np.random.randint(1, frame_total)
|
209 |
+
|
210 |
+
if videoname[:1] == 'p':
|
211 |
+
image_id = np.random.randint(1, 100)
|
212 |
+
s = "%d_scene" % image_id
|
213 |
+
image_name = s + '.jpg'
|
214 |
+
# /home/shejiahui5/notespace/data/oulu_img/train_bbox_files/p2_0_1_30/21_scence.jpg
|
215 |
+
s = "%d_depth1D" % image_id
|
216 |
+
map_name = s + '.jpg'
|
217 |
+
else:
|
218 |
+
image_id = np.random.randint(1, frame_total)
|
219 |
+
s = "_%d_scene" % image_id
|
220 |
+
image_name = videoname + s + '.jpg'
|
221 |
+
s = "_%d_depth1D" % image_id
|
222 |
+
map_name = videoname + s + '.jpg'
|
223 |
+
|
224 |
+
image_path = os.path.join(images_path, image_name)
|
225 |
+
map_path = os.path.join(maps_path, map_name)
|
226 |
+
|
227 |
+
map_x = np.zeros((32, 32))
|
228 |
+
|
229 |
+
# RGB
|
230 |
+
image_x = cv2.imread(image_path)
|
231 |
+
image_x = cv2.resize(image_x, (256, 256))
|
232 |
+
# data augment from 'imgaug' --> Add (value=(-40,40), per_channel=True), GammaContrast (gamma=(0.5,1.5))
|
233 |
+
image_x_aug = seq.augment_image(image_x)
|
234 |
+
|
235 |
+
# gray-map
|
236 |
+
if os.path.exists(map_path):
|
237 |
+
map_x = cv2.imread(map_path, 0)
|
238 |
+
map_x = cv2.resize(map_x, (32, 32))
|
239 |
+
|
240 |
+
return image_x_aug, map_x
|
241 |
+
|
242 |
+
|
243 |
+
class SeparateBatchSampler(object):
|
244 |
+
def __init__(self, real_data_idx, fake_data_idx, batch_size, ratio, put_back=False):
|
245 |
+
self.batch_size = batch_size
|
246 |
+
self.ratio = ratio
|
247 |
+
self.real_data_num = len(real_data_idx)
|
248 |
+
self.fake_data_num = len(fake_data_idx)
|
249 |
+
self.max_num_image = max(self.real_data_num, self.fake_data_num)
|
250 |
+
|
251 |
+
self.real_data_idx = real_data_idx
|
252 |
+
self.fake_data_idx = fake_data_idx
|
253 |
+
|
254 |
+
self.processed_idx = copy.deepcopy(self.real_data_idx)
|
255 |
+
|
256 |
+
def __len__(self):
|
257 |
+
return self.max_num_image // (int(self.batch_size * self.ratio))
|
258 |
+
|
259 |
+
def __iter__(self):
|
260 |
+
batch_size_real_data = int(math.floor(self.ratio * self.batch_size))
|
261 |
+
batch_size_fake_data = self.batch_size - batch_size_real_data
|
262 |
+
|
263 |
+
self.processed_idx = copy.deepcopy(self.real_data_idx)
|
264 |
+
rand_real_data_idx = np.random.permutation(len(self.real_data_idx) // 2)
|
265 |
+
for i in range(self.__len__()):
|
266 |
+
batch = []
|
267 |
+
idx_fake_data = random.sample(self.fake_data_idx, batch_size_fake_data)
|
268 |
+
|
269 |
+
for j in range(batch_size_real_data // 2):
|
270 |
+
idx = rand_real_data_idx[(i * batch_size_real_data + j) % (self.real_data_num // 2)]
|
271 |
+
batch.append(self.processed_idx[2 * idx])
|
272 |
+
batch.append(self.processed_idx[2 * idx + 1])
|
273 |
+
|
274 |
+
for idx in idx_fake_data:
|
275 |
+
batch.append(idx + self.real_data_num)
|
276 |
+
# batch.append(2 * idx + 1 + self.real_data_num)
|
277 |
+
yield batch
|
DSDG/DUM/Load_OULUNPUcrop_valtest.py
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import print_function, division
|
2 |
+
import os
|
3 |
+
import torch
|
4 |
+
import pandas as pd
|
5 |
+
# from skimage import io, transform
|
6 |
+
import cv2
|
7 |
+
import numpy as np
|
8 |
+
import random
|
9 |
+
import torch
|
10 |
+
from torch.utils.data import Dataset, DataLoader
|
11 |
+
from torchvision import transforms
|
12 |
+
import pdb
|
13 |
+
import math
|
14 |
+
import os
|
15 |
+
|
16 |
+
|
17 |
+
class Normaliztion_valtest(object):
|
18 |
+
"""
|
19 |
+
same as mxnet, normalize into [-1, 1]
|
20 |
+
image = (image - 127.5)/128
|
21 |
+
"""
|
22 |
+
|
23 |
+
def __call__(self, sample):
|
24 |
+
image_x, val_map_x, spoofing_label, image_names = sample['image_x'], sample['val_map_x'], sample[
|
25 |
+
'spoofing_label'], sample['image_names']
|
26 |
+
new_image_x = (image_x - 127.5) / 128 # [-1,1]
|
27 |
+
return {'image_x': new_image_x, 'val_map_x': val_map_x, 'spoofing_label': spoofing_label,
|
28 |
+
'image_names': image_names}
|
29 |
+
|
30 |
+
|
31 |
+
class ToTensor_valtest(object):
|
32 |
+
"""
|
33 |
+
Convert ndarrays in sample to Tensors.
|
34 |
+
process only one batch every time
|
35 |
+
"""
|
36 |
+
|
37 |
+
def __call__(self, sample):
|
38 |
+
image_x, val_map_x, spoofing_label, image_names = sample['image_x'], sample['val_map_x'], sample[
|
39 |
+
'spoofing_label'], sample['image_names']
|
40 |
+
|
41 |
+
# swap color axis because BGR2RGB
|
42 |
+
# numpy image: (batch_size) x T x H x W x C
|
43 |
+
# torch image: (batch_size) x T x C X H X W
|
44 |
+
image_x = image_x[:, :, :, ::-1].transpose((0, 3, 1, 2))
|
45 |
+
image_x = np.array(image_x)
|
46 |
+
|
47 |
+
val_map_x = np.array(val_map_x)
|
48 |
+
|
49 |
+
spoofing_label_np = np.array([0], dtype=np.long)
|
50 |
+
spoofing_label_np[0] = spoofing_label
|
51 |
+
|
52 |
+
return {'image_x': torch.from_numpy(image_x.astype(np.float)).float(),
|
53 |
+
'val_map_x': torch.from_numpy(val_map_x.astype(np.float)).float(),
|
54 |
+
'spoofing_label': torch.from_numpy(spoofing_label_np.astype(np.long)).long(),
|
55 |
+
'image_names': image_names}
|
56 |
+
|
57 |
+
|
58 |
+
class Spoofing_valtest(Dataset):
|
59 |
+
|
60 |
+
def __init__(self, info_list, root_dir, val_map_dir, transform=None):
|
61 |
+
|
62 |
+
self.landmarks_frame = pd.read_csv(info_list, delimiter=',', header=None)
|
63 |
+
self.root_dir = root_dir
|
64 |
+
self.val_map_dir = val_map_dir
|
65 |
+
self.transform = transform
|
66 |
+
|
67 |
+
def __len__(self):
|
68 |
+
return len(self.landmarks_frame)
|
69 |
+
|
70 |
+
def __getitem__(self, idx):
|
71 |
+
# print(self.landmarks_frame.iloc[idx, 0])
|
72 |
+
videoname = str(self.landmarks_frame.iloc[idx, 1])
|
73 |
+
image_path = os.path.join(self.root_dir, videoname)
|
74 |
+
val_map_path = os.path.join(self.val_map_dir, videoname)
|
75 |
+
|
76 |
+
image_x, val_map_x, image_names = self.get_single_image_x(image_path, val_map_path, videoname)
|
77 |
+
|
78 |
+
spoofing_label = self.landmarks_frame.iloc[idx, 0]
|
79 |
+
if spoofing_label == 1:
|
80 |
+
spoofing_label = 1 # real
|
81 |
+
else:
|
82 |
+
spoofing_label = 0
|
83 |
+
|
84 |
+
sample = {'image_x': image_x, 'val_map_x': val_map_x, 'spoofing_label': spoofing_label,
|
85 |
+
'image_names': image_names}
|
86 |
+
|
87 |
+
if self.transform:
|
88 |
+
sample = self.transform(sample)
|
89 |
+
return sample
|
90 |
+
|
91 |
+
def get_single_image_x(self, images_path, maps_path, videoname):
|
92 |
+
# some vedio flod miss .dat
|
93 |
+
files_total = len([name for name in os.listdir(images_path) if os.path.isfile(os.path.join(images_path, name))])
|
94 |
+
|
95 |
+
image_x = np.zeros((files_total, 256, 256, 3))
|
96 |
+
map_x = np.ones((files_total, 32, 32))
|
97 |
+
image_names = []
|
98 |
+
|
99 |
+
file_list = os.listdir(maps_path)
|
100 |
+
|
101 |
+
for i, map_name in enumerate(file_list):
|
102 |
+
image_name = map_name[:-12] + '_scene.jpg'
|
103 |
+
image_path = os.path.join(images_path, image_name)
|
104 |
+
map_path = os.path.join(maps_path, map_name)
|
105 |
+
|
106 |
+
# RGB
|
107 |
+
image = cv2.imread(image_path)
|
108 |
+
# gray-map
|
109 |
+
map = cv2.imread(map_path, 0)
|
110 |
+
|
111 |
+
image_x[i, :, :, :] = cv2.resize(image, (256, 256))
|
112 |
+
# transform to binary mask --> threshold = 0
|
113 |
+
map_x[i, :, :] = cv2.resize(map, (32, 32))
|
114 |
+
# np.where(temp < 1, temp, 1)
|
115 |
+
# val_map_x[i, :, :] = temp
|
116 |
+
|
117 |
+
image_names.append(image_name)
|
118 |
+
|
119 |
+
return image_x, map_x, image_names
|
DSDG/DUM/make_dataset/crop_dataset.py
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
import os
|
3 |
+
import cv2
|
4 |
+
import numpy as np
|
5 |
+
|
6 |
+
|
7 |
+
root_dir = '/export2/home/wht/oulu_images_crop/'
|
8 |
+
|
9 |
+
img_root = '/export2/home/wht/oulu_images/train_img_flod/'
|
10 |
+
map_root = '/export2/home/wht/oulu_images/train_depth_flod/'
|
11 |
+
bbox_root = '/export2/home/wht/oulu_images/train_bbox_flod/'
|
12 |
+
|
13 |
+
|
14 |
+
def crop_face_from_scene(image, face_name_full, scale):
|
15 |
+
f = open(face_name_full, 'r')
|
16 |
+
lines = f.readlines()
|
17 |
+
lines = lines[0].split(' ')
|
18 |
+
y1, x1, w, h = [int(ele) for ele in lines[:4]]
|
19 |
+
f.close()
|
20 |
+
y2 = y1 + w
|
21 |
+
x2 = x1 + h
|
22 |
+
|
23 |
+
y_mid = (y1 + y2) / 2.0
|
24 |
+
x_mid = (x1 + x2) / 2.0
|
25 |
+
h_img, w_img = image.shape[0], image.shape[1]
|
26 |
+
# w_img,h_img=image.size
|
27 |
+
w_scale = scale * w
|
28 |
+
h_scale = scale * h
|
29 |
+
y1 = y_mid - w_scale / 2.0
|
30 |
+
x1 = x_mid - h_scale / 2.0
|
31 |
+
y2 = y_mid + w_scale / 2.0
|
32 |
+
x2 = x_mid + h_scale / 2.0
|
33 |
+
y1 = max(math.floor(y1), 0)
|
34 |
+
x1 = max(math.floor(x1), 0)
|
35 |
+
y2 = min(math.floor(y2), w_img)
|
36 |
+
x2 = min(math.floor(x2), h_img)
|
37 |
+
|
38 |
+
# region=image[y1:y2,x1:x2]
|
39 |
+
region = image[x1:x2, y1:y2]
|
40 |
+
return region
|
41 |
+
|
42 |
+
|
43 |
+
def crop_face_from_scene_prnet(image, face_name_full, scale):
|
44 |
+
h_img, w_img = image.shape[0], image.shape[1]
|
45 |
+
f = open(face_name_full, 'r')
|
46 |
+
lines = f.readlines()
|
47 |
+
lines = lines[0].split(' ')
|
48 |
+
l, r, t, b = [int(ele) for ele in lines[:4]]
|
49 |
+
if l < 0:
|
50 |
+
l = 0
|
51 |
+
if r > w_img:
|
52 |
+
r = w_img
|
53 |
+
if t < 0:
|
54 |
+
t = 0
|
55 |
+
if b > h_img:
|
56 |
+
b = h_img
|
57 |
+
y1 = l
|
58 |
+
x1 = t
|
59 |
+
w = r - l
|
60 |
+
h = b - t
|
61 |
+
f.close()
|
62 |
+
y2 = y1 + w
|
63 |
+
x2 = x1 + h
|
64 |
+
|
65 |
+
y_mid = (y1 + y2) / 2.0
|
66 |
+
x_mid = (x1 + x2) / 2.0
|
67 |
+
# w_img,h_img=image.size
|
68 |
+
w_scale = scale * w
|
69 |
+
h_scale = scale * h
|
70 |
+
y1 = y_mid - w_scale / 2.0
|
71 |
+
x1 = x_mid - h_scale / 2.0
|
72 |
+
y2 = y_mid + w_scale / 2.0
|
73 |
+
x2 = x_mid + h_scale / 2.0
|
74 |
+
y1 = max(math.floor(y1), 0)
|
75 |
+
x1 = max(math.floor(x1), 0)
|
76 |
+
y2 = min(math.floor(y2), w_img)
|
77 |
+
x2 = min(math.floor(x2), h_img)
|
78 |
+
|
79 |
+
# region=image[y1:y2,x1:x2]
|
80 |
+
region = image[x1:x2, y1:y2]
|
81 |
+
return region
|
82 |
+
|
83 |
+
|
84 |
+
vedio_list = os.listdir(bbox_root)
|
85 |
+
for i, vedio_name in enumerate(vedio_list):
|
86 |
+
print(i)
|
87 |
+
bbox_list = os.listdir(os.path.join(bbox_root, vedio_name))
|
88 |
+
for bbox_name in bbox_list:
|
89 |
+
|
90 |
+
face_scale = np.random.randint(12, 15)
|
91 |
+
face_scale = face_scale / 10.0
|
92 |
+
|
93 |
+
# face_scale = 1.3
|
94 |
+
|
95 |
+
bbox_path = os.path.join(bbox_root, vedio_name, bbox_name)
|
96 |
+
|
97 |
+
img_path = os.path.join(img_root, vedio_name, bbox_name[:-4] + '.jpg')
|
98 |
+
|
99 |
+
img = cv2.imread(img_path)
|
100 |
+
img_crop = cv2.resize(crop_face_from_scene_prnet(img, bbox_path, face_scale), (256, 256))
|
101 |
+
|
102 |
+
img_crop_path = os.path.join(root_dir, 'train_img_flod')
|
103 |
+
|
104 |
+
if not os.path.exists(os.path.join(img_crop_path, vedio_name)):
|
105 |
+
os.makedirs(os.path.join(img_crop_path, vedio_name))
|
106 |
+
|
107 |
+
cv2.imwrite(os.path.join(img_crop_path, vedio_name, bbox_name[:-4] + '.jpg'), img_crop)
|
108 |
+
|
109 |
+
map_path = os.path.join(map_root, vedio_name, bbox_name[:-9] + 'depth1D.jpg')
|
110 |
+
|
111 |
+
map = cv2.imread(map_path, 0)
|
112 |
+
map_crop = cv2.resize(crop_face_from_scene_prnet(map, bbox_path, face_scale), (32, 32))
|
113 |
+
map_crop_path = os.path.join(root_dir, 'train_depth_flod')
|
114 |
+
if not os.path.exists(os.path.join(map_crop_path, vedio_name)):
|
115 |
+
os.makedirs(os.path.join(map_crop_path, vedio_name))
|
116 |
+
cv2.imwrite(os.path.join(map_crop_path, vedio_name, bbox_name[:-9] + 'depth1D.jpg'), map_crop)
|
DSDG/DUM/models/CDCNs_u.py
ADDED
@@ -0,0 +1,266 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
|
3 |
+
import torch
|
4 |
+
import torch.nn.functional as F
|
5 |
+
import torch.utils.model_zoo as model_zoo
|
6 |
+
from torch import nn
|
7 |
+
from torch.nn import Parameter
|
8 |
+
import pdb
|
9 |
+
import numpy as np
|
10 |
+
|
11 |
+
|
12 |
+
class Conv2d_cd(nn.Module):
|
13 |
+
def __init__(self, in_channels, out_channels, kernel_size=3, stride=1,
|
14 |
+
padding=1, dilation=1, groups=1, bias=False, theta=0.7):
|
15 |
+
|
16 |
+
super(Conv2d_cd, self).__init__()
|
17 |
+
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding=padding,
|
18 |
+
dilation=dilation, groups=groups, bias=bias)
|
19 |
+
self.theta = theta
|
20 |
+
|
21 |
+
def forward(self, x):
|
22 |
+
out_normal = self.conv(x)
|
23 |
+
|
24 |
+
if math.fabs(self.theta - 0.0) < 1e-8:
|
25 |
+
return out_normal
|
26 |
+
else:
|
27 |
+
# pdb.set_trace()
|
28 |
+
[C_out, C_in, kernel_size, kernel_size] = self.conv.weight.shape
|
29 |
+
kernel_diff = self.conv.weight.sum(2).sum(2)
|
30 |
+
kernel_diff = kernel_diff[:, :, None, None]
|
31 |
+
out_diff = F.conv2d(input=x, weight=kernel_diff, bias=self.conv.bias, stride=self.conv.stride, padding=0,
|
32 |
+
groups=self.conv.groups)
|
33 |
+
|
34 |
+
return out_normal - self.theta * out_diff
|
35 |
+
|
36 |
+
|
37 |
+
class SpatialAttention(nn.Module):
|
38 |
+
def __init__(self, kernel=3):
|
39 |
+
super(SpatialAttention, self).__init__()
|
40 |
+
|
41 |
+
self.conv1 = nn.Conv2d(2, 1, kernel_size=kernel, padding=kernel // 2, bias=False)
|
42 |
+
self.sigmoid = nn.Sigmoid()
|
43 |
+
|
44 |
+
def forward(self, x):
|
45 |
+
avg_out = torch.mean(x, dim=1, keepdim=True)
|
46 |
+
max_out, _ = torch.max(x, dim=1, keepdim=True)
|
47 |
+
x = torch.cat([avg_out, max_out], dim=1)
|
48 |
+
x = self.conv1(x)
|
49 |
+
|
50 |
+
return self.sigmoid(x)
|
51 |
+
|
52 |
+
|
53 |
+
class CDCN_u(nn.Module):
|
54 |
+
|
55 |
+
def __init__(self, basic_conv=Conv2d_cd, theta=0.7):
|
56 |
+
super(CDCN_u, self).__init__()
|
57 |
+
|
58 |
+
self.conv1 = nn.Sequential(
|
59 |
+
basic_conv(3, 64, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
60 |
+
nn.BatchNorm2d(64),
|
61 |
+
nn.ReLU(),
|
62 |
+
)
|
63 |
+
|
64 |
+
self.Block1 = nn.Sequential(
|
65 |
+
basic_conv(64, 128, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
66 |
+
nn.BatchNorm2d(128),
|
67 |
+
nn.ReLU(),
|
68 |
+
basic_conv(128, 196, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
69 |
+
nn.BatchNorm2d(196),
|
70 |
+
nn.ReLU(),
|
71 |
+
basic_conv(196, 128, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
72 |
+
nn.BatchNorm2d(128),
|
73 |
+
nn.ReLU(),
|
74 |
+
nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
|
75 |
+
|
76 |
+
)
|
77 |
+
|
78 |
+
self.Block2 = nn.Sequential(
|
79 |
+
basic_conv(128, 128, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
80 |
+
nn.BatchNorm2d(128),
|
81 |
+
nn.ReLU(),
|
82 |
+
basic_conv(128, 196, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
83 |
+
nn.BatchNorm2d(196),
|
84 |
+
nn.ReLU(),
|
85 |
+
basic_conv(196, 128, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
86 |
+
nn.BatchNorm2d(128),
|
87 |
+
nn.ReLU(),
|
88 |
+
nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
|
89 |
+
)
|
90 |
+
|
91 |
+
self.Block3 = nn.Sequential(
|
92 |
+
basic_conv(128, 128, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
93 |
+
nn.BatchNorm2d(128),
|
94 |
+
nn.ReLU(),
|
95 |
+
basic_conv(128, 196, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
96 |
+
nn.BatchNorm2d(196),
|
97 |
+
nn.ReLU(),
|
98 |
+
basic_conv(196, 128, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
99 |
+
nn.BatchNorm2d(128),
|
100 |
+
nn.ReLU(),
|
101 |
+
nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
|
102 |
+
)
|
103 |
+
|
104 |
+
self.lastconv1 = nn.Sequential(
|
105 |
+
basic_conv(128 * 3, 128, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
106 |
+
nn.BatchNorm2d(128),
|
107 |
+
nn.ReLU(),
|
108 |
+
)
|
109 |
+
|
110 |
+
self.lastconv2 = nn.Sequential(
|
111 |
+
basic_conv(128, 64, kernel_size=3, stride=1, padding=1, bias=False, theta=theta),
|
112 |
+
nn.BatchNorm2d(64),
|
113 |
+
nn.ReLU(),
|
114 |
+
)
|
115 |
+
|
116 |
+
self.mu_head = nn.Sequential(
|
117 |
+
nn.Conv2d(64, 1, kernel_size=3, stride=1, padding=1, bias=False),
|
118 |
+
)
|
119 |
+
|
120 |
+
self.logvar_head = nn.Sequential(
|
121 |
+
nn.Conv2d(64, 1, kernel_size=3, stride=1, padding=1, bias=False),
|
122 |
+
)
|
123 |
+
|
124 |
+
self.downsample32x32 = nn.Upsample(size=(32, 32), mode='bilinear')
|
125 |
+
|
126 |
+
def _reparameterize(self, mu, logvar):
|
127 |
+
std = torch.exp(logvar).sqrt()
|
128 |
+
epsilon = torch.randn_like(std)
|
129 |
+
return mu + epsilon * std
|
130 |
+
|
131 |
+
def forward(self, x): # x [3, 256, 256]
|
132 |
+
|
133 |
+
x_input = x
|
134 |
+
x = self.conv1(x)
|
135 |
+
|
136 |
+
x_Block1 = self.Block1(x) # x [128, 128, 128]
|
137 |
+
x_Block1_32x32 = self.downsample32x32(x_Block1) # x [128, 32, 32]
|
138 |
+
|
139 |
+
x_Block2 = self.Block2(x_Block1) # x [128, 64, 64]
|
140 |
+
x_Block2_32x32 = self.downsample32x32(x_Block2) # x [128, 32, 32]
|
141 |
+
|
142 |
+
x_Block3 = self.Block3(x_Block2) # x [128, 32, 32]
|
143 |
+
x_Block3_32x32 = self.downsample32x32(x_Block3) # x [128, 32, 32]
|
144 |
+
|
145 |
+
x_concat = torch.cat((x_Block1_32x32, x_Block2_32x32, x_Block3_32x32), dim=1) # x [128*3, 32, 32]
|
146 |
+
|
147 |
+
# pdb.set_trace()
|
148 |
+
|
149 |
+
x = self.lastconv1(x_concat) # x [128, 32, 32]
|
150 |
+
x = self.lastconv2(x) # x [64, 32, 32]
|
151 |
+
|
152 |
+
mu = self.mu_head(x)
|
153 |
+
mu = mu.squeeze(1)
|
154 |
+
logvar = self.logvar_head(x)
|
155 |
+
logvar = logvar.squeeze(1)
|
156 |
+
embedding = self._reparameterize(mu, logvar)
|
157 |
+
|
158 |
+
return mu, logvar, embedding, x_concat, x_Block1, x_Block2, x_Block3, x_input
|
159 |
+
|
160 |
+
|
161 |
+
class depthnet_u(nn.Module):
|
162 |
+
|
163 |
+
def __init__(self):
|
164 |
+
super(depthnet_u, self).__init__()
|
165 |
+
|
166 |
+
self.conv1 = nn.Sequential(
|
167 |
+
nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False),
|
168 |
+
nn.BatchNorm2d(64),
|
169 |
+
nn.ReLU(),
|
170 |
+
)
|
171 |
+
|
172 |
+
self.Block1 = nn.Sequential(
|
173 |
+
nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1, bias=False),
|
174 |
+
nn.BatchNorm2d(128),
|
175 |
+
nn.ReLU(),
|
176 |
+
nn.Conv2d(128, 196, kernel_size=3, stride=1, padding=1, bias=False),
|
177 |
+
nn.BatchNorm2d(196),
|
178 |
+
nn.ReLU(),
|
179 |
+
nn.Conv2d(196, 128, kernel_size=3, stride=1, padding=1, bias=False),
|
180 |
+
nn.BatchNorm2d(128),
|
181 |
+
nn.ReLU(),
|
182 |
+
nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
|
183 |
+
|
184 |
+
)
|
185 |
+
|
186 |
+
self.Block2 = nn.Sequential(
|
187 |
+
nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1, bias=False),
|
188 |
+
nn.BatchNorm2d(128),
|
189 |
+
nn.ReLU(),
|
190 |
+
nn.Conv2d(128, 196, kernel_size=3, stride=1, padding=1, bias=False),
|
191 |
+
nn.BatchNorm2d(196),
|
192 |
+
nn.ReLU(),
|
193 |
+
nn.Conv2d(196, 128, kernel_size=3, stride=1, padding=1, bias=False),
|
194 |
+
nn.BatchNorm2d(128),
|
195 |
+
nn.ReLU(),
|
196 |
+
nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
|
197 |
+
)
|
198 |
+
|
199 |
+
self.Block3 = nn.Sequential(
|
200 |
+
nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1, bias=False),
|
201 |
+
nn.BatchNorm2d(128),
|
202 |
+
nn.ReLU(),
|
203 |
+
nn.Conv2d(128, 196, kernel_size=3, stride=1, padding=1, bias=False),
|
204 |
+
nn.BatchNorm2d(196),
|
205 |
+
nn.ReLU(),
|
206 |
+
nn.Conv2d(196, 128, kernel_size=3, stride=1, padding=1, bias=False),
|
207 |
+
nn.BatchNorm2d(128),
|
208 |
+
nn.ReLU(),
|
209 |
+
nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
|
210 |
+
)
|
211 |
+
|
212 |
+
self.lastconv1 = nn.Sequential(
|
213 |
+
nn.Conv2d(128 * 3, 128, kernel_size=3, stride=1, padding=1, bias=False),
|
214 |
+
nn.BatchNorm2d(128),
|
215 |
+
nn.ReLU(),
|
216 |
+
)
|
217 |
+
|
218 |
+
self.lastconv2 = nn.Sequential(
|
219 |
+
nn.Conv2d(128, 64, kernel_size=3, stride=1, padding=1, bias=False),
|
220 |
+
nn.BatchNorm2d(64),
|
221 |
+
nn.ReLU(),
|
222 |
+
)
|
223 |
+
|
224 |
+
self.mu_head = nn.Sequential(
|
225 |
+
nn.Conv2d(64, 1, kernel_size=3, stride=1, padding=1, bias=False),
|
226 |
+
)
|
227 |
+
|
228 |
+
self.logvar_head = nn.Sequential(
|
229 |
+
nn.Conv2d(64, 1, kernel_size=3, stride=1, padding=1, bias=False),
|
230 |
+
)
|
231 |
+
|
232 |
+
self.downsample32x32 = nn.Upsample(size=(32, 32), mode='bilinear')
|
233 |
+
|
234 |
+
def _reparameterize(self, mu, logvar):
|
235 |
+
std = torch.exp(logvar).sqrt()
|
236 |
+
epsilon = torch.randn_like(std)
|
237 |
+
return mu + epsilon * std
|
238 |
+
|
239 |
+
def forward(self, x): # x [3, 256, 256]
|
240 |
+
|
241 |
+
x_input = x
|
242 |
+
x = self.conv1(x)
|
243 |
+
|
244 |
+
x_Block1 = self.Block1(x) # x [128, 128, 128]
|
245 |
+
x_Block1_32x32 = self.downsample32x32(x_Block1) # x [128, 32, 32]
|
246 |
+
|
247 |
+
x_Block2 = self.Block2(x_Block1) # x [128, 64, 64]
|
248 |
+
x_Block2_32x32 = self.downsample32x32(x_Block2) # x [128, 32, 32]
|
249 |
+
|
250 |
+
x_Block3 = self.Block3(x_Block2) # x [128, 32, 32]
|
251 |
+
x_Block3_32x32 = self.downsample32x32(x_Block3) # x [128, 32, 32]
|
252 |
+
|
253 |
+
x_concat = torch.cat((x_Block1_32x32, x_Block2_32x32, x_Block3_32x32), dim=1) # x [128*3, 32, 32]
|
254 |
+
|
255 |
+
# pdb.set_trace()
|
256 |
+
|
257 |
+
x = self.lastconv1(x_concat) # x [128, 32, 32]
|
258 |
+
x = self.lastconv2(x) # x [64, 32, 32]
|
259 |
+
|
260 |
+
mu = self.mu_head(x)
|
261 |
+
mu = mu.squeeze(1)
|
262 |
+
logvar = self.logvar_head(x)
|
263 |
+
logvar = logvar.squeeze(1)
|
264 |
+
embedding = self._reparameterize(mu, logvar)
|
265 |
+
|
266 |
+
return mu, logvar, embedding, x_concat, x_Block1, x_Block2, x_Block3, x_input
|
DSDG/DUM/models/ResNet_u.py
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
|
3 |
+
import torch
|
4 |
+
import torch.nn.functional as F
|
5 |
+
import torch.utils.model_zoo as model_zoo
|
6 |
+
from torch import nn
|
7 |
+
from torch.nn import Parameter
|
8 |
+
import pdb
|
9 |
+
import numpy as np
|
10 |
+
|
11 |
+
|
12 |
+
class ResidualBlock(nn.Module):
|
13 |
+
def __init__(self, inchannel, outchannel, stride=1):
|
14 |
+
super(ResidualBlock, self).__init__()
|
15 |
+
self.left = nn.Sequential(
|
16 |
+
nn.Conv2d(inchannel, outchannel, kernel_size=3, stride=stride, padding=1, bias=False),
|
17 |
+
nn.BatchNorm2d(outchannel),
|
18 |
+
nn.ReLU(inplace=True),
|
19 |
+
nn.Conv2d(outchannel, outchannel, kernel_size=3, stride=1, padding=1, bias=False),
|
20 |
+
nn.BatchNorm2d(outchannel)
|
21 |
+
)
|
22 |
+
self.shortcut = nn.Sequential()
|
23 |
+
if stride != 1 or inchannel != outchannel:
|
24 |
+
self.shortcut = nn.Sequential(
|
25 |
+
nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=stride, bias=False),
|
26 |
+
nn.BatchNorm2d(outchannel)
|
27 |
+
)
|
28 |
+
|
29 |
+
def forward(self, x):
|
30 |
+
out = self.left(x)
|
31 |
+
out += self.shortcut(x)
|
32 |
+
out = F.relu(out)
|
33 |
+
return out
|
34 |
+
|
35 |
+
|
36 |
+
class ResNet(nn.Module):
|
37 |
+
def __init__(self, ResidualBlock = ResidualBlock):
|
38 |
+
super(ResNet, self).__init__()
|
39 |
+
self.inchannel = 64
|
40 |
+
self.conv1 = nn.Sequential(
|
41 |
+
nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False),
|
42 |
+
nn.BatchNorm2d(64),
|
43 |
+
nn.ReLU(),
|
44 |
+
)
|
45 |
+
self.layer1 = self.make_layer(ResidualBlock, 64, 2, stride=1)
|
46 |
+
self.layer2 = self.make_layer(ResidualBlock, 128, 2, stride=2)
|
47 |
+
self.layer3 = self.make_layer(ResidualBlock, 196, 2, stride=2)
|
48 |
+
self.layer4 = self.make_layer(ResidualBlock, 256, 2, stride=2)
|
49 |
+
self.lastconv1 = nn.Sequential(
|
50 |
+
nn.Conv2d(128 + 196 + 256, 128, kernel_size=3, stride=1, padding=1, bias=False),
|
51 |
+
nn.BatchNorm2d(128),
|
52 |
+
nn.ReLU(),
|
53 |
+
)
|
54 |
+
self.lastconv2 = nn.Sequential(
|
55 |
+
nn.Conv2d(128, 64, kernel_size=3, stride=1, padding=1, bias=False),
|
56 |
+
nn.BatchNorm2d(64),
|
57 |
+
nn.ReLU(),
|
58 |
+
)
|
59 |
+
self.lastconv3 = nn.Sequential(
|
60 |
+
nn.Conv2d(64, 1, kernel_size=3, stride=1, padding=1, bias=False),
|
61 |
+
nn.ReLU(),
|
62 |
+
)
|
63 |
+
self.downsample32x32 = nn.Upsample(size=(32, 32), mode='bilinear')
|
64 |
+
|
65 |
+
self.mu_head = nn.Sequential(
|
66 |
+
nn.Conv2d(64, 1, kernel_size=3, stride=1, padding=1, bias=False),
|
67 |
+
|
68 |
+
)
|
69 |
+
self.logvar_head = nn.Sequential(
|
70 |
+
nn.Conv2d(64, 1, kernel_size=3, stride=1, padding=1, bias=False),
|
71 |
+
|
72 |
+
)
|
73 |
+
|
74 |
+
def make_layer(self, block, channels, num_blocks, stride):
|
75 |
+
strides = [stride] + [1] * (num_blocks - 1) #strides=[1,1]
|
76 |
+
layers = []
|
77 |
+
for stride in strides:
|
78 |
+
layers.append(block(self.inchannel, channels, stride))
|
79 |
+
self.inchannel = channels
|
80 |
+
return nn.Sequential(*layers)
|
81 |
+
|
82 |
+
def _reparameterize(self, mu, logvar):
|
83 |
+
std = torch.exp(logvar).sqrt()
|
84 |
+
epsilon = torch.randn_like(std)
|
85 |
+
return mu + epsilon * std
|
86 |
+
|
87 |
+
def forward(self, x):
|
88 |
+
x_input = x
|
89 |
+
x = self.conv1(x)
|
90 |
+
x_block1 = self.layer1(x)
|
91 |
+
x_block2 = self.layer2(x_block1)
|
92 |
+
x_block2_32 = self.downsample32x32(x_block2)
|
93 |
+
x_block3 = self.layer3(x_block2)
|
94 |
+
x_block3_32 = self.downsample32x32(x_block3)
|
95 |
+
x_block4 = self.layer4(x_block3)
|
96 |
+
x_block4_32 = self.downsample32x32(x_block4)
|
97 |
+
|
98 |
+
x_concat = torch.cat((x_block2_32, x_block3_32, x_block4_32), dim=1)
|
99 |
+
|
100 |
+
x = self.lastconv1(x_concat)
|
101 |
+
x = self.lastconv2(x)
|
102 |
+
mu = self.mu_head(x)
|
103 |
+
mu = mu.squeeze(1)
|
104 |
+
logvar = self.logvar_head(x)
|
105 |
+
logvar = logvar.squeeze(1)
|
106 |
+
embedding = self._reparameterize(mu, logvar)
|
107 |
+
|
108 |
+
return mu, logvar, embedding, x_concat, x_block2, x_block3, x_block4, x_input
|
109 |
+
|
110 |
+
|
111 |
+
def ResNet18_u():
|
112 |
+
|
113 |
+
return ResNet(ResidualBlock)
|
114 |
+
|
DSDG/DUM/test.py
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import print_function, division
|
2 |
+
import torch
|
3 |
+
|
4 |
+
torch.set_printoptions(profile="full")
|
5 |
+
import matplotlib.pyplot as plt
|
6 |
+
import argparse, os
|
7 |
+
import numpy as np
|
8 |
+
import shutil
|
9 |
+
from torch.utils.data import DataLoader
|
10 |
+
from torchvision import transforms
|
11 |
+
|
12 |
+
from models.CDCNs_u import Conv2d_cd, CDCN_u
|
13 |
+
|
14 |
+
from Load_OULUNPUcrop_valtest import Spoofing_valtest, Normaliztion_valtest, ToTensor_valtest
|
15 |
+
|
16 |
+
import torch.optim as optim
|
17 |
+
|
18 |
+
from utils import performances
|
19 |
+
|
20 |
+
# Dataset root
|
21 |
+
|
22 |
+
val_image_dir = '/export2/home/wht/oulu_img_crop/dev_file_flod/'
|
23 |
+
test_image_dir = '/export2/home/wht/oulu_img_crop/test_file_flod/'
|
24 |
+
|
25 |
+
val_map_dir = '/export2/home/wht/oulu_img_crop/dev_depth_flod/'
|
26 |
+
test_map_dir = '/export2/home/wht/oulu_img_crop/test_depth_flod/'
|
27 |
+
|
28 |
+
val_list = '/export2/home/wht/oulu_img_crop/protocols/Protocol_1/Dev.txt'
|
29 |
+
test_list = '/export2/home/wht/oulu_img_crop/protocols/Protocol_1/Test.txt'
|
30 |
+
|
31 |
+
|
32 |
+
# main function
|
33 |
+
def test():
|
34 |
+
# GPU & log file --> if use DataParallel, please comment this command
|
35 |
+
os.environ["CUDA_VISIBLE_DEVICES"] = '0, 1, 2, 3'
|
36 |
+
|
37 |
+
isExists = os.path.exists(args.log)
|
38 |
+
if not isExists:
|
39 |
+
os.makedirs(args.log)
|
40 |
+
log_file = open(args.log + '/' + args.log + '_log_P1.txt', 'w')
|
41 |
+
|
42 |
+
log_file.write('Oulu-NPU, P1:\n ')
|
43 |
+
log_file.flush()
|
44 |
+
|
45 |
+
print('test!\n')
|
46 |
+
log_file.write('test!\n')
|
47 |
+
log_file.flush()
|
48 |
+
|
49 |
+
model = CDCN_u(basic_conv=Conv2d_cd, theta=0.7)
|
50 |
+
# model = ResNet18_u()
|
51 |
+
|
52 |
+
model = model.cuda()
|
53 |
+
model = torch.nn.DataParallel(model)
|
54 |
+
model.load_state_dict(torch.load('./DUM/checkpoint/CDCN_U_P1.pkl', map_location='cuda:0'))
|
55 |
+
|
56 |
+
print(model)
|
57 |
+
|
58 |
+
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=0.00005)
|
59 |
+
|
60 |
+
for epoch in range(args.epochs):
|
61 |
+
|
62 |
+
model.eval()
|
63 |
+
|
64 |
+
with torch.no_grad():
|
65 |
+
###########################################
|
66 |
+
''' val '''
|
67 |
+
###########################################
|
68 |
+
# val for threshold
|
69 |
+
val_data = Spoofing_valtest(val_list, val_image_dir, val_map_dir,
|
70 |
+
transform=transforms.Compose([Normaliztion_valtest(), ToTensor_valtest()]))
|
71 |
+
dataloader_val = DataLoader(val_data, batch_size=1, shuffle=False, num_workers=4)
|
72 |
+
|
73 |
+
map_score_list = []
|
74 |
+
|
75 |
+
for i, sample_batched in enumerate(dataloader_val):
|
76 |
+
# get the inputs
|
77 |
+
inputs, spoof_label = sample_batched['image_x'].cuda(), sample_batched['spoofing_label'].cuda()
|
78 |
+
val_maps = sample_batched['val_map_x'].cuda() # binary map from PRNet
|
79 |
+
|
80 |
+
optimizer.zero_grad()
|
81 |
+
|
82 |
+
# pdb.set_trace()
|
83 |
+
map_score = 0.0
|
84 |
+
for frame_t in range(inputs.shape[1]):
|
85 |
+
mu, logvar, map_x, x_concat, x_Block1, x_Block2, x_Block3, x_input = model(
|
86 |
+
inputs[:, frame_t, :, :, :])
|
87 |
+
score_norm = torch.sum(mu) / torch.sum(val_maps[:, frame_t, :, :])
|
88 |
+
map_score += score_norm
|
89 |
+
|
90 |
+
map_score = map_score / inputs.shape[1]
|
91 |
+
|
92 |
+
map_score_list.append('{} {}\n'.format(map_score, spoof_label[0][0]))
|
93 |
+
# pdb.set_trace()
|
94 |
+
map_score_val_filename = args.log + '/' + args.log + '_map_score_val.txt'
|
95 |
+
with open(map_score_val_filename, 'w') as file:
|
96 |
+
file.writelines(map_score_list)
|
97 |
+
|
98 |
+
###########################################
|
99 |
+
''' test '''
|
100 |
+
##########################################
|
101 |
+
# test for ACC
|
102 |
+
test_data = Spoofing_valtest(test_list, test_image_dir, test_map_dir,
|
103 |
+
transform=transforms.Compose([Normaliztion_valtest(), ToTensor_valtest()]))
|
104 |
+
dataloader_test = DataLoader(test_data, batch_size=1, shuffle=False, num_workers=4)
|
105 |
+
|
106 |
+
map_score_list = []
|
107 |
+
|
108 |
+
for i, sample_batched in enumerate(dataloader_test):
|
109 |
+
# get the inputs
|
110 |
+
inputs, spoof_label = sample_batched['image_x'].cuda(), sample_batched['spoofing_label'].cuda()
|
111 |
+
test_maps = sample_batched['val_map_x'].cuda()
|
112 |
+
|
113 |
+
optimizer.zero_grad()
|
114 |
+
|
115 |
+
# pdb.set_trace()
|
116 |
+
map_score = 0.0
|
117 |
+
for frame_t in range(inputs.shape[1]):
|
118 |
+
mu, logvar, map_x, x_concat, x_Block1, x_Block2, x_Block3, x_input = model(
|
119 |
+
inputs[:, frame_t, :, :, :])
|
120 |
+
|
121 |
+
score_norm = torch.sum(mu) / torch.sum(test_maps[:, frame_t, :, :])
|
122 |
+
map_score += score_norm
|
123 |
+
|
124 |
+
map_score = map_score / inputs.shape[1]
|
125 |
+
|
126 |
+
map_score_list.append('{} {}\n'.format(map_score, spoof_label[0][0]))
|
127 |
+
|
128 |
+
map_score_test_filename = args.log + '/' + args.log + '_map_score_test.txt'
|
129 |
+
with open(map_score_test_filename, 'w') as file:
|
130 |
+
file.writelines(map_score_list)
|
131 |
+
|
132 |
+
#############################################################
|
133 |
+
# performance measurement both val and test
|
134 |
+
#############################################################
|
135 |
+
val_threshold, test_threshold, val_ACC, val_ACER, test_ACC, test_APCER, test_BPCER, test_ACER, test_ACER_test_threshold = performances(
|
136 |
+
map_score_val_filename, map_score_test_filename)
|
137 |
+
|
138 |
+
print('epoch:%d, Val: val_threshold= %.4f, val_ACC= %.4f, val_ACER= %.4f' % (
|
139 |
+
epoch + 1, val_threshold, val_ACC, val_ACER))
|
140 |
+
log_file.write('\n epoch:%d, Val: val_threshold= %.4f, val_ACC= %.4f, val_ACER= %.4f \n' % (
|
141 |
+
epoch + 1, val_threshold, val_ACC, val_ACER))
|
142 |
+
|
143 |
+
print('epoch:%d, Test: ACC= %.4f, APCER= %.4f, BPCER= %.4f, ACER= %.4f' % (
|
144 |
+
epoch + 1, test_ACC, test_APCER, test_BPCER, test_ACER))
|
145 |
+
log_file.write('epoch:%d, Test: ACC= %.4f, APCER= %.4f, BPCER= %.4f, ACER= %.4f \n' % (
|
146 |
+
epoch + 1, test_ACC, test_APCER, test_BPCER, test_ACER))
|
147 |
+
log_file.flush()
|
148 |
+
|
149 |
+
print('Finished Training')
|
150 |
+
log_file.close()
|
151 |
+
|
152 |
+
|
153 |
+
if __name__ == "__main__":
|
154 |
+
parser = argparse.ArgumentParser(description="save quality using landmarkpose model")
|
155 |
+
parser.add_argument('--gpus', type=str, default='0,1,2,3', help='the gpu id used for predict')
|
156 |
+
parser.add_argument('--lr', type=float, default=0.001, help='initial learning rate')
|
157 |
+
parser.add_argument('--batchsize', type=int, default=32, help='initial batchsize')
|
158 |
+
parser.add_argument('--step_size', type=int, default=500, help='how many epochs lr decays once') # 500
|
159 |
+
parser.add_argument('--gamma', type=float, default=0.5, help='gamma of optim.lr_scheduler.StepLR, decay of lr')
|
160 |
+
parser.add_argument('--kl_lambda', type=float, default=0.001, help='')
|
161 |
+
parser.add_argument('--echo_batches', type=int, default=50, help='how many batches display once') # 50
|
162 |
+
parser.add_argument('--epochs', type=int, default=1, help='total training epochs')
|
163 |
+
parser.add_argument('--log', type=str, default="CDCN_U_P1_test", help='log and save model name')
|
164 |
+
parser.add_argument('--finetune', action='store_true', default=False, help='whether finetune other models')
|
165 |
+
parser.add_argument('--test', action='store_true', default=True, help='')
|
166 |
+
|
167 |
+
args = parser.parse_args()
|
168 |
+
test()
|
DSDG/DUM/train.py
ADDED
@@ -0,0 +1,289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import print_function, division
|
2 |
+
import torch
|
3 |
+
import matplotlib.pyplot as plt
|
4 |
+
import argparse, os
|
5 |
+
import numpy as np
|
6 |
+
from torch.utils.data import DataLoader
|
7 |
+
from torchvision import transforms
|
8 |
+
|
9 |
+
from models.CDCNs_u import Conv2d_cd, CDCN_u
|
10 |
+
|
11 |
+
from Load_OULUNPUcrop_train import Spoofing_train_g, SeparateBatchSampler, Normaliztion, ToTensor, \
|
12 |
+
RandomHorizontalFlip, Cutout, RandomErasing
|
13 |
+
from Load_OULUNPUcrop_valtest import Spoofing_valtest, Normaliztion_valtest, ToTensor_valtest
|
14 |
+
|
15 |
+
import torch.nn.functional as F
|
16 |
+
import torch.nn as nn
|
17 |
+
import torch.optim as optim
|
18 |
+
|
19 |
+
from utils import AvgrageMeter, performances
|
20 |
+
|
21 |
+
# Dataset root
|
22 |
+
train_image_dir = '/export2/home/wht/oulu_img_crop/train_file_flod/'
|
23 |
+
val_image_dir = '/export2/home/wht/oulu_img_crop/dev_file_flod/'
|
24 |
+
test_image_dir = '/export2/home/wht/oulu_img_crop/test_file_flod/'
|
25 |
+
|
26 |
+
train_map_dir = '/export2/home/wht/oulu_img_crop/train_depth_flod/'
|
27 |
+
val_map_dir = '/export2/home/wht/oulu_img_crop/dev_depth_flod/'
|
28 |
+
test_map_dir = '/export2/home/wht/oulu_img_crop/test_depth_flod/'
|
29 |
+
|
30 |
+
train_list = '/export2/home/wht/oulu_img_crop/protocols/Protocol_1/Train_g.txt'
|
31 |
+
val_list = '/export2/home/wht/oulu_img_crop/protocols/Protocol_1/Dev.txt'
|
32 |
+
test_list = '/export2/home/wht/oulu_img_crop/protocols/Protocol_1/Test.txt'
|
33 |
+
|
34 |
+
|
35 |
+
def contrast_depth_conv(input):
|
36 |
+
''' compute contrast depth in both of (out, label) '''
|
37 |
+
'''
|
38 |
+
input 32x32
|
39 |
+
output 8x32x32
|
40 |
+
'''
|
41 |
+
|
42 |
+
kernel_filter_list = [
|
43 |
+
[[1, 0, 0], [0, -1, 0], [0, 0, 0]], [[0, 1, 0], [0, -1, 0], [0, 0, 0]], [[0, 0, 1], [0, -1, 0], [0, 0, 0]],
|
44 |
+
[[0, 0, 0], [1, -1, 0], [0, 0, 0]], [[0, 0, 0], [0, -1, 1], [0, 0, 0]],
|
45 |
+
[[0, 0, 0], [0, -1, 0], [1, 0, 0]], [[0, 0, 0], [0, -1, 0], [0, 1, 0]], [[0, 0, 0], [0, -1, 0], [0, 0, 1]]
|
46 |
+
]
|
47 |
+
|
48 |
+
kernel_filter = np.array(kernel_filter_list, np.float32)
|
49 |
+
|
50 |
+
kernel_filter = torch.from_numpy(kernel_filter.astype(np.float)).float().cuda()
|
51 |
+
# weights (in_channel, out_channel, kernel, kernel)
|
52 |
+
kernel_filter = kernel_filter.unsqueeze(dim=1)
|
53 |
+
|
54 |
+
input = input.unsqueeze(dim=1).expand(input.shape[0], 8, input.shape[1], input.shape[2])
|
55 |
+
|
56 |
+
contrast_depth = F.conv2d(input, weight=kernel_filter, groups=8)
|
57 |
+
|
58 |
+
return contrast_depth
|
59 |
+
|
60 |
+
|
61 |
+
class Contrast_depth_loss(nn.Module):
|
62 |
+
def __init__(self):
|
63 |
+
super(Contrast_depth_loss, self).__init__()
|
64 |
+
return
|
65 |
+
|
66 |
+
def forward(self, out, label):
|
67 |
+
contrast_out = contrast_depth_conv(out)
|
68 |
+
contrast_label = contrast_depth_conv(label)
|
69 |
+
|
70 |
+
criterion_MSE = nn.MSELoss().cuda()
|
71 |
+
|
72 |
+
loss = criterion_MSE(contrast_out, contrast_label)
|
73 |
+
|
74 |
+
return loss
|
75 |
+
|
76 |
+
|
77 |
+
def train_test():
|
78 |
+
isExists = os.path.exists(args.log)
|
79 |
+
if not isExists:
|
80 |
+
os.makedirs(args.log)
|
81 |
+
log_file = open(args.log + '/' + args.log + '_log_P1.txt', 'a')
|
82 |
+
|
83 |
+
log_file.write('Oulu-NPU, P1:\n ')
|
84 |
+
log_file.flush()
|
85 |
+
|
86 |
+
print('train from scratch!\n')
|
87 |
+
log_file.write('train from scratch!\n')
|
88 |
+
log_file.write('lr:%.6f, lamda_kl:%.6f , batchsize:%d\n' % (args.lr, args.kl_lambda, args.batchsize))
|
89 |
+
log_file.flush()
|
90 |
+
|
91 |
+
model = CDCN_u(basic_conv=Conv2d_cd, theta=0.7)
|
92 |
+
# model = ResNet18_u()
|
93 |
+
|
94 |
+
model = model.cuda()
|
95 |
+
model = torch.nn.DataParallel(model)
|
96 |
+
|
97 |
+
lr = args.lr
|
98 |
+
optimizer = optim.Adam(model.parameters(), lr=lr, weight_decay=0.00005)
|
99 |
+
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=args.step_size, gamma=args.gamma)
|
100 |
+
|
101 |
+
print(model)
|
102 |
+
|
103 |
+
criterion_absolute_loss = nn.MSELoss().cuda()
|
104 |
+
criterion_contrastive_loss = Contrast_depth_loss().cuda()
|
105 |
+
|
106 |
+
for epoch in range(args.epochs):
|
107 |
+
if (epoch + 1) % args.step_size == 0:
|
108 |
+
lr *= args.gamma
|
109 |
+
|
110 |
+
loss_absolute_real = AvgrageMeter()
|
111 |
+
loss_absolute_fake = AvgrageMeter()
|
112 |
+
loss_contra_real = AvgrageMeter()
|
113 |
+
loss_contra_fake = AvgrageMeter()
|
114 |
+
loss_kl_real = AvgrageMeter()
|
115 |
+
loss_kl_fake = AvgrageMeter()
|
116 |
+
|
117 |
+
###########################################
|
118 |
+
''' train '''
|
119 |
+
###########################################
|
120 |
+
model.train()
|
121 |
+
|
122 |
+
# load random 16-frame clip data every epoch
|
123 |
+
train_data = Spoofing_train_g(train_list, train_image_dir, train_map_dir,
|
124 |
+
transform=transforms.Compose(
|
125 |
+
[RandomErasing(), RandomHorizontalFlip(), ToTensor(), Cutout(),
|
126 |
+
Normaliztion()]))
|
127 |
+
train_real_idx, train_fake_idx = train_data.get_idx()
|
128 |
+
batch_sampler = SeparateBatchSampler(train_real_idx, train_fake_idx, batch_size=args.batchsize, ratio=args.ratio)
|
129 |
+
dataloader_train = DataLoader(train_data, num_workers=8, batch_sampler=batch_sampler)
|
130 |
+
|
131 |
+
for i, sample_batched in enumerate(dataloader_train):
|
132 |
+
# get the inputs
|
133 |
+
inputs, map_label, spoof_label = sample_batched['image_x'].cuda(), sample_batched['map_x'].cuda(), \
|
134 |
+
sample_batched['spoofing_label'].cuda()
|
135 |
+
|
136 |
+
optimizer.zero_grad()
|
137 |
+
|
138 |
+
# forward + backward + optimize
|
139 |
+
mu, logvar, map_x, x_concat, x_Block1, x_Block2, x_Block3, x_input = model(inputs)
|
140 |
+
|
141 |
+
mu_real = mu[:int(args.batchsize * args.ratio), :, :]
|
142 |
+
logvar_real = logvar[:int(args.batchsize * args.ratio), :, :]
|
143 |
+
map_x_real = map_x[:int(args.batchsize * args.ratio), :, :]
|
144 |
+
map_label_real = map_label[:int(args.batchsize * args.ratio), :, :]
|
145 |
+
|
146 |
+
absolute_loss_real = criterion_absolute_loss(map_x_real, map_label_real)
|
147 |
+
contrastive_loss_real = criterion_contrastive_loss(map_x_real, map_label_real)
|
148 |
+
kl_loss_real = -(1 + logvar_real - (mu_real - map_label_real).pow(2) - logvar_real.exp()) / 2
|
149 |
+
kl_loss_real = kl_loss_real.sum(dim=1).sum(dim=1).mean()
|
150 |
+
kl_loss_real = args.kl_lambda * kl_loss_real
|
151 |
+
|
152 |
+
mu_fake = mu[int(args.batchsize * args.ratio):, :, :]
|
153 |
+
logvar_fake = logvar[int(args.batchsize * args.ratio):, :, :]
|
154 |
+
map_x_fake = map_x[int(args.batchsize * args.ratio):, :, :]
|
155 |
+
map_label_fake = map_label[int(args.batchsize * args.ratio):, :, :]
|
156 |
+
|
157 |
+
absolute_loss_fake = 0.1 * criterion_absolute_loss(map_x_fake, map_label_fake)
|
158 |
+
contrastive_loss_fake = 0.1 * criterion_contrastive_loss(map_x_fake, map_label_fake)
|
159 |
+
kl_loss_fake = -(1 + logvar_fake - (mu_fake - map_label_fake).pow(2) - logvar_fake.exp()) / 2
|
160 |
+
kl_loss_fake = kl_loss_fake.sum(dim=1).sum(dim=1).mean()
|
161 |
+
kl_loss_fake = 0.1 * args.kl_lambda * kl_loss_fake
|
162 |
+
|
163 |
+
absolute_loss = absolute_loss_real + absolute_loss_fake
|
164 |
+
contrastive_loss = contrastive_loss_real + contrastive_loss_fake
|
165 |
+
kl_loss = kl_loss_real + kl_loss_fake
|
166 |
+
|
167 |
+
loss = absolute_loss + contrastive_loss + kl_loss
|
168 |
+
|
169 |
+
loss.backward()
|
170 |
+
|
171 |
+
optimizer.step()
|
172 |
+
|
173 |
+
n = inputs.size(0)
|
174 |
+
loss_absolute_real.update(absolute_loss_real.data, n)
|
175 |
+
loss_absolute_fake.update(absolute_loss_fake.data, n)
|
176 |
+
loss_contra_real.update(contrastive_loss_real.data, n)
|
177 |
+
loss_contra_fake.update(contrastive_loss_fake.data, n)
|
178 |
+
loss_kl_real.update(kl_loss_real.data, n)
|
179 |
+
loss_kl_fake.update(kl_loss_fake.data, n)
|
180 |
+
|
181 |
+
scheduler.step()
|
182 |
+
# whole epoch average
|
183 |
+
print(
|
184 |
+
'epoch:%d, Train: Absolute_loss: real=%.4f,fake=%.4f, '
|
185 |
+
'Contrastive_loss: real=%.4f,fake=%.4f, kl_loss: real=%.4f,fake=%.4f' % (
|
186 |
+
epoch + 1, loss_absolute_real.avg, loss_absolute_fake.avg, loss_contra_real.avg, loss_contra_fake.avg,
|
187 |
+
loss_kl_real.avg, loss_kl_fake.avg))
|
188 |
+
|
189 |
+
# validation/test
|
190 |
+
if epoch < 200:
|
191 |
+
epoch_test = 200
|
192 |
+
else:
|
193 |
+
epoch_test = 50
|
194 |
+
# epoch_test = 1
|
195 |
+
if epoch % epoch_test == epoch_test - 1:
|
196 |
+
model.eval()
|
197 |
+
|
198 |
+
with torch.no_grad():
|
199 |
+
###########################################
|
200 |
+
''' val '''
|
201 |
+
###########################################
|
202 |
+
# val for threshold
|
203 |
+
val_data = Spoofing_valtest(val_list, val_image_dir, val_map_dir,
|
204 |
+
transform=transforms.Compose([Normaliztion_valtest(), ToTensor_valtest()]))
|
205 |
+
dataloader_val = DataLoader(val_data, batch_size=1, shuffle=False, num_workers=4)
|
206 |
+
|
207 |
+
map_score_list = []
|
208 |
+
|
209 |
+
for i, sample_batched in enumerate(dataloader_val):
|
210 |
+
# get the inputs
|
211 |
+
inputs, spoof_label = sample_batched['image_x'].cuda(), sample_batched['spoofing_label'].cuda()
|
212 |
+
val_maps = sample_batched['val_map_x'].cuda() # binary map from PRNet
|
213 |
+
|
214 |
+
optimizer.zero_grad()
|
215 |
+
|
216 |
+
mu, logvar, map_x, x_concat, x_Block1, x_Block2, x_Block3, x_input = model(inputs.squeeze(0))
|
217 |
+
score_norm = mu.sum(dim=1).sum(dim=1) / val_maps.squeeze(0).sum(dim=1).sum(dim=1)
|
218 |
+
map_score = score_norm.mean()
|
219 |
+
map_score_list.append('{} {}\n'.format(map_score, spoof_label[0][0]))
|
220 |
+
|
221 |
+
map_score_val_filename = args.log + '/' + args.log + '_map_score_val.txt'
|
222 |
+
with open(map_score_val_filename, 'w') as file:
|
223 |
+
file.writelines(map_score_list)
|
224 |
+
|
225 |
+
###########################################
|
226 |
+
''' test '''
|
227 |
+
##########################################
|
228 |
+
# test for ACC
|
229 |
+
test_data = Spoofing_valtest(test_list, test_image_dir, test_map_dir,
|
230 |
+
transform=transforms.Compose([Normaliztion_valtest(), ToTensor_valtest()]))
|
231 |
+
dataloader_test = DataLoader(test_data, batch_size=1, shuffle=False, num_workers=4)
|
232 |
+
|
233 |
+
map_score_list = []
|
234 |
+
|
235 |
+
for i, sample_batched in enumerate(dataloader_test):
|
236 |
+
# get the inputs
|
237 |
+
inputs, spoof_label = sample_batched['image_x'].cuda(), sample_batched['spoofing_label'].cuda()
|
238 |
+
test_maps = sample_batched['val_map_x'].cuda()
|
239 |
+
|
240 |
+
optimizer.zero_grad()
|
241 |
+
mu, logvar, map_x, x_concat, x_Block1, x_Block2, x_Block3, x_input = model(inputs.squeeze(0))
|
242 |
+
score_norm = mu.sum(dim=1).sum(dim=1) / test_maps.squeeze(0).sum(dim=1).sum(dim=1)
|
243 |
+
map_score = score_norm.mean()
|
244 |
+
map_score_list.append('{} {}\n'.format(map_score, spoof_label[0][0]))
|
245 |
+
|
246 |
+
map_score_test_filename = args.log + '/' + args.log + '_map_score_test.txt'
|
247 |
+
with open(map_score_test_filename, 'w') as file:
|
248 |
+
file.writelines(map_score_list)
|
249 |
+
|
250 |
+
#############################################################
|
251 |
+
# performance measurement both val and test
|
252 |
+
#############################################################
|
253 |
+
val_threshold, test_threshold, val_ACC, val_ACER, test_ACC, test_APCER, test_BPCER, test_ACER, test_ACER_test_threshold = performances(
|
254 |
+
map_score_val_filename, map_score_test_filename)
|
255 |
+
|
256 |
+
print('epoch:%d, Val: val_threshold= %.4f, val_ACC= %.4f, val_ACER= %.4f' % (
|
257 |
+
epoch + 1, val_threshold, val_ACC, val_ACER))
|
258 |
+
log_file.write('\n epoch:%d, Val: val_threshold= %.4f, val_ACC= %.4f, val_ACER= %.4f \n' % (
|
259 |
+
epoch + 1, val_threshold, val_ACC, val_ACER))
|
260 |
+
|
261 |
+
print('epoch:%d, Test: ACC= %.4f, APCER= %.4f, BPCER= %.4f, ACER= %.4f' % (
|
262 |
+
epoch + 1, test_ACC, test_APCER, test_BPCER, test_ACER))
|
263 |
+
log_file.write('epoch:%d, Test: ACC= %.4f, APCER= %.4f, BPCER= %.4f, ACER= %.4f \n' % (
|
264 |
+
epoch + 1, test_ACC, test_APCER, test_BPCER, test_ACER))
|
265 |
+
log_file.flush()
|
266 |
+
|
267 |
+
if epoch % epoch_test == epoch_test - 1:
|
268 |
+
# save the model until the next improvement
|
269 |
+
torch.save(model.state_dict(), args.log + '/' + args.log + '_%d.pkl' % (epoch + 1))
|
270 |
+
|
271 |
+
print('Finished Training')
|
272 |
+
log_file.close()
|
273 |
+
|
274 |
+
if __name__ == "__main__":
|
275 |
+
parser = argparse.ArgumentParser(description="save quality using landmarkpose model")
|
276 |
+
parser.add_argument('--gpus', type=str, default='0, 1, 2, 3', help='the gpu id used for predict')
|
277 |
+
parser.add_argument('--lr', type=float, default=0.0001, help='initial learning rate')
|
278 |
+
parser.add_argument('--batchsize', type=int, default=64, help='initial batchsize')
|
279 |
+
parser.add_argument('--step_size', type=int, default=500, help='how many epochs lr decays once') # 500
|
280 |
+
parser.add_argument('--gamma', type=float, default=0.5, help='gamma of optim.lr_scheduler.StepLR, decay of lr')
|
281 |
+
parser.add_argument('--kl_lambda', type=float, default=0.001, help='')
|
282 |
+
parser.add_argument('--ratio', type=float, default=0.75, help='real and fake in batchsize ')
|
283 |
+
parser.add_argument('--echo_batches', type=int, default=50, help='how many batches display once') # 50
|
284 |
+
parser.add_argument('--epochs', type=int, default=1600, help='total training epochs')
|
285 |
+
parser.add_argument('--log', type=str, default="CDCN_U_P1", help='log and save model name')
|
286 |
+
parser.add_argument('--finetune', action='store_true', default=False, help='whether finetune other models')
|
287 |
+
|
288 |
+
args = parser.parse_args()
|
289 |
+
train_test()
|
DSDG/DUM/utils.py
ADDED
@@ -0,0 +1,431 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import numpy as np
|
3 |
+
import torch
|
4 |
+
import shutil
|
5 |
+
import torchvision.transforms as transforms
|
6 |
+
from torch.autograd import Variable
|
7 |
+
import sklearn
|
8 |
+
from sklearn import metrics
|
9 |
+
from sklearn.metrics import roc_curve, auc
|
10 |
+
import pdb
|
11 |
+
|
12 |
+
|
13 |
+
class AvgrageMeter(object):
|
14 |
+
|
15 |
+
def __init__(self):
|
16 |
+
self.reset()
|
17 |
+
|
18 |
+
def reset(self):
|
19 |
+
self.avg = 0
|
20 |
+
self.sum = 0
|
21 |
+
self.cnt = 0
|
22 |
+
|
23 |
+
def update(self, val, n=1):
|
24 |
+
self.sum += val * n
|
25 |
+
self.cnt += n
|
26 |
+
self.avg = self.sum / self.cnt
|
27 |
+
|
28 |
+
|
29 |
+
def accuracy(output, target, topk=(1,)):
|
30 |
+
maxk = max(topk)
|
31 |
+
batch_size = target.size(0)
|
32 |
+
|
33 |
+
_, pred = output.topk(maxk, 1, True, True)
|
34 |
+
pred = pred.t()
|
35 |
+
correct = pred.eq(target.view(1, -1).expand_as(pred))
|
36 |
+
|
37 |
+
res = []
|
38 |
+
for k in topk:
|
39 |
+
correct_k = correct[:k].view(-1).float().sum(0)
|
40 |
+
res.append(correct_k.mul_(100.0 / batch_size))
|
41 |
+
return res
|
42 |
+
|
43 |
+
|
44 |
+
def get_threshold(score_file):
|
45 |
+
with open(score_file, 'r') as file:
|
46 |
+
lines = file.readlines()
|
47 |
+
|
48 |
+
data = []
|
49 |
+
count = 0.0
|
50 |
+
num_real = 0.0
|
51 |
+
num_fake = 0.0
|
52 |
+
for line in lines:
|
53 |
+
count += 1
|
54 |
+
tokens = line.split()
|
55 |
+
angle = float(tokens[0])
|
56 |
+
# pdb.set_trace()
|
57 |
+
type = int(tokens[1])
|
58 |
+
data.append({'map_score': angle, 'label': type})
|
59 |
+
if type == 1:
|
60 |
+
num_real += 1
|
61 |
+
else:
|
62 |
+
num_fake += 1
|
63 |
+
|
64 |
+
min_error = count # account ACER (or ACC)
|
65 |
+
min_threshold = 0.0
|
66 |
+
min_ACC = 0.0
|
67 |
+
min_ACER = 0.0
|
68 |
+
min_APCER = 0.0
|
69 |
+
min_BPCER = 0.0
|
70 |
+
|
71 |
+
for d in data:
|
72 |
+
threshold = d['map_score']
|
73 |
+
|
74 |
+
type1 = len([s for s in data if s['map_score'] <= threshold and s['label'] == 1])
|
75 |
+
type2 = len([s for s in data if s['map_score'] > threshold and s['label'] == 0])
|
76 |
+
|
77 |
+
ACC = 1 - (type1 + type2) / count
|
78 |
+
APCER = type2 / num_fake
|
79 |
+
BPCER = type1 / num_real
|
80 |
+
ACER = (APCER + BPCER) / 2.0
|
81 |
+
|
82 |
+
if ACER < min_error:
|
83 |
+
min_error = ACER
|
84 |
+
min_threshold = threshold
|
85 |
+
min_ACC = ACC
|
86 |
+
min_ACER = ACER
|
87 |
+
min_APCER = APCER
|
88 |
+
min_BPCER = min_BPCER
|
89 |
+
|
90 |
+
# print(min_error, min_threshold)
|
91 |
+
return min_threshold, min_ACC, min_APCER, min_BPCER, min_ACER
|
92 |
+
|
93 |
+
|
94 |
+
def test_threshold_based(threshold, score_file):
|
95 |
+
with open(score_file, 'r') as file:
|
96 |
+
lines = file.readlines()
|
97 |
+
|
98 |
+
data = []
|
99 |
+
count = 0.0
|
100 |
+
num_real = 0.0
|
101 |
+
num_fake = 0.0
|
102 |
+
for line in lines:
|
103 |
+
count += 1
|
104 |
+
tokens = line.split()
|
105 |
+
angle = float(tokens[0])
|
106 |
+
type = int(tokens[1])
|
107 |
+
data.append({'map_score': angle, 'label': type})
|
108 |
+
if type == 1:
|
109 |
+
num_real += 1
|
110 |
+
else:
|
111 |
+
num_fake += 1
|
112 |
+
|
113 |
+
type1 = len([s for s in data if s['map_score'] <= threshold and s['label'] == 1])
|
114 |
+
type2 = len([s for s in data if s['map_score'] > threshold and s['label'] == 0])
|
115 |
+
|
116 |
+
ACC = 1 - (type1 + type2) / count
|
117 |
+
APCER = type2 / num_fake
|
118 |
+
BPCER = type1 / num_real
|
119 |
+
ACER = (APCER + BPCER) / 2.0
|
120 |
+
|
121 |
+
return ACC, APCER, BPCER, ACER
|
122 |
+
|
123 |
+
|
124 |
+
def get_err_threhold(fpr, tpr, threshold):
|
125 |
+
RightIndex = (tpr + (1 - fpr) - 1)
|
126 |
+
right_index = np.argmax(RightIndex)
|
127 |
+
best_th = threshold[right_index]
|
128 |
+
err = fpr[right_index]
|
129 |
+
|
130 |
+
differ_tpr_fpr_1 = tpr + fpr - 1.0
|
131 |
+
|
132 |
+
right_index = np.argmin(np.abs(differ_tpr_fpr_1))
|
133 |
+
best_th = threshold[right_index]
|
134 |
+
err = fpr[right_index]
|
135 |
+
|
136 |
+
# print(err, best_th)
|
137 |
+
return err, best_th
|
138 |
+
|
139 |
+
|
140 |
+
# def performances(dev_scores, dev_labels, test_scores, test_labels):
|
141 |
+
def performances(map_score_val_filename, map_score_test_filename):
|
142 |
+
# val
|
143 |
+
with open(map_score_val_filename, 'r') as file:
|
144 |
+
lines = file.readlines()
|
145 |
+
val_scores = []
|
146 |
+
val_labels = []
|
147 |
+
data = []
|
148 |
+
count = 0.0
|
149 |
+
num_real = 0.0
|
150 |
+
num_fake = 0.0
|
151 |
+
for line in lines:
|
152 |
+
count += 1
|
153 |
+
tokens = line.split()
|
154 |
+
score = float(tokens[0])
|
155 |
+
label = float(tokens[1]) # label = int(tokens[1])
|
156 |
+
val_scores.append(score)
|
157 |
+
val_labels.append(label)
|
158 |
+
data.append({'map_score': score, 'label': label})
|
159 |
+
if label == 1:
|
160 |
+
num_real += 1
|
161 |
+
else:
|
162 |
+
num_fake += 1
|
163 |
+
|
164 |
+
fpr, tpr, threshold = roc_curve(val_labels, val_scores, pos_label=1)
|
165 |
+
val_err, val_threshold = get_err_threhold(fpr, tpr, threshold)
|
166 |
+
|
167 |
+
type1 = len([s for s in data if s['map_score'] <= val_threshold and s['label'] == 1])
|
168 |
+
type2 = len([s for s in data if s['map_score'] > val_threshold and s['label'] == 0])
|
169 |
+
|
170 |
+
val_ACC = 1 - (type1 + type2) / count
|
171 |
+
val_APCER = type2 / num_fake
|
172 |
+
val_BPCER = type1 / num_real
|
173 |
+
val_ACER = (val_APCER + val_BPCER) / 2.0
|
174 |
+
|
175 |
+
# test
|
176 |
+
with open(map_score_test_filename, 'r') as file2:
|
177 |
+
lines = file2.readlines()
|
178 |
+
test_scores = []
|
179 |
+
test_labels = []
|
180 |
+
data = []
|
181 |
+
count = 0.0
|
182 |
+
num_real = 0.0
|
183 |
+
num_fake = 0.0
|
184 |
+
for line in lines:
|
185 |
+
count += 1
|
186 |
+
tokens = line.split()
|
187 |
+
score = float(tokens[0])
|
188 |
+
label = float(tokens[1]) # label = int(tokens[1])
|
189 |
+
test_scores.append(score)
|
190 |
+
test_labels.append(label)
|
191 |
+
data.append({'map_score': score, 'label': label})
|
192 |
+
if label == 1:
|
193 |
+
num_real += 1
|
194 |
+
else:
|
195 |
+
num_fake += 1
|
196 |
+
|
197 |
+
# test based on val_threshold
|
198 |
+
type1 = len([s for s in data if s['map_score'] <= val_threshold and s['label'] == 1])
|
199 |
+
print([s for s in data if s['map_score'] <= val_threshold and s['label'] == 1])
|
200 |
+
type2 = len([s for s in data if s['map_score'] > val_threshold and s['label'] == 0])
|
201 |
+
print([s for s in data if s['map_score'] > val_threshold and s['label'] == 0])
|
202 |
+
|
203 |
+
test_ACC = 1 - (type1 + type2) / count
|
204 |
+
test_APCER = type2 / num_fake
|
205 |
+
test_BPCER = type1 / num_real
|
206 |
+
test_ACER = (test_APCER + test_BPCER) / 2.0
|
207 |
+
|
208 |
+
# test based on test_threshold
|
209 |
+
fpr_test, tpr_test, threshold_test = roc_curve(test_labels, test_scores, pos_label=1)
|
210 |
+
err_test, best_test_threshold = get_err_threhold(fpr_test, tpr_test, threshold_test)
|
211 |
+
|
212 |
+
type1 = len([s for s in data if s['map_score'] <= best_test_threshold and s['label'] == 1])
|
213 |
+
type2 = len([s for s in data if s['map_score'] > best_test_threshold and s['label'] == 0])
|
214 |
+
|
215 |
+
test_threshold_ACC = 1 - (type1 + type2) / count
|
216 |
+
test_threshold_APCER = type2 / num_fake
|
217 |
+
test_threshold_BPCER = type1 / num_real
|
218 |
+
test_threshold_ACER = (test_threshold_APCER + test_threshold_BPCER) / 2.0
|
219 |
+
|
220 |
+
return val_threshold, best_test_threshold, val_ACC, val_ACER, test_ACC, test_APCER, test_BPCER, test_ACER, test_threshold_ACER
|
221 |
+
|
222 |
+
|
223 |
+
def performances_SiW_EER(map_score_val_filename):
|
224 |
+
# val
|
225 |
+
with open(map_score_val_filename, 'r') as file:
|
226 |
+
lines = file.readlines()
|
227 |
+
val_scores = []
|
228 |
+
val_labels = []
|
229 |
+
data = []
|
230 |
+
count = 0.0
|
231 |
+
num_real = 0.0
|
232 |
+
num_fake = 0.0
|
233 |
+
for line in lines:
|
234 |
+
count += 1
|
235 |
+
tokens = line.split()
|
236 |
+
score = float(tokens[0])
|
237 |
+
label = int(tokens[1])
|
238 |
+
val_scores.append(score)
|
239 |
+
val_labels.append(label)
|
240 |
+
data.append({'map_score': score, 'label': label})
|
241 |
+
if label == 1:
|
242 |
+
num_real += 1
|
243 |
+
else:
|
244 |
+
num_fake += 1
|
245 |
+
|
246 |
+
fpr, tpr, threshold = roc_curve(val_labels, val_scores, pos_label=1)
|
247 |
+
val_err, val_threshold = get_err_threhold(fpr, tpr, threshold)
|
248 |
+
|
249 |
+
type1 = len([s for s in data if s['map_score'] <= val_threshold and s['label'] == 1])
|
250 |
+
type2 = len([s for s in data if s['map_score'] > val_threshold and s['label'] == 0])
|
251 |
+
|
252 |
+
val_ACC = 1 - (type1 + type2) / count
|
253 |
+
val_APCER = type2 / num_fake
|
254 |
+
val_BPCER = type1 / num_real
|
255 |
+
val_ACER = (val_APCER + val_BPCER) / 2.0
|
256 |
+
|
257 |
+
return val_threshold, val_ACC, val_APCER, val_BPCER, val_ACER
|
258 |
+
|
259 |
+
|
260 |
+
def performances_SiWM_EER(map_score_val_filename):
|
261 |
+
# val
|
262 |
+
with open(map_score_val_filename, 'r') as file:
|
263 |
+
lines = file.readlines()
|
264 |
+
val_scores = []
|
265 |
+
val_labels = []
|
266 |
+
data = []
|
267 |
+
count = 0.0
|
268 |
+
num_real = 0.0
|
269 |
+
num_fake = 0.0
|
270 |
+
for line in lines:
|
271 |
+
count += 1
|
272 |
+
tokens = line.split()
|
273 |
+
score = float(tokens[0])
|
274 |
+
label = int(tokens[1])
|
275 |
+
val_scores.append(score)
|
276 |
+
val_labels.append(label)
|
277 |
+
data.append({'map_score': score, 'label': label})
|
278 |
+
if label == 1:
|
279 |
+
num_real += 1
|
280 |
+
else:
|
281 |
+
num_fake += 1
|
282 |
+
|
283 |
+
fpr, tpr, threshold = roc_curve(val_labels, val_scores, pos_label=1)
|
284 |
+
val_err, val_threshold = get_err_threhold(fpr, tpr, threshold)
|
285 |
+
|
286 |
+
type1 = len([s for s in data if s['map_score'] <= val_threshold and s['label'] == 1])
|
287 |
+
type2 = len([s for s in data if s['map_score'] > val_threshold and s['label'] == 0])
|
288 |
+
|
289 |
+
val_ACC = 1 - (type1 + type2) / count
|
290 |
+
val_APCER = type2 / num_fake
|
291 |
+
val_BPCER = type1 / num_real
|
292 |
+
val_ACER = (val_APCER + val_BPCER) / 2.0
|
293 |
+
|
294 |
+
return val_threshold, val_err, val_ACC, val_APCER, val_BPCER, val_ACER
|
295 |
+
|
296 |
+
|
297 |
+
def get_err_threhold_CASIA_Replay(fpr, tpr, threshold):
|
298 |
+
RightIndex = (tpr + (1 - fpr) - 1)
|
299 |
+
right_index = np.argmax(RightIndex)
|
300 |
+
best_th = threshold[right_index]
|
301 |
+
err = fpr[right_index]
|
302 |
+
|
303 |
+
differ_tpr_fpr_1 = tpr + fpr - 1.0
|
304 |
+
|
305 |
+
right_index = np.argmin(np.abs(differ_tpr_fpr_1))
|
306 |
+
best_th = threshold[right_index]
|
307 |
+
err = fpr[right_index]
|
308 |
+
|
309 |
+
# print(err, best_th)
|
310 |
+
return err, best_th, right_index
|
311 |
+
|
312 |
+
|
313 |
+
def performances_CASIA_Replay(map_score_val_filename):
|
314 |
+
# val
|
315 |
+
with open(map_score_val_filename, 'r') as file:
|
316 |
+
lines = file.readlines()
|
317 |
+
val_scores = []
|
318 |
+
val_labels = []
|
319 |
+
data = []
|
320 |
+
count = 0.0
|
321 |
+
num_real = 0.0
|
322 |
+
num_fake = 0.0
|
323 |
+
for line in lines:
|
324 |
+
count += 1
|
325 |
+
tokens = line.split()
|
326 |
+
score = float(tokens[0])
|
327 |
+
label = float(tokens[1]) # int(tokens[1])
|
328 |
+
val_scores.append(score)
|
329 |
+
val_labels.append(label)
|
330 |
+
data.append({'map_score': score, 'label': label})
|
331 |
+
if label == 1:
|
332 |
+
num_real += 1
|
333 |
+
else:
|
334 |
+
num_fake += 1
|
335 |
+
|
336 |
+
fpr, tpr, threshold = roc_curve(val_labels, val_scores, pos_label=1)
|
337 |
+
val_err, val_threshold, right_index = get_err_threhold_CASIA_Replay(fpr, tpr, threshold)
|
338 |
+
|
339 |
+
type1 = len([s for s in data if s['map_score'] <= val_threshold and s['label'] == 1])
|
340 |
+
print([s for s in data if s['map_score'] <= val_threshold and s['label'] == 1])
|
341 |
+
type2 = len([s for s in data if s['map_score'] > val_threshold and s['label'] == 0])
|
342 |
+
print([s for s in data if s['map_score'] > val_threshold and s['label'] == 0])
|
343 |
+
|
344 |
+
val_ACC = 1 - (type1 + type2) / count
|
345 |
+
|
346 |
+
FRR = 1 - tpr # FRR = 1 - TPR
|
347 |
+
|
348 |
+
HTER = (fpr + FRR) / 2.0 # error recognition rate & reject recognition rate
|
349 |
+
|
350 |
+
return val_ACC, fpr[right_index], FRR[right_index], HTER[right_index], val_threshold
|
351 |
+
|
352 |
+
|
353 |
+
def performances_ZeroShot(map_score_val_filename):
|
354 |
+
# val
|
355 |
+
with open(map_score_val_filename, 'r') as file:
|
356 |
+
lines = file.readlines()
|
357 |
+
val_scores = []
|
358 |
+
val_labels = []
|
359 |
+
data = []
|
360 |
+
count = 0.0
|
361 |
+
num_real = 0.0
|
362 |
+
num_fake = 0.0
|
363 |
+
for line in lines:
|
364 |
+
count += 1
|
365 |
+
tokens = line.split()
|
366 |
+
score = float(tokens[0])
|
367 |
+
label = int(tokens[1])
|
368 |
+
val_scores.append(score)
|
369 |
+
val_labels.append(label)
|
370 |
+
data.append({'map_score': score, 'label': label})
|
371 |
+
if label == 1:
|
372 |
+
num_real += 1
|
373 |
+
else:
|
374 |
+
num_fake += 1
|
375 |
+
|
376 |
+
fpr, tpr, threshold = roc_curve(val_labels, val_scores, pos_label=1)
|
377 |
+
auc_val = metrics.auc(fpr, tpr)
|
378 |
+
|
379 |
+
val_err, val_threshold, right_index = get_err_threhold_CASIA_Replay(fpr, tpr, threshold)
|
380 |
+
|
381 |
+
type1 = len([s for s in data if s['map_score'] <= val_threshold and s['label'] == 1])
|
382 |
+
type2 = len([s for s in data if s['map_score'] > val_threshold and s['label'] == 0])
|
383 |
+
|
384 |
+
val_ACC = 1 - (type1 + type2) / count
|
385 |
+
|
386 |
+
FRR = 1 - tpr # FRR = 1 - TPR
|
387 |
+
|
388 |
+
HTER = (fpr + FRR) / 2.0 # error recognition rate & reject recognition rate
|
389 |
+
|
390 |
+
return val_ACC, auc_val, HTER[right_index]
|
391 |
+
|
392 |
+
|
393 |
+
def count_parameters_in_MB(model):
|
394 |
+
return np.sum(np.prod(v.size()) for name, v in model.named_parameters() if "auxiliary" not in name) / 1e6
|
395 |
+
|
396 |
+
|
397 |
+
def save_checkpoint(state, is_best, save):
|
398 |
+
filename = os.path.join(save, 'checkpoint.pth.tar')
|
399 |
+
torch.save(state, filename)
|
400 |
+
if is_best:
|
401 |
+
best_filename = os.path.join(save, 'model_best.pth.tar')
|
402 |
+
shutil.copyfile(filename, best_filename)
|
403 |
+
|
404 |
+
|
405 |
+
def save(model, model_path):
|
406 |
+
torch.save(model.state_dict(), model_path)
|
407 |
+
|
408 |
+
|
409 |
+
def load(model, model_path):
|
410 |
+
model.load_state_dict(torch.load(model_path))
|
411 |
+
|
412 |
+
|
413 |
+
def drop_path(x, drop_prob):
|
414 |
+
if drop_prob > 0.:
|
415 |
+
keep_prob = 1. - drop_prob
|
416 |
+
mask = Variable(torch.cuda.FloatTensor(x.size(0), 1, 1, 1, 1).bernoulli_(keep_prob))
|
417 |
+
x.div_(keep_prob)
|
418 |
+
x.mul_(mask)
|
419 |
+
return x
|
420 |
+
|
421 |
+
|
422 |
+
def create_exp_dir(path, scripts_to_save=None):
|
423 |
+
if not os.path.exists(path):
|
424 |
+
os.mkdir(path)
|
425 |
+
print('Experiment dir : {}'.format(path))
|
426 |
+
|
427 |
+
if scripts_to_save is not None:
|
428 |
+
os.mkdir(os.path.join(path, 'scripts'))
|
429 |
+
for script in scripts_to_save:
|
430 |
+
dst_file = os.path.join(path, 'scripts', os.path.basename(script))
|
431 |
+
shutil.copyfile(script, dst_file)
|
DSDG/misc/__init__.py
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from .util import *
|
DSDG/misc/util.py
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import time
|
3 |
+
import argparse
|
4 |
+
import numpy as np
|
5 |
+
|
6 |
+
import torch
|
7 |
+
import torch.nn.functional as F
|
8 |
+
|
9 |
+
|
10 |
+
def rgb2gray(img):
|
11 |
+
r, g, b = torch.split(img, 1, dim=1)
|
12 |
+
return torch.mul(r, 0.299) + torch.mul(g, 0.587) + torch.mul(b, 0.114)
|
13 |
+
|
14 |
+
|
15 |
+
def reparameterize(mu, logvar):
|
16 |
+
std = logvar.mul(0.5).exp_()
|
17 |
+
eps = torch.cuda.FloatTensor(std.size()).normal_()
|
18 |
+
return eps.mul(std).add_(mu)
|
19 |
+
|
20 |
+
|
21 |
+
def kl_loss(mu, logvar, prior_mu=0):
|
22 |
+
v_kl = mu.add(-prior_mu).pow(2).add_(logvar.exp()).mul_(-1).add_(1).add_(logvar)
|
23 |
+
v_kl = v_kl.sum(dim=-1).mul_(-0.5) # (batch, 2)
|
24 |
+
return v_kl
|
25 |
+
|
26 |
+
|
27 |
+
def reconstruction_loss(prediction, target, size_average=False):
|
28 |
+
error = (prediction - target).view(prediction.size(0), -1)
|
29 |
+
error = error ** 2
|
30 |
+
error = torch.sum(error, dim=-1)
|
31 |
+
|
32 |
+
if size_average:
|
33 |
+
error = error.mean()
|
34 |
+
else:
|
35 |
+
error = error.sum()
|
36 |
+
return error
|
37 |
+
|
38 |
+
|
39 |
+
def load_model(model, pretrained):
|
40 |
+
weights = torch.load(pretrained)
|
41 |
+
pretrained_dict = weights['model'].state_dict()
|
42 |
+
model_dict = model.state_dict()
|
43 |
+
# 1. filter out unnecessary keys
|
44 |
+
pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
|
45 |
+
# 2. overwrite entries in the existing state dict
|
46 |
+
model_dict.update(pretrained_dict)
|
47 |
+
# 3. load the new state dict
|
48 |
+
model.load_state_dict(model_dict)
|
49 |
+
|
50 |
+
|
51 |
+
def save_checkpoint(model_path, model, epoch, iteration, name):
|
52 |
+
model_out_path = model_path + name + "model_epoch_{}_iter_{}.pth".format(epoch, iteration)
|
53 |
+
state = {"epoch": epoch, "model": model}
|
54 |
+
if not os.path.exists(model_path):
|
55 |
+
os.makedirs(model_path)
|
56 |
+
torch.save(state, model_out_path)
|
57 |
+
print("Checkpoint saved to {}".format(model_out_path))
|
58 |
+
|
59 |
+
|
60 |
+
class AverageMeter(object):
|
61 |
+
"""Computes and stores the average and current value"""
|
62 |
+
|
63 |
+
def __init__(self):
|
64 |
+
self.reset()
|
65 |
+
|
66 |
+
def reset(self):
|
67 |
+
self.val = 0
|
68 |
+
self.avg = 0
|
69 |
+
self.sum = 0
|
70 |
+
self.count = 0
|
71 |
+
|
72 |
+
def update(self, val, n=1):
|
73 |
+
self.val = val
|
74 |
+
self.sum += val * n
|
75 |
+
self.count += n
|
76 |
+
self.avg = self.sum / self.count
|
77 |
+
|
78 |
+
|
79 |
+
def MMD_Loss(fc_nir, fc_vis):
|
80 |
+
mean_fc_nir = torch.mean(fc_nir, 0)
|
81 |
+
mean_fc_vis = torch.mean(fc_vis, 0)
|
82 |
+
loss_mmd = F.mse_loss(mean_fc_nir, mean_fc_vis)
|
83 |
+
return loss_mmd
|
84 |
+
|
85 |
+
|
86 |
+
def adjust_learning_rate(lr, step, optimizer, epoch):
|
87 |
+
scale = 0.457305051927326
|
88 |
+
lr = lr * (scale ** (epoch // step))
|
89 |
+
print('lr: {}'.format(lr))
|
90 |
+
if (epoch != 0) & (epoch % step == 0):
|
91 |
+
print('Change lr')
|
92 |
+
for param_group in optimizer.param_groups:
|
93 |
+
param_group['lr'] = param_group['lr'] * scale
|
94 |
+
|
95 |
+
|
96 |
+
def accuracy(output, target, topk=(1,)):
|
97 |
+
"""Computes the precision@k for the specified values of k"""
|
98 |
+
maxk = max(topk)
|
99 |
+
batch_size = target.size(0)
|
100 |
+
|
101 |
+
_, pred = output.topk(maxk, 1, True, True)
|
102 |
+
pred = pred.t()
|
103 |
+
correct = pred.eq(target.view(1, -1).expand_as(pred))
|
104 |
+
|
105 |
+
res = []
|
106 |
+
for k in topk:
|
107 |
+
correct_k = correct[:k].view(-1).float().sum(0)
|
108 |
+
res.append(correct_k.mul_(100.0 / batch_size))
|
109 |
+
return res
|
DSDG/networks/__init__.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from .generator import Encoder, Decoder, Encoder_s, Decoder_s, Cls
|
3 |
+
from .light_cnn import network_29layers_v2, resblock
|
4 |
+
|
5 |
+
|
6 |
+
# define generator
|
7 |
+
def define_G(hdim=256, attack_type=4):
|
8 |
+
netE_nir = Encoder_s(hdim=hdim)
|
9 |
+
netCls = Cls(hdim=hdim, attack_type=attack_type)
|
10 |
+
netE_vis = Encoder(hdim=hdim)
|
11 |
+
netG = Decoder_s(hdim=hdim)
|
12 |
+
|
13 |
+
netE_nir = torch.nn.DataParallel(netE_nir).cuda()
|
14 |
+
netE_vis = torch.nn.DataParallel(netE_vis).cuda()
|
15 |
+
netG = torch.nn.DataParallel(netG).cuda()
|
16 |
+
netCls = torch.nn.DataParallel(netCls).cuda()
|
17 |
+
|
18 |
+
return netE_nir, netE_vis, netG, netCls
|
19 |
+
|
20 |
+
|
21 |
+
# define identity preserving && feature extraction net
|
22 |
+
def define_IP(is_train=False):
|
23 |
+
netIP = network_29layers_v2(resblock, [1, 2, 3, 4], is_train)
|
24 |
+
netIP = torch.nn.DataParallel(netIP).cuda()
|
25 |
+
return netIP
|
26 |
+
|
27 |
+
|
28 |
+
# define recognition network
|
29 |
+
def LightCNN_29v2(num_classes=10000, is_train=True):
|
30 |
+
net = network_29layers_v2(resblock, [1, 2, 3, 4], is_train, num_classes=num_classes)
|
31 |
+
net = torch.nn.DataParallel(net).cuda()
|
32 |
+
return net
|
DSDG/networks/generator.py
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
|
3 |
+
import torch
|
4 |
+
import torch.nn as nn
|
5 |
+
import torch.nn.functional as F
|
6 |
+
from torch.autograd import Variable
|
7 |
+
|
8 |
+
|
9 |
+
class Encoder(nn.Module):
|
10 |
+
def __init__(self, hdim=256):
|
11 |
+
super(Encoder, self).__init__()
|
12 |
+
|
13 |
+
self.hdim = hdim
|
14 |
+
|
15 |
+
self.main = nn.Sequential(
|
16 |
+
nn.Conv2d(3, 32, 5, 2, 2, bias=False),
|
17 |
+
nn.InstanceNorm2d(32, eps=0.001),
|
18 |
+
nn.LeakyReLU(0.2),
|
19 |
+
nn.AvgPool2d(2),
|
20 |
+
make_layer(_Residual_Block, 1, 32, 64),
|
21 |
+
nn.AvgPool2d(2),
|
22 |
+
make_layer(_Residual_Block, 1, 64, 128),
|
23 |
+
nn.AvgPool2d(2),
|
24 |
+
make_layer(_Residual_Block, 1, 128, 256),
|
25 |
+
nn.AvgPool2d(2),
|
26 |
+
make_layer(_Residual_Block, 1, 256, 512),
|
27 |
+
nn.AvgPool2d(2),
|
28 |
+
make_layer(_Residual_Block, 1, 512, 512)
|
29 |
+
)
|
30 |
+
|
31 |
+
# mu and logvar
|
32 |
+
self.fc = nn.Linear(512 * 4 * 4, 2 * hdim)
|
33 |
+
|
34 |
+
def forward(self, x):
|
35 |
+
z = self.main(x).view(x.size(0), -1)
|
36 |
+
z = self.fc(z)
|
37 |
+
mu, logvar = torch.split(z, split_size_or_sections=self.hdim, dim=-1)
|
38 |
+
|
39 |
+
return mu, logvar
|
40 |
+
|
41 |
+
|
42 |
+
class Encoder_s(nn.Module):
|
43 |
+
def __init__(self, hdim=256):
|
44 |
+
super(Encoder_s, self).__init__()
|
45 |
+
|
46 |
+
self.hdim = hdim
|
47 |
+
|
48 |
+
self.main = nn.Sequential(
|
49 |
+
nn.Conv2d(3, 32, 5, 2, 2, bias=False),
|
50 |
+
nn.InstanceNorm2d(32, eps=0.001),
|
51 |
+
nn.LeakyReLU(0.2),
|
52 |
+
nn.AvgPool2d(2),
|
53 |
+
make_layer(_Residual_Block, 1, 32, 64),
|
54 |
+
nn.AvgPool2d(2),
|
55 |
+
make_layer(_Residual_Block, 1, 64, 128),
|
56 |
+
nn.AvgPool2d(2),
|
57 |
+
make_layer(_Residual_Block, 1, 128, 256),
|
58 |
+
nn.AvgPool2d(2),
|
59 |
+
make_layer(_Residual_Block, 1, 256, 512),
|
60 |
+
nn.AvgPool2d(2),
|
61 |
+
make_layer(_Residual_Block, 1, 512, 512)
|
62 |
+
)
|
63 |
+
|
64 |
+
# mu and logvar
|
65 |
+
self.fc = nn.Linear(512 * 4 * 4, 4 * hdim)
|
66 |
+
# self.fc_at = nn.Linear(hdim, attack_type)
|
67 |
+
|
68 |
+
def forward(self, x):
|
69 |
+
z = self.main(x).view(x.size(0), -1)
|
70 |
+
z = self.fc(z)
|
71 |
+
mu, logvar, mu_a, logvar_a = torch.split(z, split_size_or_sections=self.hdim, dim=-1)
|
72 |
+
# a_type = self.fc_at(a_t)
|
73 |
+
|
74 |
+
return mu, logvar, mu_a, logvar_a
|
75 |
+
|
76 |
+
|
77 |
+
class Cls(nn.Module):
|
78 |
+
def __init__(self, hdim=256, attack_type=4):
|
79 |
+
super(Cls, self).__init__()
|
80 |
+
|
81 |
+
self.fc = nn.Linear(hdim, attack_type)
|
82 |
+
|
83 |
+
def forward(self, x):
|
84 |
+
a_cls = self.fc(x)
|
85 |
+
|
86 |
+
return a_cls
|
87 |
+
|
88 |
+
class Decoder(nn.Module):
|
89 |
+
def __init__(self, hdim=256):
|
90 |
+
super(Decoder, self).__init__()
|
91 |
+
|
92 |
+
self.fc = nn.Sequential(
|
93 |
+
nn.Linear(hdim, 512 * 4 * 4),
|
94 |
+
nn.ReLU(True)
|
95 |
+
)
|
96 |
+
|
97 |
+
self.main = nn.Sequential(
|
98 |
+
make_layer(_Residual_Block, 1, 512, 512),
|
99 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
100 |
+
make_layer(_Residual_Block, 1, 512, 512),
|
101 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
102 |
+
make_layer(_Residual_Block, 1, 512, 512),
|
103 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
104 |
+
make_layer(_Residual_Block, 1, 512, 256),
|
105 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
106 |
+
make_layer(_Residual_Block, 1, 256, 128),
|
107 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
108 |
+
make_layer(_Residual_Block, 2, 128, 64),
|
109 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
110 |
+
nn.Conv2d(64, 3 + 3, 5, 1, 2)
|
111 |
+
)
|
112 |
+
|
113 |
+
def forward(self, z):
|
114 |
+
z = z.view(z.size(0), -1)
|
115 |
+
y = self.fc(z)
|
116 |
+
x = y.view(z.size(0), -1, 4, 4)
|
117 |
+
img = torch.sigmoid(self.main(x))
|
118 |
+
return img
|
119 |
+
|
120 |
+
|
121 |
+
class Decoder_s(nn.Module):
|
122 |
+
def __init__(self, hdim=256):
|
123 |
+
super(Decoder_s, self).__init__()
|
124 |
+
|
125 |
+
self.fc = nn.Sequential(
|
126 |
+
nn.Linear(3 * hdim, 512 * 4 * 4),
|
127 |
+
nn.ReLU(True)
|
128 |
+
)
|
129 |
+
|
130 |
+
self.main = nn.Sequential(
|
131 |
+
make_layer(_Residual_Block, 1, 512, 512),
|
132 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
133 |
+
make_layer(_Residual_Block, 1, 512, 512),
|
134 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
135 |
+
make_layer(_Residual_Block, 1, 512, 512),
|
136 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
137 |
+
make_layer(_Residual_Block, 1, 512, 256),
|
138 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
139 |
+
make_layer(_Residual_Block, 1, 256, 128),
|
140 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
141 |
+
make_layer(_Residual_Block, 2, 128, 64),
|
142 |
+
nn.Upsample(scale_factor=2, mode='nearest'),
|
143 |
+
nn.Conv2d(64, 3 + 3, 5, 1, 2)
|
144 |
+
)
|
145 |
+
|
146 |
+
def forward(self, z):
|
147 |
+
z = z.view(z.size(0), -1)
|
148 |
+
y = self.fc(z)
|
149 |
+
x = y.view(z.size(0), -1, 4, 4)
|
150 |
+
img = torch.sigmoid(self.main(x))
|
151 |
+
return img
|
152 |
+
|
153 |
+
|
154 |
+
class _Residual_Block(nn.Module):
|
155 |
+
def __init__(self, inc=64, outc=64, groups=1):
|
156 |
+
super(_Residual_Block, self).__init__()
|
157 |
+
|
158 |
+
if inc is not outc:
|
159 |
+
self.conv_expand = nn.Conv2d(in_channels=inc, out_channels=outc, kernel_size=1, stride=1, padding=0,
|
160 |
+
groups=1, bias=False)
|
161 |
+
else:
|
162 |
+
self.conv_expand = None
|
163 |
+
|
164 |
+
self.conv1 = nn.Conv2d(in_channels=inc, out_channels=outc, kernel_size=3, stride=1, padding=1, groups=groups,
|
165 |
+
bias=False)
|
166 |
+
self.bn1 = nn.InstanceNorm2d(outc, eps=0.001)
|
167 |
+
self.relu1 = nn.LeakyReLU(0.2, inplace=True)
|
168 |
+
self.conv2 = nn.Conv2d(in_channels=outc, out_channels=outc, kernel_size=3, stride=1, padding=1, groups=groups,
|
169 |
+
bias=False)
|
170 |
+
self.bn2 = nn.InstanceNorm2d(outc, eps=0.001)
|
171 |
+
self.relu2 = nn.LeakyReLU(0.2, inplace=True)
|
172 |
+
|
173 |
+
def forward(self, x):
|
174 |
+
if self.conv_expand is not None:
|
175 |
+
identity_data = self.conv_expand(x)
|
176 |
+
else:
|
177 |
+
identity_data = x
|
178 |
+
|
179 |
+
output = self.relu1(self.bn1(self.conv1(x)))
|
180 |
+
output = self.conv2(output)
|
181 |
+
output = self.relu2(self.bn2(torch.add(output, identity_data)))
|
182 |
+
return output
|
183 |
+
|
184 |
+
|
185 |
+
def make_layer(block, num_of_layer, inc=64, outc=64, groups=1):
|
186 |
+
if num_of_layer < 1:
|
187 |
+
num_of_layer = 1
|
188 |
+
layers = []
|
189 |
+
layers.append(block(inc=inc, outc=outc, groups=groups))
|
190 |
+
for _ in range(1, num_of_layer):
|
191 |
+
layers.append(block(inc=outc, outc=outc, groups=groups))
|
192 |
+
return nn.Sequential(*layers)
|
DSDG/networks/light_cnn.py
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import torch.nn as nn
|
3 |
+
import torch.nn.functional as F
|
4 |
+
|
5 |
+
|
6 |
+
class mfm(nn.Module):
|
7 |
+
def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1, type=1):
|
8 |
+
super(mfm, self).__init__()
|
9 |
+
self.out_channels = out_channels
|
10 |
+
if type == 1:
|
11 |
+
self.filter = nn.Conv2d(in_channels, 2 * out_channels, kernel_size=kernel_size, stride=stride,
|
12 |
+
padding=padding)
|
13 |
+
else:
|
14 |
+
self.filter = nn.Linear(in_channels, 2 * out_channels)
|
15 |
+
|
16 |
+
def forward(self, x):
|
17 |
+
x = self.filter(x)
|
18 |
+
out = torch.split(x, self.out_channels, 1)
|
19 |
+
return torch.max(out[0], out[1])
|
20 |
+
|
21 |
+
|
22 |
+
class group(nn.Module):
|
23 |
+
def __init__(self, in_channels, out_channels, kernel_size, stride, padding):
|
24 |
+
super(group, self).__init__()
|
25 |
+
self.conv_a = mfm(in_channels, in_channels, 1, 1, 0)
|
26 |
+
self.conv = mfm(in_channels, out_channels, kernel_size, stride, padding)
|
27 |
+
|
28 |
+
def forward(self, x):
|
29 |
+
x = self.conv_a(x)
|
30 |
+
x = self.conv(x)
|
31 |
+
return x
|
32 |
+
|
33 |
+
|
34 |
+
class resblock(nn.Module):
|
35 |
+
def __init__(self, in_channels, out_channels):
|
36 |
+
super(resblock, self).__init__()
|
37 |
+
self.conv1 = mfm(in_channels, out_channels, kernel_size=3, stride=1, padding=1)
|
38 |
+
self.conv2 = mfm(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
|
39 |
+
|
40 |
+
def forward(self, x):
|
41 |
+
res = x
|
42 |
+
out = self.conv1(x)
|
43 |
+
out = self.conv2(out)
|
44 |
+
out = out + res
|
45 |
+
return out
|
46 |
+
|
47 |
+
|
48 |
+
class network_29layers_v2(nn.Module):
|
49 |
+
def __init__(self, block, layers, is_train=False, num_classes=80013):
|
50 |
+
super(network_29layers_v2, self).__init__()
|
51 |
+
self.is_train = is_train
|
52 |
+
self.conv1 = mfm(1, 48, 5, 1, 2)
|
53 |
+
self.block1 = self._make_layer(block, layers[0], 48, 48)
|
54 |
+
self.group1 = group(48, 96, 3, 1, 1)
|
55 |
+
self.block2 = self._make_layer(block, layers[1], 96, 96)
|
56 |
+
self.group2 = group(96, 192, 3, 1, 1)
|
57 |
+
self.block3 = self._make_layer(block, layers[2], 192, 192)
|
58 |
+
self.group3 = group(192, 128, 3, 1, 1)
|
59 |
+
self.block4 = self._make_layer(block, layers[3], 128, 128)
|
60 |
+
self.group4 = group(128, 128, 3, 1, 1)
|
61 |
+
self.fc = nn.Linear(8 * 8 * 128, 256)
|
62 |
+
|
63 |
+
if self.is_train:
|
64 |
+
self.fc2_ = nn.Linear(256, num_classes, bias=False)
|
65 |
+
|
66 |
+
def _make_layer(self, block, num_blocks, in_channels, out_channels):
|
67 |
+
layers = []
|
68 |
+
for i in range(0, num_blocks):
|
69 |
+
layers.append(block(in_channels, out_channels))
|
70 |
+
return nn.Sequential(*layers)
|
71 |
+
|
72 |
+
def forward(self, x):
|
73 |
+
x = self.conv1(x)
|
74 |
+
x = F.max_pool2d(x, 2) + F.avg_pool2d(x, 2)
|
75 |
+
|
76 |
+
x = self.block1(x)
|
77 |
+
x = self.group1(x)
|
78 |
+
x = F.max_pool2d(x, 2) + F.avg_pool2d(x, 2)
|
79 |
+
|
80 |
+
x = self.block2(x)
|
81 |
+
x = self.group2(x)
|
82 |
+
x = F.max_pool2d(x, 2) + F.avg_pool2d(x, 2)
|
83 |
+
|
84 |
+
x = self.block3(x)
|
85 |
+
x = self.group3(x)
|
86 |
+
x = self.block4(x)
|
87 |
+
x = self.group4(x)
|
88 |
+
x = F.max_pool2d(x, 2) + F.avg_pool2d(x, 2)
|
89 |
+
|
90 |
+
x = x.view(x.size(0), -1)
|
91 |
+
fc = self.fc(x)
|
92 |
+
|
93 |
+
if self.is_train:
|
94 |
+
x = F.dropout(fc, training=self.training)
|
95 |
+
out = self.fc2_(x)
|
96 |
+
return out, fc
|
97 |
+
else:
|
98 |
+
return fc
|
app.py
CHANGED
@@ -1,3 +1,6 @@
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
from gradio.components import Dropdown
|
3 |
|
@@ -12,20 +15,25 @@ import pandas as pd
|
|
12 |
from skimage.io import imread, imsave
|
13 |
# from tddfa.TDDFA import TDDFA
|
14 |
from tddfa.utils.depth import depth
|
15 |
-
from tddfa.
|
|
|
|
|
|
|
16 |
|
17 |
import os
|
18 |
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
|
19 |
os.environ['OMP_NUM_THREADS'] = '4'
|
20 |
|
|
|
|
|
21 |
labels = ['Live', 'Spoof']
|
22 |
-
|
|
|
23 |
examples = [
|
24 |
['examples/1_1_21_2_33_scene_fake.jpg', "DeePixBiS"],
|
25 |
['examples/frame150_real.jpg', "DeePixBiS"],
|
26 |
['examples/1_2.avi_125_real.jpg', "DeePixBiS"],
|
27 |
['examples/1_3.avi_25_fake.jpg', "DeePixBiS"]]
|
28 |
-
device = torch.device("cpu")
|
29 |
faceClassifier = cv.CascadeClassifier('./DeePixBiS/Classifiers/haarface.xml')
|
30 |
tfms = transforms.Compose([
|
31 |
transforms.ToPILImage(),
|
@@ -37,8 +45,52 @@ model = DeePixBiS(pretrained=False)
|
|
37 |
model.load_state_dict(torch.load('./DeePixBiS/DeePixBiS.pth'))
|
38 |
model.eval()
|
39 |
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
def find_largest_face(faces):
|
44 |
largest_face = None
|
@@ -51,6 +103,7 @@ def find_largest_face(faces):
|
|
51 |
largest_face = (x, y, w, h)
|
52 |
return largest_face
|
53 |
|
|
|
54 |
def inference(img, model_name):
|
55 |
confidences = {}
|
56 |
grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
@@ -68,14 +121,9 @@ def inference(img, model_name):
|
|
68 |
if model_name == 'DeePixBiS':
|
69 |
mask, binary = model.forward(faceRegion)
|
70 |
res = torch.mean(mask).item()
|
71 |
-
if res
|
72 |
-
|
73 |
-
|
74 |
-
res = 1 - res
|
75 |
-
else:
|
76 |
-
cls = 'Real'
|
77 |
-
color = (0, 255, 0)
|
78 |
-
|
79 |
else:
|
80 |
dense_flag = True
|
81 |
boxes = list(face)
|
@@ -83,13 +131,35 @@ def inference(img, model_name):
|
|
83 |
param_lst, roi_box_lst = tddfa(img, [boxes])
|
84 |
|
85 |
ver_lst = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
label = f'{cls} {res:.2f}'
|
92 |
confidences = {label: res}
|
|
|
93 |
cv.rectangle(img, (x, y), (x + w, y + h), color, 2)
|
94 |
cv.putText(img, label, (x, y + h + 30),
|
95 |
cv.FONT_HERSHEY_COMPLEX, 1, color)
|
|
|
1 |
+
import subprocess
|
2 |
+
subprocess.run(["sh", "tddfa/build.sh"])
|
3 |
+
|
4 |
import gradio as gr
|
5 |
from gradio.components import Dropdown
|
6 |
|
|
|
15 |
from skimage.io import imread, imsave
|
16 |
# from tddfa.TDDFA import TDDFA
|
17 |
from tddfa.utils.depth import depth
|
18 |
+
from tddfa.TDDFA import TDDFA
|
19 |
+
|
20 |
+
import torch.optim as optim
|
21 |
+
from DSDG.DUM.models.CDCNs_u import Conv2d_cd, CDCN_u
|
22 |
|
23 |
import os
|
24 |
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
|
25 |
os.environ['OMP_NUM_THREADS'] = '4'
|
26 |
|
27 |
+
|
28 |
+
device = torch.device("cpu")
|
29 |
labels = ['Live', 'Spoof']
|
30 |
+
pix_threshhold = 0.45
|
31 |
+
dsdg_threshold = 0.003
|
32 |
examples = [
|
33 |
['examples/1_1_21_2_33_scene_fake.jpg', "DeePixBiS"],
|
34 |
['examples/frame150_real.jpg', "DeePixBiS"],
|
35 |
['examples/1_2.avi_125_real.jpg', "DeePixBiS"],
|
36 |
['examples/1_3.avi_25_fake.jpg', "DeePixBiS"]]
|
|
|
37 |
faceClassifier = cv.CascadeClassifier('./DeePixBiS/Classifiers/haarface.xml')
|
38 |
tfms = transforms.Compose([
|
39 |
transforms.ToPILImage(),
|
|
|
45 |
model.load_state_dict(torch.load('./DeePixBiS/DeePixBiS.pth'))
|
46 |
model.eval()
|
47 |
|
48 |
+
|
49 |
+
depth_config_path = 'tddfa/configs/mb05_120x120.yml' # 'tddfa/configs/mb1_120x120.yml
|
50 |
+
cfg = yaml.load(open(depth_config_path), Loader=yaml.SafeLoader)
|
51 |
+
tddfa = TDDFA(gpu_mode=False, **cfg)
|
52 |
+
|
53 |
+
|
54 |
+
model = CDCN_u(basic_conv=Conv2d_cd, theta=0.7)
|
55 |
+
model = model.to(device)
|
56 |
+
weights = torch.load('./DSDG/DUM/checkpoint/CDCN_U_P1_updated.pkl', map_location=device)
|
57 |
+
model.load_state_dict(weights)
|
58 |
+
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=0.00005)
|
59 |
+
model.eval()
|
60 |
+
|
61 |
+
|
62 |
+
class Normaliztion_valtest(object):
|
63 |
+
"""
|
64 |
+
same as mxnet, normalize into [-1, 1]
|
65 |
+
image = (image - 127.5)/128
|
66 |
+
"""
|
67 |
+
def __call__(self, image_x):
|
68 |
+
image_x = (image_x - 127.5) / 128 # [-1,1]
|
69 |
+
return image_x
|
70 |
+
|
71 |
+
|
72 |
+
def prepare_data(images, boxes, depths):
|
73 |
+
transform = transforms.Compose([Normaliztion_valtest()])
|
74 |
+
files_total = 1
|
75 |
+
image_x = np.zeros((files_total, 256, 256, 3))
|
76 |
+
depth_x = np.ones((files_total, 32, 32))
|
77 |
+
|
78 |
+
for i, (image, bbox, depth_img) in enumerate(
|
79 |
+
zip(images, boxes, depths)):
|
80 |
+
x, y, w, h = bbox
|
81 |
+
depth_img = cv.cvtColor(depth_img, cv.COLOR_RGB2GRAY)
|
82 |
+
image = image[y:y + h, x:x + w]
|
83 |
+
depth_img = depth_img[y:y + h, x:x + w]
|
84 |
+
|
85 |
+
image_x[i, :, :, :] = cv.resize(image, (256, 256))
|
86 |
+
# transform to binary mask --> threshold = 0
|
87 |
+
depth_x[i, :, :] = cv.resize(depth_img, (32, 32))
|
88 |
+
image_x = image_x.transpose((0, 3, 1, 2))
|
89 |
+
image_x = transform(image_x)
|
90 |
+
image_x = torch.from_numpy(image_x.astype(float)).float()
|
91 |
+
depth_x = torch.from_numpy(depth_x.astype(float)).float()
|
92 |
+
return image_x, depth_x
|
93 |
+
|
94 |
|
95 |
def find_largest_face(faces):
|
96 |
largest_face = None
|
|
|
103 |
largest_face = (x, y, w, h)
|
104 |
return largest_face
|
105 |
|
106 |
+
|
107 |
def inference(img, model_name):
|
108 |
confidences = {}
|
109 |
grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
|
|
121 |
if model_name == 'DeePixBiS':
|
122 |
mask, binary = model.forward(faceRegion)
|
123 |
res = torch.mean(mask).item()
|
124 |
+
cls = 'Real' if res >= pix_threshhold else 'Spoof'
|
125 |
+
res = 1 - res
|
126 |
+
|
|
|
|
|
|
|
|
|
|
|
127 |
else:
|
128 |
dense_flag = True
|
129 |
boxes = list(face)
|
|
|
131 |
param_lst, roi_box_lst = tddfa(img, [boxes])
|
132 |
|
133 |
ver_lst = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)
|
134 |
+
depth_img = depth(img, ver_lst, tddfa.tri, with_bg_flag=False)
|
135 |
+
with torch.no_grad():
|
136 |
+
map_score_list = []
|
137 |
+
image_x, map_x = prepare_data([img], [list(face)], [depth_img])
|
138 |
+
# get the inputs
|
139 |
+
image_x = image_x.unsqueeze(0)
|
140 |
+
map_x = map_x.unsqueeze(0)
|
141 |
+
inputs = image_x.to(device)
|
142 |
+
test_maps = map_x.to(device)
|
143 |
+
optimizer.zero_grad()
|
144 |
+
|
145 |
+
map_score = 0.0
|
146 |
+
for frame_t in range(inputs.shape[1]):
|
147 |
+
mu, logvar, map_x, x_concat, x_Block1, x_Block2, x_Block3, x_input = model(inputs[:, frame_t, :, :, :])
|
148 |
+
|
149 |
+
score_norm = torch.sum(mu) / torch.sum(test_maps[:, frame_t, :, :])
|
150 |
+
map_score += score_norm
|
151 |
+
map_score = map_score / inputs.shape[1]
|
152 |
+
map_score_list.append(map_score)
|
153 |
+
|
154 |
+
res = map_score_list[0].item()
|
155 |
+
if res > 10:
|
156 |
+
res = 0.0
|
157 |
+
cls = 'Real' if res >= dsdg_threshold else 'Spoof'
|
158 |
+
res = res * 100
|
159 |
|
160 |
label = f'{cls} {res:.2f}'
|
161 |
confidences = {label: res}
|
162 |
+
color = color = (0, 255, 0) if cls == 'Real' else (255, 0, 0)
|
163 |
cv.rectangle(img, (x, y), (x + w, y + h), color, 2)
|
164 |
cv.putText(img, label, (x, y + h + 30),
|
165 |
cv.FONT_HERSHEY_COMPLEX, 1, color)
|
tddfa/TDDFA.py
CHANGED
@@ -10,13 +10,13 @@ import torch
|
|
10 |
from torchvision.transforms import Compose
|
11 |
import torch.backends.cudnn as cudnn
|
12 |
|
13 |
-
import models
|
14 |
-
from bfm import BFMModel
|
15 |
-
from utils.io import _load
|
16 |
-
from utils.functions import (
|
17 |
crop_img, parse_roi_box_from_bbox, parse_roi_box_from_landmark,
|
18 |
)
|
19 |
-
from utils.tddfa_util import (
|
20 |
load_model, _parse_param, similar_transform,
|
21 |
ToTensorGjz, NormalizeGjz
|
22 |
)
|
@@ -114,7 +114,7 @@ class TDDFA(object):
|
|
114 |
else:
|
115 |
param = self.model(inp)
|
116 |
|
117 |
-
param = param.squeeze().cpu().numpy().flatten().astype(np.float32)
|
118 |
param = param * self.param_std + self.param_mean # re-scale
|
119 |
# print('output', param)
|
120 |
param_lst.append(param)
|
|
|
10 |
from torchvision.transforms import Compose
|
11 |
import torch.backends.cudnn as cudnn
|
12 |
|
13 |
+
import tddfa.models as models
|
14 |
+
from tddfa.bfm import BFMModel
|
15 |
+
from tddfa.utils.io import _load
|
16 |
+
from tddfa.utils.functions import (
|
17 |
crop_img, parse_roi_box_from_bbox, parse_roi_box_from_landmark,
|
18 |
)
|
19 |
+
from tddfa.utils.tddfa_util import (
|
20 |
load_model, _parse_param, similar_transform,
|
21 |
ToTensorGjz, NormalizeGjz
|
22 |
)
|
|
|
114 |
else:
|
115 |
param = self.model(inp)
|
116 |
|
117 |
+
param = param.squeeze().cpu().detach().numpy().flatten().astype(np.float32)
|
118 |
param = param * self.param_std + self.param_mean # re-scale
|
119 |
# print('output', param)
|
120 |
param_lst.append(param)
|
tddfa/weights/mb1_120x120.onnx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:91aba763fd0a5d9ed78d11ff728be54b83e24ab2f2b3389f204be95b482b23d2
|
3 |
+
size 13048589
|