ozyman commited on
Commit
e437acb
1 Parent(s): 332db8e

added dsdg without model file

Browse files
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.TDDFA_ONNX import TDDFA_ONNX
 
 
 
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
- thresh = 0.45
 
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
- cfg = yaml.load(open('tddfa/configs/mb1_120x120.yml'), Loader=yaml.SafeLoader)
41
- tddfa = TDDFA_ONNX(gpu_mode=False, **cfg)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 < thresh:
72
- cls = 'Spoof'
73
- color = (0, 0, 255)
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
- img = depth(img, ver_lst, tddfa.tri, with_bg_flag=False)
87
- cls = 'Other'
88
- res = 0.5
89
- color = (0, 0, 255)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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