Spaces:
Running
Running
AK391
commited on
Commit
•
2782137
1
Parent(s):
a3a294d
files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- __init_paths.py +30 -0
- align_faces.py +266 -0
- data_loader/dataset_face.py +103 -0
- data_loader/degradations.py +765 -0
- distributed.py +126 -0
- face_colorization.py +48 -0
- face_detect/data/FDDB/img_list.txt +2845 -0
- face_detect/data/__init__.py +3 -0
- face_detect/data/config.py +42 -0
- face_detect/data/data_augment.py +237 -0
- face_detect/data/wider_face.py +101 -0
- face_detect/facemodels/__init__.py +0 -0
- face_detect/facemodels/net.py +137 -0
- face_detect/facemodels/retinaface.py +127 -0
- face_detect/layers/__init__.py +2 -0
- face_detect/layers/functions/prior_box.py +34 -0
- face_detect/layers/modules/__init__.py +3 -0
- face_detect/layers/modules/multibox_loss.py +125 -0
- face_detect/retinaface_detection.py +192 -0
- face_detect/utils/__init__.py +0 -0
- face_detect/utils/box_utils.py +330 -0
- face_detect/utils/nms/__init__.py +0 -0
- face_detect/utils/nms/py_cpu_nms.py +38 -0
- face_detect/utils/timer.py +40 -0
- face_enhancement.py +145 -0
- face_inpainting.py +101 -0
- face_model/face_gan.py +57 -0
- face_model/gpen_model.py +747 -0
- face_model/op/__init__.py +2 -0
- face_model/op/fused_act.py +96 -0
- face_model/op/fused_bias_act.cpp +21 -0
- face_model/op/fused_bias_act_kernel.cu +99 -0
- face_model/op/upfirdn2d.cpp +23 -0
- face_model/op/upfirdn2d.py +194 -0
- face_model/op/upfirdn2d_kernel.cu +272 -0
- face_parse/blocks.py +127 -0
- face_parse/face_parsing.py +78 -0
- face_parse/mask.png +0 -0
- face_parse/parse_model.py +77 -0
- face_parse/test.png +0 -0
- loss/helpers.py +119 -0
- loss/id_loss.py +50 -0
- loss/model_irse.py +85 -0
- lpips/__init__.py +178 -0
- lpips/lpips.py +219 -0
- lpips/pretrained_networks.py +180 -0
- lpips/trainer.py +280 -0
- lpips/weights/v0.0/alex.pth +3 -0
- lpips/weights/v0.0/squeeze.pth +3 -0
- lpips/weights/v0.0/vgg.pth +3 -0
__init_paths.py
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@paper: GAN Prior Embedded Network for Blind Face Restoration in the Wild (CVPR2021)
|
3 |
+
@author: yangxy (yangtao9009@gmail.com)
|
4 |
+
'''
|
5 |
+
import os.path as osp
|
6 |
+
import sys
|
7 |
+
|
8 |
+
def add_path(path):
|
9 |
+
if path not in sys.path:
|
10 |
+
sys.path.insert(0, path)
|
11 |
+
|
12 |
+
this_dir = osp.dirname(__file__)
|
13 |
+
|
14 |
+
path = osp.join(this_dir, 'face_detect')
|
15 |
+
add_path(path)
|
16 |
+
|
17 |
+
path = osp.join(this_dir, 'face_parse')
|
18 |
+
add_path(path)
|
19 |
+
|
20 |
+
path = osp.join(this_dir, 'face_model')
|
21 |
+
add_path(path)
|
22 |
+
|
23 |
+
path = osp.join(this_dir, 'sr_model')
|
24 |
+
add_path(path)
|
25 |
+
|
26 |
+
path = osp.join(this_dir, 'loss')
|
27 |
+
add_path(path)
|
28 |
+
|
29 |
+
path = osp.join(this_dir, 'data_loader')
|
30 |
+
add_path(path)
|
align_faces.py
ADDED
@@ -0,0 +1,266 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
"""
|
3 |
+
Created on Mon Apr 24 15:43:29 2017
|
4 |
+
@author: zhaoy
|
5 |
+
"""
|
6 |
+
"""
|
7 |
+
@Modified by yangxy (yangtao9009@gmail.com)
|
8 |
+
"""
|
9 |
+
import cv2
|
10 |
+
import numpy as np
|
11 |
+
from skimage import transform as trans
|
12 |
+
|
13 |
+
# reference facial points, a list of coordinates (x,y)
|
14 |
+
REFERENCE_FACIAL_POINTS = [
|
15 |
+
[30.29459953, 51.69630051],
|
16 |
+
[65.53179932, 51.50139999],
|
17 |
+
[48.02519989, 71.73660278],
|
18 |
+
[33.54930115, 92.3655014],
|
19 |
+
[62.72990036, 92.20410156]
|
20 |
+
]
|
21 |
+
|
22 |
+
DEFAULT_CROP_SIZE = (96, 112)
|
23 |
+
|
24 |
+
|
25 |
+
def _umeyama(src, dst, estimate_scale=True, scale=1.0):
|
26 |
+
"""Estimate N-D similarity transformation with or without scaling.
|
27 |
+
Parameters
|
28 |
+
----------
|
29 |
+
src : (M, N) array
|
30 |
+
Source coordinates.
|
31 |
+
dst : (M, N) array
|
32 |
+
Destination coordinates.
|
33 |
+
estimate_scale : bool
|
34 |
+
Whether to estimate scaling factor.
|
35 |
+
Returns
|
36 |
+
-------
|
37 |
+
T : (N + 1, N + 1)
|
38 |
+
The homogeneous similarity transformation matrix. The matrix contains
|
39 |
+
NaN values only if the problem is not well-conditioned.
|
40 |
+
References
|
41 |
+
----------
|
42 |
+
.. [1] "Least-squares estimation of transformation parameters between two
|
43 |
+
point patterns", Shinji Umeyama, PAMI 1991, :DOI:`10.1109/34.88573`
|
44 |
+
"""
|
45 |
+
|
46 |
+
num = src.shape[0]
|
47 |
+
dim = src.shape[1]
|
48 |
+
|
49 |
+
# Compute mean of src and dst.
|
50 |
+
src_mean = src.mean(axis=0)
|
51 |
+
dst_mean = dst.mean(axis=0)
|
52 |
+
|
53 |
+
# Subtract mean from src and dst.
|
54 |
+
src_demean = src - src_mean
|
55 |
+
dst_demean = dst - dst_mean
|
56 |
+
|
57 |
+
# Eq. (38).
|
58 |
+
A = dst_demean.T @ src_demean / num
|
59 |
+
|
60 |
+
# Eq. (39).
|
61 |
+
d = np.ones((dim,), dtype=np.double)
|
62 |
+
if np.linalg.det(A) < 0:
|
63 |
+
d[dim - 1] = -1
|
64 |
+
|
65 |
+
T = np.eye(dim + 1, dtype=np.double)
|
66 |
+
|
67 |
+
U, S, V = np.linalg.svd(A)
|
68 |
+
|
69 |
+
# Eq. (40) and (43).
|
70 |
+
rank = np.linalg.matrix_rank(A)
|
71 |
+
if rank == 0:
|
72 |
+
return np.nan * T
|
73 |
+
elif rank == dim - 1:
|
74 |
+
if np.linalg.det(U) * np.linalg.det(V) > 0:
|
75 |
+
T[:dim, :dim] = U @ V
|
76 |
+
else:
|
77 |
+
s = d[dim - 1]
|
78 |
+
d[dim - 1] = -1
|
79 |
+
T[:dim, :dim] = U @ np.diag(d) @ V
|
80 |
+
d[dim - 1] = s
|
81 |
+
else:
|
82 |
+
T[:dim, :dim] = U @ np.diag(d) @ V
|
83 |
+
|
84 |
+
if estimate_scale:
|
85 |
+
# Eq. (41) and (42).
|
86 |
+
scale = 1.0 / src_demean.var(axis=0).sum() * (S @ d)
|
87 |
+
else:
|
88 |
+
scale = scale
|
89 |
+
|
90 |
+
T[:dim, dim] = dst_mean - scale * (T[:dim, :dim] @ src_mean.T)
|
91 |
+
T[:dim, :dim] *= scale
|
92 |
+
|
93 |
+
return T, scale
|
94 |
+
|
95 |
+
|
96 |
+
class FaceWarpException(Exception):
|
97 |
+
def __str__(self):
|
98 |
+
return 'In File {}:{}'.format(
|
99 |
+
__file__, super.__str__(self))
|
100 |
+
|
101 |
+
|
102 |
+
def get_reference_facial_points(output_size=None,
|
103 |
+
inner_padding_factor=0.0,
|
104 |
+
outer_padding=(0, 0),
|
105 |
+
default_square=False):
|
106 |
+
tmp_5pts = np.array(REFERENCE_FACIAL_POINTS)
|
107 |
+
tmp_crop_size = np.array(DEFAULT_CROP_SIZE)
|
108 |
+
|
109 |
+
# 0) make the inner region a square
|
110 |
+
if default_square:
|
111 |
+
size_diff = max(tmp_crop_size) - tmp_crop_size
|
112 |
+
tmp_5pts += size_diff / 2
|
113 |
+
tmp_crop_size += size_diff
|
114 |
+
|
115 |
+
if (output_size and
|
116 |
+
output_size[0] == tmp_crop_size[0] and
|
117 |
+
output_size[1] == tmp_crop_size[1]):
|
118 |
+
print('output_size == DEFAULT_CROP_SIZE {}: return default reference points'.format(tmp_crop_size))
|
119 |
+
return tmp_5pts
|
120 |
+
|
121 |
+
if (inner_padding_factor == 0 and
|
122 |
+
outer_padding == (0, 0)):
|
123 |
+
if output_size is None:
|
124 |
+
print('No paddings to do: return default reference points')
|
125 |
+
return tmp_5pts
|
126 |
+
else:
|
127 |
+
raise FaceWarpException(
|
128 |
+
'No paddings to do, output_size must be None or {}'.format(tmp_crop_size))
|
129 |
+
|
130 |
+
# check output size
|
131 |
+
if not (0 <= inner_padding_factor <= 1.0):
|
132 |
+
raise FaceWarpException('Not (0 <= inner_padding_factor <= 1.0)')
|
133 |
+
|
134 |
+
if ((inner_padding_factor > 0 or outer_padding[0] > 0 or outer_padding[1] > 0)
|
135 |
+
and output_size is None):
|
136 |
+
output_size = tmp_crop_size * \
|
137 |
+
(1 + inner_padding_factor * 2).astype(np.int32)
|
138 |
+
output_size += np.array(outer_padding)
|
139 |
+
print(' deduced from paddings, output_size = ', output_size)
|
140 |
+
|
141 |
+
if not (outer_padding[0] < output_size[0]
|
142 |
+
and outer_padding[1] < output_size[1]):
|
143 |
+
raise FaceWarpException('Not (outer_padding[0] < output_size[0]'
|
144 |
+
'and outer_padding[1] < output_size[1])')
|
145 |
+
|
146 |
+
# 1) pad the inner region according inner_padding_factor
|
147 |
+
# print('---> STEP1: pad the inner region according inner_padding_factor')
|
148 |
+
if inner_padding_factor > 0:
|
149 |
+
size_diff = tmp_crop_size * inner_padding_factor * 2
|
150 |
+
tmp_5pts += size_diff / 2
|
151 |
+
tmp_crop_size += np.round(size_diff).astype(np.int32)
|
152 |
+
|
153 |
+
# print(' crop_size = ', tmp_crop_size)
|
154 |
+
# print(' reference_5pts = ', tmp_5pts)
|
155 |
+
|
156 |
+
# 2) resize the padded inner region
|
157 |
+
# print('---> STEP2: resize the padded inner region')
|
158 |
+
size_bf_outer_pad = np.array(output_size) - np.array(outer_padding) * 2
|
159 |
+
# print(' crop_size = ', tmp_crop_size)
|
160 |
+
# print(' size_bf_outer_pad = ', size_bf_outer_pad)
|
161 |
+
|
162 |
+
if size_bf_outer_pad[0] * tmp_crop_size[1] != size_bf_outer_pad[1] * tmp_crop_size[0]:
|
163 |
+
raise FaceWarpException('Must have (output_size - outer_padding)'
|
164 |
+
'= some_scale * (crop_size * (1.0 + inner_padding_factor)')
|
165 |
+
|
166 |
+
scale_factor = size_bf_outer_pad[0].astype(np.float32) / tmp_crop_size[0]
|
167 |
+
# print(' resize scale_factor = ', scale_factor)
|
168 |
+
tmp_5pts = tmp_5pts * scale_factor
|
169 |
+
# size_diff = tmp_crop_size * (scale_factor - min(scale_factor))
|
170 |
+
# tmp_5pts = tmp_5pts + size_diff / 2
|
171 |
+
tmp_crop_size = size_bf_outer_pad
|
172 |
+
# print(' crop_size = ', tmp_crop_size)
|
173 |
+
# print(' reference_5pts = ', tmp_5pts)
|
174 |
+
|
175 |
+
# 3) add outer_padding to make output_size
|
176 |
+
reference_5point = tmp_5pts + np.array(outer_padding)
|
177 |
+
tmp_crop_size = output_size
|
178 |
+
# print('---> STEP3: add outer_padding to make output_size')
|
179 |
+
# print(' crop_size = ', tmp_crop_size)
|
180 |
+
# print(' reference_5pts = ', tmp_5pts)
|
181 |
+
#
|
182 |
+
# print('===> end get_reference_facial_points\n')
|
183 |
+
|
184 |
+
return reference_5point
|
185 |
+
|
186 |
+
|
187 |
+
def get_affine_transform_matrix(src_pts, dst_pts):
|
188 |
+
tfm = np.float32([[1, 0, 0], [0, 1, 0]])
|
189 |
+
n_pts = src_pts.shape[0]
|
190 |
+
ones = np.ones((n_pts, 1), src_pts.dtype)
|
191 |
+
src_pts_ = np.hstack([src_pts, ones])
|
192 |
+
dst_pts_ = np.hstack([dst_pts, ones])
|
193 |
+
|
194 |
+
A, res, rank, s = np.linalg.lstsq(src_pts_, dst_pts_)
|
195 |
+
|
196 |
+
if rank == 3:
|
197 |
+
tfm = np.float32([
|
198 |
+
[A[0, 0], A[1, 0], A[2, 0]],
|
199 |
+
[A[0, 1], A[1, 1], A[2, 1]]
|
200 |
+
])
|
201 |
+
elif rank == 2:
|
202 |
+
tfm = np.float32([
|
203 |
+
[A[0, 0], A[1, 0], 0],
|
204 |
+
[A[0, 1], A[1, 1], 0]
|
205 |
+
])
|
206 |
+
|
207 |
+
return tfm
|
208 |
+
|
209 |
+
|
210 |
+
def warp_and_crop_face(src_img,
|
211 |
+
facial_pts,
|
212 |
+
reference_pts=None,
|
213 |
+
crop_size=(96, 112),
|
214 |
+
align_type='smilarity'): #smilarity cv2_affine affine
|
215 |
+
if reference_pts is None:
|
216 |
+
if crop_size[0] == 96 and crop_size[1] == 112:
|
217 |
+
reference_pts = REFERENCE_FACIAL_POINTS
|
218 |
+
else:
|
219 |
+
default_square = False
|
220 |
+
inner_padding_factor = 0
|
221 |
+
outer_padding = (0, 0)
|
222 |
+
output_size = crop_size
|
223 |
+
|
224 |
+
reference_pts = get_reference_facial_points(output_size,
|
225 |
+
inner_padding_factor,
|
226 |
+
outer_padding,
|
227 |
+
default_square)
|
228 |
+
|
229 |
+
ref_pts = np.float32(reference_pts)
|
230 |
+
ref_pts_shp = ref_pts.shape
|
231 |
+
if max(ref_pts_shp) < 3 or min(ref_pts_shp) != 2:
|
232 |
+
raise FaceWarpException(
|
233 |
+
'reference_pts.shape must be (K,2) or (2,K) and K>2')
|
234 |
+
|
235 |
+
if ref_pts_shp[0] == 2:
|
236 |
+
ref_pts = ref_pts.T
|
237 |
+
|
238 |
+
src_pts = np.float32(facial_pts)
|
239 |
+
src_pts_shp = src_pts.shape
|
240 |
+
if max(src_pts_shp) < 3 or min(src_pts_shp) != 2:
|
241 |
+
raise FaceWarpException(
|
242 |
+
'facial_pts.shape must be (K,2) or (2,K) and K>2')
|
243 |
+
|
244 |
+
if src_pts_shp[0] == 2:
|
245 |
+
src_pts = src_pts.T
|
246 |
+
|
247 |
+
if src_pts.shape != ref_pts.shape:
|
248 |
+
raise FaceWarpException(
|
249 |
+
'facial_pts and reference_pts must have the same shape')
|
250 |
+
|
251 |
+
if align_type is 'cv2_affine':
|
252 |
+
tfm = cv2.getAffineTransform(src_pts[0:3], ref_pts[0:3])
|
253 |
+
tfm_inv = cv2.getAffineTransform(ref_pts[0:3], src_pts[0:3])
|
254 |
+
elif align_type is 'affine':
|
255 |
+
tfm = get_affine_transform_matrix(src_pts, ref_pts)
|
256 |
+
tfm_inv = get_affine_transform_matrix(ref_pts, src_pts)
|
257 |
+
else:
|
258 |
+
params, scale = _umeyama(src_pts, ref_pts)
|
259 |
+
tfm = params[:2, :]
|
260 |
+
|
261 |
+
params, _ = _umeyama(ref_pts, src_pts, False, scale=1.0/scale)
|
262 |
+
tfm_inv = params[:2, :]
|
263 |
+
|
264 |
+
face_img = cv2.warpAffine(src_img, tfm, (crop_size[0], crop_size[1]), flags=3)
|
265 |
+
|
266 |
+
return face_img, tfm_inv
|
data_loader/dataset_face.py
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
import os
|
4 |
+
import glob
|
5 |
+
import math
|
6 |
+
import random
|
7 |
+
import torch
|
8 |
+
import torch.nn.functional as F
|
9 |
+
from torch.utils.data import Dataset
|
10 |
+
|
11 |
+
import degradations
|
12 |
+
|
13 |
+
|
14 |
+
class GFPGAN_degradation(object):
|
15 |
+
def __init__(self):
|
16 |
+
self.kernel_list = ['iso', 'aniso']
|
17 |
+
self.kernel_prob = [0.5, 0.5]
|
18 |
+
self.blur_kernel_size = 41
|
19 |
+
self.blur_sigma = [0.1, 10]
|
20 |
+
self.downsample_range = [0.8, 8]
|
21 |
+
self.noise_range = [0, 20]
|
22 |
+
self.jpeg_range = [60, 100]
|
23 |
+
self.gray_prob = 0.2
|
24 |
+
self.color_jitter_prob = 0.0
|
25 |
+
self.color_jitter_pt_prob = 0.0
|
26 |
+
self.shift = 20/255.
|
27 |
+
|
28 |
+
def degrade_process(self, img_gt):
|
29 |
+
if random.random() > 0.5:
|
30 |
+
img_gt = cv2.flip(img_gt, 1)
|
31 |
+
|
32 |
+
h, w = img_gt.shape[:2]
|
33 |
+
|
34 |
+
# random color jitter
|
35 |
+
if np.random.uniform() < self.color_jitter_prob:
|
36 |
+
jitter_val = np.random.uniform(-self.shift, self.shift, 3).astype(np.float32)
|
37 |
+
img_gt = img_gt + jitter_val
|
38 |
+
img_gt = np.clip(img_gt, 0, 1)
|
39 |
+
|
40 |
+
# random grayscale
|
41 |
+
if np.random.uniform() < self.gray_prob:
|
42 |
+
img_gt = cv2.cvtColor(img_gt, cv2.COLOR_BGR2GRAY)
|
43 |
+
img_gt = np.tile(img_gt[:, :, None], [1, 1, 3])
|
44 |
+
|
45 |
+
# ------------------------ generate lq image ------------------------ #
|
46 |
+
# blur
|
47 |
+
kernel = degradations.random_mixed_kernels(
|
48 |
+
self.kernel_list,
|
49 |
+
self.kernel_prob,
|
50 |
+
self.blur_kernel_size,
|
51 |
+
self.blur_sigma,
|
52 |
+
self.blur_sigma, [-math.pi, math.pi],
|
53 |
+
noise_range=None)
|
54 |
+
img_lq = cv2.filter2D(img_gt, -1, kernel)
|
55 |
+
# downsample
|
56 |
+
scale = np.random.uniform(self.downsample_range[0], self.downsample_range[1])
|
57 |
+
img_lq = cv2.resize(img_lq, (int(w // scale), int(h // scale)), interpolation=cv2.INTER_LINEAR)
|
58 |
+
|
59 |
+
# noise
|
60 |
+
if self.noise_range is not None:
|
61 |
+
img_lq = degradations.random_add_gaussian_noise(img_lq, self.noise_range)
|
62 |
+
# jpeg compression
|
63 |
+
if self.jpeg_range is not None:
|
64 |
+
img_lq = degradations.random_add_jpg_compression(img_lq, self.jpeg_range)
|
65 |
+
|
66 |
+
# round and clip
|
67 |
+
img_lq = np.clip((img_lq * 255.0).round(), 0, 255) / 255.
|
68 |
+
|
69 |
+
# resize to original size
|
70 |
+
img_lq = cv2.resize(img_lq, (w, h), interpolation=cv2.INTER_LINEAR)
|
71 |
+
|
72 |
+
return img_gt, img_lq
|
73 |
+
|
74 |
+
class FaceDataset(Dataset):
|
75 |
+
def __init__(self, path, resolution=512):
|
76 |
+
self.resolution = resolution
|
77 |
+
|
78 |
+
self.HQ_imgs = glob.glob(os.path.join(path, '*.*'))
|
79 |
+
self.length = len(self.HQ_imgs)
|
80 |
+
|
81 |
+
self.degrader = GFPGAN_degradation()
|
82 |
+
|
83 |
+
def __len__(self):
|
84 |
+
return self.length
|
85 |
+
|
86 |
+
def __getitem__(self, index):
|
87 |
+
img_gt = cv2.imread(self.HQ_imgs[index], cv2.IMREAD_COLOR)
|
88 |
+
img_gt = cv2.resize(img_gt, (self.resolution, self.resolution), interpolation=cv2.INTER_AREA)
|
89 |
+
|
90 |
+
# BFR degradation
|
91 |
+
# We adopt the degradation of GFPGAN for simplicity, which however differs from our implementation in the paper.
|
92 |
+
# Data degradation plays a key role in BFR. Please replace it with your own methods.
|
93 |
+
img_gt = img_gt.astype(np.float32)/255.
|
94 |
+
img_gt, img_lq = self.degrader.degrade_process(img_gt)
|
95 |
+
|
96 |
+
img_gt = (torch.from_numpy(img_gt) - 0.5) / 0.5
|
97 |
+
img_lq = (torch.from_numpy(img_lq) - 0.5) / 0.5
|
98 |
+
|
99 |
+
img_gt = img_gt.permute(2, 0, 1).flip(0) # BGR->RGB
|
100 |
+
img_lq = img_lq.permute(2, 0, 1).flip(0) # BGR->RGB
|
101 |
+
|
102 |
+
return img_lq, img_gt
|
103 |
+
|
data_loader/degradations.py
ADDED
@@ -0,0 +1,765 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import math
|
3 |
+
import numpy as np
|
4 |
+
import random
|
5 |
+
import torch
|
6 |
+
from scipy import special
|
7 |
+
from scipy.stats import multivariate_normal
|
8 |
+
from torchvision.transforms.functional_tensor import rgb_to_grayscale
|
9 |
+
|
10 |
+
# -------------------------------------------------------------------- #
|
11 |
+
# --------------------------- blur kernels --------------------------- #
|
12 |
+
# -------------------------------------------------------------------- #
|
13 |
+
|
14 |
+
|
15 |
+
# --------------------------- util functions --------------------------- #
|
16 |
+
def sigma_matrix2(sig_x, sig_y, theta):
|
17 |
+
"""Calculate the rotated sigma matrix (two dimensional matrix).
|
18 |
+
|
19 |
+
Args:
|
20 |
+
sig_x (float):
|
21 |
+
sig_y (float):
|
22 |
+
theta (float): Radian measurement.
|
23 |
+
|
24 |
+
Returns:
|
25 |
+
ndarray: Rotated sigma matrix.
|
26 |
+
"""
|
27 |
+
d_matrix = np.array([[sig_x**2, 0], [0, sig_y**2]])
|
28 |
+
u_matrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
|
29 |
+
return np.dot(u_matrix, np.dot(d_matrix, u_matrix.T))
|
30 |
+
|
31 |
+
|
32 |
+
def mesh_grid(kernel_size):
|
33 |
+
"""Generate the mesh grid, centering at zero.
|
34 |
+
|
35 |
+
Args:
|
36 |
+
kernel_size (int):
|
37 |
+
|
38 |
+
Returns:
|
39 |
+
xy (ndarray): with the shape (kernel_size, kernel_size, 2)
|
40 |
+
xx (ndarray): with the shape (kernel_size, kernel_size)
|
41 |
+
yy (ndarray): with the shape (kernel_size, kernel_size)
|
42 |
+
"""
|
43 |
+
ax = np.arange(-kernel_size // 2 + 1., kernel_size // 2 + 1.)
|
44 |
+
xx, yy = np.meshgrid(ax, ax)
|
45 |
+
xy = np.hstack((xx.reshape((kernel_size * kernel_size, 1)), yy.reshape(kernel_size * kernel_size,
|
46 |
+
1))).reshape(kernel_size, kernel_size, 2)
|
47 |
+
return xy, xx, yy
|
48 |
+
|
49 |
+
|
50 |
+
def pdf2(sigma_matrix, grid):
|
51 |
+
"""Calculate PDF of the bivariate Gaussian distribution.
|
52 |
+
|
53 |
+
Args:
|
54 |
+
sigma_matrix (ndarray): with the shape (2, 2)
|
55 |
+
grid (ndarray): generated by :func:`mesh_grid`,
|
56 |
+
with the shape (K, K, 2), K is the kernel size.
|
57 |
+
|
58 |
+
Returns:
|
59 |
+
kernel (ndarrray): un-normalized kernel.
|
60 |
+
"""
|
61 |
+
inverse_sigma = np.linalg.inv(sigma_matrix)
|
62 |
+
kernel = np.exp(-0.5 * np.sum(np.dot(grid, inverse_sigma) * grid, 2))
|
63 |
+
return kernel
|
64 |
+
|
65 |
+
|
66 |
+
def cdf2(d_matrix, grid):
|
67 |
+
"""Calculate the CDF of the standard bivariate Gaussian distribution.
|
68 |
+
Used in skewed Gaussian distribution.
|
69 |
+
|
70 |
+
Args:
|
71 |
+
d_matrix (ndarrasy): skew matrix.
|
72 |
+
grid (ndarray): generated by :func:`mesh_grid`,
|
73 |
+
with the shape (K, K, 2), K is the kernel size.
|
74 |
+
|
75 |
+
Returns:
|
76 |
+
cdf (ndarray): skewed cdf.
|
77 |
+
"""
|
78 |
+
rv = multivariate_normal([0, 0], [[1, 0], [0, 1]])
|
79 |
+
grid = np.dot(grid, d_matrix)
|
80 |
+
cdf = rv.cdf(grid)
|
81 |
+
return cdf
|
82 |
+
|
83 |
+
|
84 |
+
def bivariate_Gaussian(kernel_size, sig_x, sig_y, theta, grid=None, isotropic=True):
|
85 |
+
"""Generate a bivariate isotropic or anisotropic Gaussian kernel.
|
86 |
+
|
87 |
+
In the isotropic mode, only `sig_x` is used. `sig_y` and `theta` is ignored.
|
88 |
+
|
89 |
+
Args:
|
90 |
+
kernel_size (int):
|
91 |
+
sig_x (float):
|
92 |
+
sig_y (float):
|
93 |
+
theta (float): Radian measurement.
|
94 |
+
grid (ndarray, optional): generated by :func:`mesh_grid`,
|
95 |
+
with the shape (K, K, 2), K is the kernel size. Default: None
|
96 |
+
isotropic (bool):
|
97 |
+
|
98 |
+
Returns:
|
99 |
+
kernel (ndarray): normalized kernel.
|
100 |
+
"""
|
101 |
+
if grid is None:
|
102 |
+
grid, _, _ = mesh_grid(kernel_size)
|
103 |
+
if isotropic:
|
104 |
+
sigma_matrix = np.array([[sig_x**2, 0], [0, sig_x**2]])
|
105 |
+
else:
|
106 |
+
sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)
|
107 |
+
kernel = pdf2(sigma_matrix, grid)
|
108 |
+
kernel = kernel / np.sum(kernel)
|
109 |
+
return kernel
|
110 |
+
|
111 |
+
|
112 |
+
def bivariate_generalized_Gaussian(kernel_size, sig_x, sig_y, theta, beta, grid=None, isotropic=True):
|
113 |
+
"""Generate a bivariate generalized Gaussian kernel.
|
114 |
+
Described in `Parameter Estimation For Multivariate Generalized
|
115 |
+
Gaussian Distributions`_
|
116 |
+
by Pascal et. al (2013).
|
117 |
+
|
118 |
+
In the isotropic mode, only `sig_x` is used. `sig_y` and `theta` is ignored.
|
119 |
+
|
120 |
+
Args:
|
121 |
+
kernel_size (int):
|
122 |
+
sig_x (float):
|
123 |
+
sig_y (float):
|
124 |
+
theta (float): Radian measurement.
|
125 |
+
beta (float): shape parameter, beta = 1 is the normal distribution.
|
126 |
+
grid (ndarray, optional): generated by :func:`mesh_grid`,
|
127 |
+
with the shape (K, K, 2), K is the kernel size. Default: None
|
128 |
+
|
129 |
+
Returns:
|
130 |
+
kernel (ndarray): normalized kernel.
|
131 |
+
|
132 |
+
.. _Parameter Estimation For Multivariate Generalized Gaussian
|
133 |
+
Distributions: https://arxiv.org/abs/1302.6498
|
134 |
+
"""
|
135 |
+
if grid is None:
|
136 |
+
grid, _, _ = mesh_grid(kernel_size)
|
137 |
+
if isotropic:
|
138 |
+
sigma_matrix = np.array([[sig_x**2, 0], [0, sig_x**2]])
|
139 |
+
else:
|
140 |
+
sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)
|
141 |
+
inverse_sigma = np.linalg.inv(sigma_matrix)
|
142 |
+
kernel = np.exp(-0.5 * np.power(np.sum(np.dot(grid, inverse_sigma) * grid, 2), beta))
|
143 |
+
kernel = kernel / np.sum(kernel)
|
144 |
+
return kernel
|
145 |
+
|
146 |
+
|
147 |
+
def bivariate_plateau(kernel_size, sig_x, sig_y, theta, beta, grid=None, isotropic=True):
|
148 |
+
"""Generate a plateau-like anisotropic kernel.
|
149 |
+
1 / (1+x^(beta))
|
150 |
+
|
151 |
+
Ref: https://stats.stackexchange.com/questions/203629/is-there-a-plateau-shaped-distribution
|
152 |
+
|
153 |
+
In the isotropic mode, only `sig_x` is used. `sig_y` and `theta` is ignored.
|
154 |
+
|
155 |
+
Args:
|
156 |
+
kernel_size (int):
|
157 |
+
sig_x (float):
|
158 |
+
sig_y (float):
|
159 |
+
theta (float): Radian measurement.
|
160 |
+
beta (float): shape parameter, beta = 1 is the normal distribution.
|
161 |
+
grid (ndarray, optional): generated by :func:`mesh_grid`,
|
162 |
+
with the shape (K, K, 2), K is the kernel size. Default: None
|
163 |
+
|
164 |
+
Returns:
|
165 |
+
kernel (ndarray): normalized kernel.
|
166 |
+
"""
|
167 |
+
if grid is None:
|
168 |
+
grid, _, _ = mesh_grid(kernel_size)
|
169 |
+
if isotropic:
|
170 |
+
sigma_matrix = np.array([[sig_x**2, 0], [0, sig_x**2]])
|
171 |
+
else:
|
172 |
+
sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)
|
173 |
+
inverse_sigma = np.linalg.inv(sigma_matrix)
|
174 |
+
kernel = np.reciprocal(np.power(np.sum(np.dot(grid, inverse_sigma) * grid, 2), beta) + 1)
|
175 |
+
kernel = kernel / np.sum(kernel)
|
176 |
+
return kernel
|
177 |
+
|
178 |
+
|
179 |
+
def random_bivariate_Gaussian(kernel_size,
|
180 |
+
sigma_x_range,
|
181 |
+
sigma_y_range,
|
182 |
+
rotation_range,
|
183 |
+
noise_range=None,
|
184 |
+
isotropic=True):
|
185 |
+
"""Randomly generate bivariate isotropic or anisotropic Gaussian kernels.
|
186 |
+
|
187 |
+
In the isotropic mode, only `sigma_x_range` is used. `sigma_y_range` and `rotation_range` is ignored.
|
188 |
+
|
189 |
+
Args:
|
190 |
+
kernel_size (int):
|
191 |
+
sigma_x_range (tuple): [0.6, 5]
|
192 |
+
sigma_y_range (tuple): [0.6, 5]
|
193 |
+
rotation range (tuple): [-math.pi, math.pi]
|
194 |
+
noise_range(tuple, optional): multiplicative kernel noise,
|
195 |
+
[0.75, 1.25]. Default: None
|
196 |
+
|
197 |
+
Returns:
|
198 |
+
kernel (ndarray):
|
199 |
+
"""
|
200 |
+
assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
|
201 |
+
assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'
|
202 |
+
sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])
|
203 |
+
if isotropic is False:
|
204 |
+
assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'
|
205 |
+
assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'
|
206 |
+
sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])
|
207 |
+
rotation = np.random.uniform(rotation_range[0], rotation_range[1])
|
208 |
+
else:
|
209 |
+
sigma_y = sigma_x
|
210 |
+
rotation = 0
|
211 |
+
|
212 |
+
kernel = bivariate_Gaussian(kernel_size, sigma_x, sigma_y, rotation, isotropic=isotropic)
|
213 |
+
|
214 |
+
# add multiplicative noise
|
215 |
+
if noise_range is not None:
|
216 |
+
assert noise_range[0] < noise_range[1], 'Wrong noise range.'
|
217 |
+
noise = np.random.uniform(noise_range[0], noise_range[1], size=kernel.shape)
|
218 |
+
kernel = kernel * noise
|
219 |
+
kernel = kernel / np.sum(kernel)
|
220 |
+
return kernel
|
221 |
+
|
222 |
+
|
223 |
+
def random_bivariate_generalized_Gaussian(kernel_size,
|
224 |
+
sigma_x_range,
|
225 |
+
sigma_y_range,
|
226 |
+
rotation_range,
|
227 |
+
beta_range,
|
228 |
+
noise_range=None,
|
229 |
+
isotropic=True):
|
230 |
+
"""Randomly generate bivariate generalized Gaussian kernels.
|
231 |
+
|
232 |
+
In the isotropic mode, only `sigma_x_range` is used. `sigma_y_range` and `rotation_range` is ignored.
|
233 |
+
|
234 |
+
Args:
|
235 |
+
kernel_size (int):
|
236 |
+
sigma_x_range (tuple): [0.6, 5]
|
237 |
+
sigma_y_range (tuple): [0.6, 5]
|
238 |
+
rotation range (tuple): [-math.pi, math.pi]
|
239 |
+
beta_range (tuple): [0.5, 8]
|
240 |
+
noise_range(tuple, optional): multiplicative kernel noise,
|
241 |
+
[0.75, 1.25]. Default: None
|
242 |
+
|
243 |
+
Returns:
|
244 |
+
kernel (ndarray):
|
245 |
+
"""
|
246 |
+
assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
|
247 |
+
assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'
|
248 |
+
sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])
|
249 |
+
if isotropic is False:
|
250 |
+
assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'
|
251 |
+
assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'
|
252 |
+
sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])
|
253 |
+
rotation = np.random.uniform(rotation_range[0], rotation_range[1])
|
254 |
+
else:
|
255 |
+
sigma_y = sigma_x
|
256 |
+
rotation = 0
|
257 |
+
|
258 |
+
# assume beta_range[0] < 1 < beta_range[1]
|
259 |
+
if np.random.uniform() < 0.5:
|
260 |
+
beta = np.random.uniform(beta_range[0], 1)
|
261 |
+
else:
|
262 |
+
beta = np.random.uniform(1, beta_range[1])
|
263 |
+
|
264 |
+
kernel = bivariate_generalized_Gaussian(kernel_size, sigma_x, sigma_y, rotation, beta, isotropic=isotropic)
|
265 |
+
|
266 |
+
# add multiplicative noise
|
267 |
+
if noise_range is not None:
|
268 |
+
assert noise_range[0] < noise_range[1], 'Wrong noise range.'
|
269 |
+
noise = np.random.uniform(noise_range[0], noise_range[1], size=kernel.shape)
|
270 |
+
kernel = kernel * noise
|
271 |
+
kernel = kernel / np.sum(kernel)
|
272 |
+
return kernel
|
273 |
+
|
274 |
+
|
275 |
+
def random_bivariate_plateau(kernel_size,
|
276 |
+
sigma_x_range,
|
277 |
+
sigma_y_range,
|
278 |
+
rotation_range,
|
279 |
+
beta_range,
|
280 |
+
noise_range=None,
|
281 |
+
isotropic=True):
|
282 |
+
"""Randomly generate bivariate plateau kernels.
|
283 |
+
|
284 |
+
In the isotropic mode, only `sigma_x_range` is used. `sigma_y_range` and `rotation_range` is ignored.
|
285 |
+
|
286 |
+
Args:
|
287 |
+
kernel_size (int):
|
288 |
+
sigma_x_range (tuple): [0.6, 5]
|
289 |
+
sigma_y_range (tuple): [0.6, 5]
|
290 |
+
rotation range (tuple): [-math.pi/2, math.pi/2]
|
291 |
+
beta_range (tuple): [1, 4]
|
292 |
+
noise_range(tuple, optional): multiplicative kernel noise,
|
293 |
+
[0.75, 1.25]. Default: None
|
294 |
+
|
295 |
+
Returns:
|
296 |
+
kernel (ndarray):
|
297 |
+
"""
|
298 |
+
assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
|
299 |
+
assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'
|
300 |
+
sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])
|
301 |
+
if isotropic is False:
|
302 |
+
assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'
|
303 |
+
assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'
|
304 |
+
sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])
|
305 |
+
rotation = np.random.uniform(rotation_range[0], rotation_range[1])
|
306 |
+
else:
|
307 |
+
sigma_y = sigma_x
|
308 |
+
rotation = 0
|
309 |
+
|
310 |
+
# TODO: this may be not proper
|
311 |
+
if np.random.uniform() < 0.5:
|
312 |
+
beta = np.random.uniform(beta_range[0], 1)
|
313 |
+
else:
|
314 |
+
beta = np.random.uniform(1, beta_range[1])
|
315 |
+
|
316 |
+
kernel = bivariate_plateau(kernel_size, sigma_x, sigma_y, rotation, beta, isotropic=isotropic)
|
317 |
+
# add multiplicative noise
|
318 |
+
if noise_range is not None:
|
319 |
+
assert noise_range[0] < noise_range[1], 'Wrong noise range.'
|
320 |
+
noise = np.random.uniform(noise_range[0], noise_range[1], size=kernel.shape)
|
321 |
+
kernel = kernel * noise
|
322 |
+
kernel = kernel / np.sum(kernel)
|
323 |
+
|
324 |
+
return kernel
|
325 |
+
|
326 |
+
|
327 |
+
def random_mixed_kernels(kernel_list,
|
328 |
+
kernel_prob,
|
329 |
+
kernel_size=21,
|
330 |
+
sigma_x_range=(0.6, 5),
|
331 |
+
sigma_y_range=(0.6, 5),
|
332 |
+
rotation_range=(-math.pi, math.pi),
|
333 |
+
betag_range=(0.5, 8),
|
334 |
+
betap_range=(0.5, 8),
|
335 |
+
noise_range=None):
|
336 |
+
"""Randomly generate mixed kernels.
|
337 |
+
|
338 |
+
Args:
|
339 |
+
kernel_list (tuple): a list name of kernel types,
|
340 |
+
support ['iso', 'aniso', 'skew', 'generalized', 'plateau_iso',
|
341 |
+
'plateau_aniso']
|
342 |
+
kernel_prob (tuple): corresponding kernel probability for each
|
343 |
+
kernel type
|
344 |
+
kernel_size (int):
|
345 |
+
sigma_x_range (tuple): [0.6, 5]
|
346 |
+
sigma_y_range (tuple): [0.6, 5]
|
347 |
+
rotation range (tuple): [-math.pi, math.pi]
|
348 |
+
beta_range (tuple): [0.5, 8]
|
349 |
+
noise_range(tuple, optional): multiplicative kernel noise,
|
350 |
+
[0.75, 1.25]. Default: None
|
351 |
+
|
352 |
+
Returns:
|
353 |
+
kernel (ndarray):
|
354 |
+
"""
|
355 |
+
kernel_type = random.choices(kernel_list, kernel_prob)[0]
|
356 |
+
if kernel_type == 'iso':
|
357 |
+
kernel = random_bivariate_Gaussian(
|
358 |
+
kernel_size, sigma_x_range, sigma_y_range, rotation_range, noise_range=noise_range, isotropic=True)
|
359 |
+
elif kernel_type == 'aniso':
|
360 |
+
kernel = random_bivariate_Gaussian(
|
361 |
+
kernel_size, sigma_x_range, sigma_y_range, rotation_range, noise_range=noise_range, isotropic=False)
|
362 |
+
elif kernel_type == 'generalized_iso':
|
363 |
+
kernel = random_bivariate_generalized_Gaussian(
|
364 |
+
kernel_size,
|
365 |
+
sigma_x_range,
|
366 |
+
sigma_y_range,
|
367 |
+
rotation_range,
|
368 |
+
betag_range,
|
369 |
+
noise_range=noise_range,
|
370 |
+
isotropic=True)
|
371 |
+
elif kernel_type == 'generalized_aniso':
|
372 |
+
kernel = random_bivariate_generalized_Gaussian(
|
373 |
+
kernel_size,
|
374 |
+
sigma_x_range,
|
375 |
+
sigma_y_range,
|
376 |
+
rotation_range,
|
377 |
+
betag_range,
|
378 |
+
noise_range=noise_range,
|
379 |
+
isotropic=False)
|
380 |
+
elif kernel_type == 'plateau_iso':
|
381 |
+
kernel = random_bivariate_plateau(
|
382 |
+
kernel_size, sigma_x_range, sigma_y_range, rotation_range, betap_range, noise_range=None, isotropic=True)
|
383 |
+
elif kernel_type == 'plateau_aniso':
|
384 |
+
kernel = random_bivariate_plateau(
|
385 |
+
kernel_size, sigma_x_range, sigma_y_range, rotation_range, betap_range, noise_range=None, isotropic=False)
|
386 |
+
return kernel
|
387 |
+
|
388 |
+
|
389 |
+
np.seterr(divide='ignore', invalid='ignore')
|
390 |
+
|
391 |
+
|
392 |
+
def circular_lowpass_kernel(cutoff, kernel_size, pad_to=0):
|
393 |
+
"""2D sinc filter, ref: https://dsp.stackexchange.com/questions/58301/2-d-circularly-symmetric-low-pass-filter
|
394 |
+
|
395 |
+
Args:
|
396 |
+
cutoff (float): cutoff frequency in radians (pi is max)
|
397 |
+
kernel_size (int): horizontal and vertical size, must be odd.
|
398 |
+
pad_to (int): pad kernel size to desired size, must be odd or zero.
|
399 |
+
"""
|
400 |
+
assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
|
401 |
+
kernel = np.fromfunction(
|
402 |
+
lambda x, y: cutoff * special.j1(cutoff * np.sqrt(
|
403 |
+
(x - (kernel_size - 1) / 2)**2 + (y - (kernel_size - 1) / 2)**2)) / (2 * np.pi * np.sqrt(
|
404 |
+
(x - (kernel_size - 1) / 2)**2 + (y - (kernel_size - 1) / 2)**2)), [kernel_size, kernel_size])
|
405 |
+
kernel[(kernel_size - 1) // 2, (kernel_size - 1) // 2] = cutoff**2 / (4 * np.pi)
|
406 |
+
kernel = kernel / np.sum(kernel)
|
407 |
+
if pad_to > kernel_size:
|
408 |
+
pad_size = (pad_to - kernel_size) // 2
|
409 |
+
kernel = np.pad(kernel, ((pad_size, pad_size), (pad_size, pad_size)))
|
410 |
+
return kernel
|
411 |
+
|
412 |
+
|
413 |
+
# ------------------------------------------------------------- #
|
414 |
+
# --------------------------- noise --------------------------- #
|
415 |
+
# ------------------------------------------------------------- #
|
416 |
+
|
417 |
+
# ----------------------- Gaussian Noise ----------------------- #
|
418 |
+
|
419 |
+
|
420 |
+
def generate_gaussian_noise(img, sigma=10, gray_noise=False):
|
421 |
+
"""Generate Gaussian noise.
|
422 |
+
|
423 |
+
Args:
|
424 |
+
img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.
|
425 |
+
sigma (float): Noise scale (measured in range 255). Default: 10.
|
426 |
+
|
427 |
+
Returns:
|
428 |
+
(Numpy array): Returned noisy image, shape (h, w, c), range[0, 1],
|
429 |
+
float32.
|
430 |
+
"""
|
431 |
+
if gray_noise:
|
432 |
+
noise = np.float32(np.random.randn(*(img.shape[0:2]))) * sigma / 255.
|
433 |
+
noise = np.expand_dims(noise, axis=2).repeat(3, axis=2)
|
434 |
+
else:
|
435 |
+
noise = np.float32(np.random.randn(*(img.shape))) * sigma / 255.
|
436 |
+
return noise
|
437 |
+
|
438 |
+
|
439 |
+
def add_gaussian_noise(img, sigma=10, clip=True, rounds=False, gray_noise=False):
|
440 |
+
"""Add Gaussian noise.
|
441 |
+
|
442 |
+
Args:
|
443 |
+
img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.
|
444 |
+
sigma (float): Noise scale (measured in range 255). Default: 10.
|
445 |
+
|
446 |
+
Returns:
|
447 |
+
(Numpy array): Returned noisy image, shape (h, w, c), range[0, 1],
|
448 |
+
float32.
|
449 |
+
"""
|
450 |
+
noise = generate_gaussian_noise(img, sigma, gray_noise)
|
451 |
+
out = img + noise
|
452 |
+
if clip and rounds:
|
453 |
+
out = np.clip((out * 255.0).round(), 0, 255) / 255.
|
454 |
+
elif clip:
|
455 |
+
out = np.clip(out, 0, 1)
|
456 |
+
elif rounds:
|
457 |
+
out = (out * 255.0).round() / 255.
|
458 |
+
return out
|
459 |
+
|
460 |
+
|
461 |
+
def generate_gaussian_noise_pt(img, sigma=10, gray_noise=0):
|
462 |
+
"""Add Gaussian noise (PyTorch version).
|
463 |
+
|
464 |
+
Args:
|
465 |
+
img (Tensor): Shape (b, c, h, w), range[0, 1], float32.
|
466 |
+
scale (float | Tensor): Noise scale. Default: 1.0.
|
467 |
+
|
468 |
+
Returns:
|
469 |
+
(Tensor): Returned noisy image, shape (b, c, h, w), range[0, 1],
|
470 |
+
float32.
|
471 |
+
"""
|
472 |
+
b, _, h, w = img.size()
|
473 |
+
if not isinstance(sigma, (float, int)):
|
474 |
+
sigma = sigma.view(img.size(0), 1, 1, 1)
|
475 |
+
if isinstance(gray_noise, (float, int)):
|
476 |
+
cal_gray_noise = gray_noise > 0
|
477 |
+
else:
|
478 |
+
gray_noise = gray_noise.view(b, 1, 1, 1)
|
479 |
+
cal_gray_noise = torch.sum(gray_noise) > 0
|
480 |
+
|
481 |
+
if cal_gray_noise:
|
482 |
+
noise_gray = torch.randn(*img.size()[2:4], dtype=img.dtype, device=img.device) * sigma / 255.
|
483 |
+
noise_gray = noise_gray.view(b, 1, h, w)
|
484 |
+
|
485 |
+
# always calculate color noise
|
486 |
+
noise = torch.randn(*img.size(), dtype=img.dtype, device=img.device) * sigma / 255.
|
487 |
+
|
488 |
+
if cal_gray_noise:
|
489 |
+
noise = noise * (1 - gray_noise) + noise_gray * gray_noise
|
490 |
+
return noise
|
491 |
+
|
492 |
+
|
493 |
+
def add_gaussian_noise_pt(img, sigma=10, gray_noise=0, clip=True, rounds=False):
|
494 |
+
"""Add Gaussian noise (PyTorch version).
|
495 |
+
|
496 |
+
Args:
|
497 |
+
img (Tensor): Shape (b, c, h, w), range[0, 1], float32.
|
498 |
+
scale (float | Tensor): Noise scale. Default: 1.0.
|
499 |
+
|
500 |
+
Returns:
|
501 |
+
(Tensor): Returned noisy image, shape (b, c, h, w), range[0, 1],
|
502 |
+
float32.
|
503 |
+
"""
|
504 |
+
noise = generate_gaussian_noise_pt(img, sigma, gray_noise)
|
505 |
+
out = img + noise
|
506 |
+
if clip and rounds:
|
507 |
+
out = torch.clamp((out * 255.0).round(), 0, 255) / 255.
|
508 |
+
elif clip:
|
509 |
+
out = torch.clamp(out, 0, 1)
|
510 |
+
elif rounds:
|
511 |
+
out = (out * 255.0).round() / 255.
|
512 |
+
return out
|
513 |
+
|
514 |
+
|
515 |
+
# ----------------------- Random Gaussian Noise ----------------------- #
|
516 |
+
def random_generate_gaussian_noise(img, sigma_range=(0, 10), gray_prob=0):
|
517 |
+
sigma = np.random.uniform(sigma_range[0], sigma_range[1])
|
518 |
+
if np.random.uniform() < gray_prob:
|
519 |
+
gray_noise = True
|
520 |
+
else:
|
521 |
+
gray_noise = False
|
522 |
+
return generate_gaussian_noise(img, sigma, gray_noise)
|
523 |
+
|
524 |
+
|
525 |
+
def random_add_gaussian_noise(img, sigma_range=(0, 1.0), gray_prob=0, clip=True, rounds=False):
|
526 |
+
noise = random_generate_gaussian_noise(img, sigma_range, gray_prob)
|
527 |
+
out = img + noise
|
528 |
+
if clip and rounds:
|
529 |
+
out = np.clip((out * 255.0).round(), 0, 255) / 255.
|
530 |
+
elif clip:
|
531 |
+
out = np.clip(out, 0, 1)
|
532 |
+
elif rounds:
|
533 |
+
out = (out * 255.0).round() / 255.
|
534 |
+
return out
|
535 |
+
|
536 |
+
|
537 |
+
def random_generate_gaussian_noise_pt(img, sigma_range=(0, 10), gray_prob=0):
|
538 |
+
sigma = torch.rand(
|
539 |
+
img.size(0), dtype=img.dtype, device=img.device) * (sigma_range[1] - sigma_range[0]) + sigma_range[0]
|
540 |
+
gray_noise = torch.rand(img.size(0), dtype=img.dtype, device=img.device)
|
541 |
+
gray_noise = (gray_noise < gray_prob).float()
|
542 |
+
return generate_gaussian_noise_pt(img, sigma, gray_noise)
|
543 |
+
|
544 |
+
|
545 |
+
def random_add_gaussian_noise_pt(img, sigma_range=(0, 1.0), gray_prob=0, clip=True, rounds=False):
|
546 |
+
noise = random_generate_gaussian_noise_pt(img, sigma_range, gray_prob)
|
547 |
+
out = img + noise
|
548 |
+
if clip and rounds:
|
549 |
+
out = torch.clamp((out * 255.0).round(), 0, 255) / 255.
|
550 |
+
elif clip:
|
551 |
+
out = torch.clamp(out, 0, 1)
|
552 |
+
elif rounds:
|
553 |
+
out = (out * 255.0).round() / 255.
|
554 |
+
return out
|
555 |
+
|
556 |
+
|
557 |
+
# ----------------------- Poisson (Shot) Noise ----------------------- #
|
558 |
+
|
559 |
+
|
560 |
+
def generate_poisson_noise(img, scale=1.0, gray_noise=False):
|
561 |
+
"""Generate poisson noise.
|
562 |
+
|
563 |
+
Ref: https://github.com/scikit-image/scikit-image/blob/main/skimage/util/noise.py#L37-L219
|
564 |
+
|
565 |
+
Args:
|
566 |
+
img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.
|
567 |
+
scale (float): Noise scale. Default: 1.0.
|
568 |
+
gray_noise (bool): Whether generate gray noise. Default: False.
|
569 |
+
|
570 |
+
Returns:
|
571 |
+
(Numpy array): Returned noisy image, shape (h, w, c), range[0, 1],
|
572 |
+
float32.
|
573 |
+
"""
|
574 |
+
if gray_noise:
|
575 |
+
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
576 |
+
# round and clip image for counting vals correctly
|
577 |
+
img = np.clip((img * 255.0).round(), 0, 255) / 255.
|
578 |
+
vals = len(np.unique(img))
|
579 |
+
vals = 2**np.ceil(np.log2(vals))
|
580 |
+
out = np.float32(np.random.poisson(img * vals) / float(vals))
|
581 |
+
noise = out - img
|
582 |
+
if gray_noise:
|
583 |
+
noise = np.repeat(noise[:, :, np.newaxis], 3, axis=2)
|
584 |
+
return noise * scale
|
585 |
+
|
586 |
+
|
587 |
+
def add_poisson_noise(img, scale=1.0, clip=True, rounds=False, gray_noise=False):
|
588 |
+
"""Add poisson noise.
|
589 |
+
|
590 |
+
Args:
|
591 |
+
img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.
|
592 |
+
scale (float): Noise scale. Default: 1.0.
|
593 |
+
gray_noise (bool): Whether generate gray noise. Default: False.
|
594 |
+
|
595 |
+
Returns:
|
596 |
+
(Numpy array): Returned noisy image, shape (h, w, c), range[0, 1],
|
597 |
+
float32.
|
598 |
+
"""
|
599 |
+
noise = generate_poisson_noise(img, scale, gray_noise)
|
600 |
+
out = img + noise
|
601 |
+
if clip and rounds:
|
602 |
+
out = np.clip((out * 255.0).round(), 0, 255) / 255.
|
603 |
+
elif clip:
|
604 |
+
out = np.clip(out, 0, 1)
|
605 |
+
elif rounds:
|
606 |
+
out = (out * 255.0).round() / 255.
|
607 |
+
return out
|
608 |
+
|
609 |
+
|
610 |
+
def generate_poisson_noise_pt(img, scale=1.0, gray_noise=0):
|
611 |
+
"""Generate a batch of poisson noise (PyTorch version)
|
612 |
+
|
613 |
+
Args:
|
614 |
+
img (Tensor): Input image, shape (b, c, h, w), range [0, 1], float32.
|
615 |
+
scale (float | Tensor): Noise scale. Number or Tensor with shape (b).
|
616 |
+
Default: 1.0.
|
617 |
+
gray_noise (float | Tensor): 0-1 number or Tensor with shape (b).
|
618 |
+
0 for False, 1 for True. Default: 0.
|
619 |
+
|
620 |
+
Returns:
|
621 |
+
(Tensor): Returned noisy image, shape (b, c, h, w), range[0, 1],
|
622 |
+
float32.
|
623 |
+
"""
|
624 |
+
b, _, h, w = img.size()
|
625 |
+
if isinstance(gray_noise, (float, int)):
|
626 |
+
cal_gray_noise = gray_noise > 0
|
627 |
+
else:
|
628 |
+
gray_noise = gray_noise.view(b, 1, 1, 1)
|
629 |
+
cal_gray_noise = torch.sum(gray_noise) > 0
|
630 |
+
if cal_gray_noise:
|
631 |
+
img_gray = rgb_to_grayscale(img, num_output_channels=1)
|
632 |
+
# round and clip image for counting vals correctly
|
633 |
+
img_gray = torch.clamp((img_gray * 255.0).round(), 0, 255) / 255.
|
634 |
+
# use for-loop to get the unique values for each sample
|
635 |
+
vals_list = [len(torch.unique(img_gray[i, :, :, :])) for i in range(b)]
|
636 |
+
vals_list = [2**np.ceil(np.log2(vals)) for vals in vals_list]
|
637 |
+
vals = img_gray.new_tensor(vals_list).view(b, 1, 1, 1)
|
638 |
+
out = torch.poisson(img_gray * vals) / vals
|
639 |
+
noise_gray = out - img_gray
|
640 |
+
noise_gray = noise_gray.expand(b, 3, h, w)
|
641 |
+
|
642 |
+
# always calculate color noise
|
643 |
+
# round and clip image for counting vals correctly
|
644 |
+
img = torch.clamp((img * 255.0).round(), 0, 255) / 255.
|
645 |
+
# use for-loop to get the unique values for each sample
|
646 |
+
vals_list = [len(torch.unique(img[i, :, :, :])) for i in range(b)]
|
647 |
+
vals_list = [2**np.ceil(np.log2(vals)) for vals in vals_list]
|
648 |
+
vals = img.new_tensor(vals_list).view(b, 1, 1, 1)
|
649 |
+
out = torch.poisson(img * vals) / vals
|
650 |
+
noise = out - img
|
651 |
+
if cal_gray_noise:
|
652 |
+
noise = noise * (1 - gray_noise) + noise_gray * gray_noise
|
653 |
+
if not isinstance(scale, (float, int)):
|
654 |
+
scale = scale.view(b, 1, 1, 1)
|
655 |
+
return noise * scale
|
656 |
+
|
657 |
+
|
658 |
+
def add_poisson_noise_pt(img, scale=1.0, clip=True, rounds=False, gray_noise=0):
|
659 |
+
"""Add poisson noise to a batch of images (PyTorch version).
|
660 |
+
|
661 |
+
Args:
|
662 |
+
img (Tensor): Input image, shape (b, c, h, w), range [0, 1], float32.
|
663 |
+
scale (float | Tensor): Noise scale. Number or Tensor with shape (b).
|
664 |
+
Default: 1.0.
|
665 |
+
gray_noise (float | Tensor): 0-1 number or Tensor with shape (b).
|
666 |
+
0 for False, 1 for True. Default: 0.
|
667 |
+
|
668 |
+
Returns:
|
669 |
+
(Tensor): Returned noisy image, shape (b, c, h, w), range[0, 1],
|
670 |
+
float32.
|
671 |
+
"""
|
672 |
+
noise = generate_poisson_noise_pt(img, scale, gray_noise)
|
673 |
+
out = img + noise
|
674 |
+
if clip and rounds:
|
675 |
+
out = torch.clamp((out * 255.0).round(), 0, 255) / 255.
|
676 |
+
elif clip:
|
677 |
+
out = torch.clamp(out, 0, 1)
|
678 |
+
elif rounds:
|
679 |
+
out = (out * 255.0).round() / 255.
|
680 |
+
return out
|
681 |
+
|
682 |
+
|
683 |
+
# ----------------------- Random Poisson (Shot) Noise ----------------------- #
|
684 |
+
|
685 |
+
|
686 |
+
def random_generate_poisson_noise(img, scale_range=(0, 1.0), gray_prob=0):
|
687 |
+
scale = np.random.uniform(scale_range[0], scale_range[1])
|
688 |
+
if np.random.uniform() < gray_prob:
|
689 |
+
gray_noise = True
|
690 |
+
else:
|
691 |
+
gray_noise = False
|
692 |
+
return generate_poisson_noise(img, scale, gray_noise)
|
693 |
+
|
694 |
+
|
695 |
+
def random_add_poisson_noise(img, scale_range=(0, 1.0), gray_prob=0, clip=True, rounds=False):
|
696 |
+
noise = random_generate_poisson_noise(img, scale_range, gray_prob)
|
697 |
+
out = img + noise
|
698 |
+
if clip and rounds:
|
699 |
+
out = np.clip((out * 255.0).round(), 0, 255) / 255.
|
700 |
+
elif clip:
|
701 |
+
out = np.clip(out, 0, 1)
|
702 |
+
elif rounds:
|
703 |
+
out = (out * 255.0).round() / 255.
|
704 |
+
return out
|
705 |
+
|
706 |
+
|
707 |
+
def random_generate_poisson_noise_pt(img, scale_range=(0, 1.0), gray_prob=0):
|
708 |
+
scale = torch.rand(
|
709 |
+
img.size(0), dtype=img.dtype, device=img.device) * (scale_range[1] - scale_range[0]) + scale_range[0]
|
710 |
+
gray_noise = torch.rand(img.size(0), dtype=img.dtype, device=img.device)
|
711 |
+
gray_noise = (gray_noise < gray_prob).float()
|
712 |
+
return generate_poisson_noise_pt(img, scale, gray_noise)
|
713 |
+
|
714 |
+
|
715 |
+
def random_add_poisson_noise_pt(img, scale_range=(0, 1.0), gray_prob=0, clip=True, rounds=False):
|
716 |
+
noise = random_generate_poisson_noise_pt(img, scale_range, gray_prob)
|
717 |
+
out = img + noise
|
718 |
+
if clip and rounds:
|
719 |
+
out = torch.clamp((out * 255.0).round(), 0, 255) / 255.
|
720 |
+
elif clip:
|
721 |
+
out = torch.clamp(out, 0, 1)
|
722 |
+
elif rounds:
|
723 |
+
out = (out * 255.0).round() / 255.
|
724 |
+
return out
|
725 |
+
|
726 |
+
|
727 |
+
# ------------------------------------------------------------------------ #
|
728 |
+
# --------------------------- JPEG compression --------------------------- #
|
729 |
+
# ------------------------------------------------------------------------ #
|
730 |
+
|
731 |
+
|
732 |
+
def add_jpg_compression(img, quality=90):
|
733 |
+
"""Add JPG compression artifacts.
|
734 |
+
|
735 |
+
Args:
|
736 |
+
img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.
|
737 |
+
quality (float): JPG compression quality. 0 for lowest quality, 100 for
|
738 |
+
best quality. Default: 90.
|
739 |
+
|
740 |
+
Returns:
|
741 |
+
(Numpy array): Returned image after JPG, shape (h, w, c), range[0, 1],
|
742 |
+
float32.
|
743 |
+
"""
|
744 |
+
img = np.clip(img, 0, 1)
|
745 |
+
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
|
746 |
+
_, encimg = cv2.imencode('.jpg', img * 255., encode_param)
|
747 |
+
img = np.float32(cv2.imdecode(encimg, 1)) / 255.
|
748 |
+
return img
|
749 |
+
|
750 |
+
|
751 |
+
def random_add_jpg_compression(img, quality_range=(90, 100)):
|
752 |
+
"""Randomly add JPG compression artifacts.
|
753 |
+
|
754 |
+
Args:
|
755 |
+
img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.
|
756 |
+
quality_range (tuple[float] | list[float]): JPG compression quality
|
757 |
+
range. 0 for lowest quality, 100 for best quality.
|
758 |
+
Default: (90, 100).
|
759 |
+
|
760 |
+
Returns:
|
761 |
+
(Numpy array): Returned image after JPG, shape (h, w, c), range[0, 1],
|
762 |
+
float32.
|
763 |
+
"""
|
764 |
+
quality = int(np.random.uniform(quality_range[0], quality_range[1]))
|
765 |
+
return add_jpg_compression(img, quality)
|
distributed.py
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
import pickle
|
3 |
+
|
4 |
+
import torch
|
5 |
+
from torch import distributed as dist
|
6 |
+
from torch.utils.data.sampler import Sampler
|
7 |
+
|
8 |
+
|
9 |
+
def get_rank():
|
10 |
+
if not dist.is_available():
|
11 |
+
return 0
|
12 |
+
|
13 |
+
if not dist.is_initialized():
|
14 |
+
return 0
|
15 |
+
|
16 |
+
return dist.get_rank()
|
17 |
+
|
18 |
+
|
19 |
+
def synchronize():
|
20 |
+
if not dist.is_available():
|
21 |
+
return
|
22 |
+
|
23 |
+
if not dist.is_initialized():
|
24 |
+
return
|
25 |
+
|
26 |
+
world_size = dist.get_world_size()
|
27 |
+
|
28 |
+
if world_size == 1:
|
29 |
+
return
|
30 |
+
|
31 |
+
dist.barrier()
|
32 |
+
|
33 |
+
|
34 |
+
def get_world_size():
|
35 |
+
if not dist.is_available():
|
36 |
+
return 1
|
37 |
+
|
38 |
+
if not dist.is_initialized():
|
39 |
+
return 1
|
40 |
+
|
41 |
+
return dist.get_world_size()
|
42 |
+
|
43 |
+
|
44 |
+
def reduce_sum(tensor):
|
45 |
+
if not dist.is_available():
|
46 |
+
return tensor
|
47 |
+
|
48 |
+
if not dist.is_initialized():
|
49 |
+
return tensor
|
50 |
+
|
51 |
+
tensor = tensor.clone()
|
52 |
+
dist.all_reduce(tensor, op=dist.ReduceOp.SUM)
|
53 |
+
|
54 |
+
return tensor
|
55 |
+
|
56 |
+
|
57 |
+
def gather_grad(params):
|
58 |
+
world_size = get_world_size()
|
59 |
+
|
60 |
+
if world_size == 1:
|
61 |
+
return
|
62 |
+
|
63 |
+
for param in params:
|
64 |
+
if param.grad is not None:
|
65 |
+
dist.all_reduce(param.grad.data, op=dist.ReduceOp.SUM)
|
66 |
+
param.grad.data.div_(world_size)
|
67 |
+
|
68 |
+
|
69 |
+
def all_gather(data):
|
70 |
+
world_size = get_world_size()
|
71 |
+
|
72 |
+
if world_size == 1:
|
73 |
+
return [data]
|
74 |
+
|
75 |
+
buffer = pickle.dumps(data)
|
76 |
+
storage = torch.ByteStorage.from_buffer(buffer)
|
77 |
+
tensor = torch.ByteTensor(storage).to('cuda')
|
78 |
+
|
79 |
+
local_size = torch.IntTensor([tensor.numel()]).to('cuda')
|
80 |
+
size_list = [torch.IntTensor([0]).to('cuda') for _ in range(world_size)]
|
81 |
+
dist.all_gather(size_list, local_size)
|
82 |
+
size_list = [int(size.item()) for size in size_list]
|
83 |
+
max_size = max(size_list)
|
84 |
+
|
85 |
+
tensor_list = []
|
86 |
+
for _ in size_list:
|
87 |
+
tensor_list.append(torch.ByteTensor(size=(max_size,)).to('cuda'))
|
88 |
+
|
89 |
+
if local_size != max_size:
|
90 |
+
padding = torch.ByteTensor(size=(max_size - local_size,)).to('cuda')
|
91 |
+
tensor = torch.cat((tensor, padding), 0)
|
92 |
+
|
93 |
+
dist.all_gather(tensor_list, tensor)
|
94 |
+
|
95 |
+
data_list = []
|
96 |
+
|
97 |
+
for size, tensor in zip(size_list, tensor_list):
|
98 |
+
buffer = tensor.cpu().numpy().tobytes()[:size]
|
99 |
+
data_list.append(pickle.loads(buffer))
|
100 |
+
|
101 |
+
return data_list
|
102 |
+
|
103 |
+
|
104 |
+
def reduce_loss_dict(loss_dict):
|
105 |
+
world_size = get_world_size()
|
106 |
+
|
107 |
+
if world_size < 2:
|
108 |
+
return loss_dict
|
109 |
+
|
110 |
+
with torch.no_grad():
|
111 |
+
keys = []
|
112 |
+
losses = []
|
113 |
+
|
114 |
+
for k in sorted(loss_dict.keys()):
|
115 |
+
keys.append(k)
|
116 |
+
losses.append(loss_dict[k])
|
117 |
+
|
118 |
+
losses = torch.stack(losses, 0)
|
119 |
+
dist.reduce(losses, dst=0)
|
120 |
+
|
121 |
+
if dist.get_rank() == 0:
|
122 |
+
losses /= world_size
|
123 |
+
|
124 |
+
reduced_losses = {k: v for k, v in zip(keys, losses)}
|
125 |
+
|
126 |
+
return reduced_losses
|
face_colorization.py
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@paper: GAN Prior Embedded Network for Blind Face Restoration in the Wild (CVPR2021)
|
3 |
+
@author: yangxy (yangtao9009@gmail.com)
|
4 |
+
'''
|
5 |
+
import os
|
6 |
+
import cv2
|
7 |
+
import glob
|
8 |
+
import time
|
9 |
+
import numpy as np
|
10 |
+
from PIL import Image
|
11 |
+
import __init_paths
|
12 |
+
from face_model.face_gan import FaceGAN
|
13 |
+
|
14 |
+
class FaceColorization(object):
|
15 |
+
def __init__(self, base_dir='./', size=1024, model=None, channel_multiplier=2):
|
16 |
+
self.facegan = FaceGAN(base_dir, size, model, channel_multiplier)
|
17 |
+
|
18 |
+
# make sure the face image is well aligned. Please refer to face_enhancement.py
|
19 |
+
def process(self, gray):
|
20 |
+
# colorize the face
|
21 |
+
out = self.facegan.process(gray)
|
22 |
+
|
23 |
+
return out
|
24 |
+
|
25 |
+
|
26 |
+
if __name__=='__main__':
|
27 |
+
model = {'name':'GPEN-Colorization-1024', 'size':1024}
|
28 |
+
|
29 |
+
indir = 'examples/grays'
|
30 |
+
outdir = 'examples/outs-colorization'
|
31 |
+
os.makedirs(outdir, exist_ok=True)
|
32 |
+
|
33 |
+
facecolorizer = FaceColorization(size=model['size'], model=model['name'], channel_multiplier=2)
|
34 |
+
|
35 |
+
files = sorted(glob.glob(os.path.join(indir, '*.*g')))
|
36 |
+
for n, file in enumerate(files[:]):
|
37 |
+
filename = os.path.basename(file)
|
38 |
+
|
39 |
+
grayf = cv2.imread(file, cv2.IMREAD_GRAYSCALE)
|
40 |
+
grayf = cv2.cvtColor(grayf, cv2.COLOR_GRAY2BGR) # channel: 1->3
|
41 |
+
|
42 |
+
colorf = facecolorizer.process(grayf)
|
43 |
+
|
44 |
+
grayf = cv2.resize(grayf, colorf.shape[:2])
|
45 |
+
cv2.imwrite(os.path.join(outdir, '.'.join(filename.split('.')[:-1])+'.jpg'), np.hstack((grayf, colorf)))
|
46 |
+
|
47 |
+
if n%10==0: print(n, file)
|
48 |
+
|
face_detect/data/FDDB/img_list.txt
ADDED
@@ -0,0 +1,2845 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2002/08/11/big/img_591
|
2 |
+
2002/08/26/big/img_265
|
3 |
+
2002/07/19/big/img_423
|
4 |
+
2002/08/24/big/img_490
|
5 |
+
2002/08/31/big/img_17676
|
6 |
+
2002/07/31/big/img_228
|
7 |
+
2002/07/24/big/img_402
|
8 |
+
2002/08/04/big/img_769
|
9 |
+
2002/07/19/big/img_581
|
10 |
+
2002/08/13/big/img_723
|
11 |
+
2002/08/12/big/img_821
|
12 |
+
2003/01/17/big/img_610
|
13 |
+
2002/08/13/big/img_1116
|
14 |
+
2002/08/28/big/img_19238
|
15 |
+
2002/08/21/big/img_660
|
16 |
+
2002/08/14/big/img_607
|
17 |
+
2002/08/05/big/img_3708
|
18 |
+
2002/08/19/big/img_511
|
19 |
+
2002/08/07/big/img_1316
|
20 |
+
2002/07/25/big/img_1047
|
21 |
+
2002/07/23/big/img_474
|
22 |
+
2002/07/27/big/img_970
|
23 |
+
2002/09/02/big/img_15752
|
24 |
+
2002/09/01/big/img_16378
|
25 |
+
2002/09/01/big/img_16189
|
26 |
+
2002/08/26/big/img_276
|
27 |
+
2002/07/24/big/img_518
|
28 |
+
2002/08/14/big/img_1027
|
29 |
+
2002/08/24/big/img_733
|
30 |
+
2002/08/15/big/img_249
|
31 |
+
2003/01/15/big/img_1371
|
32 |
+
2002/08/07/big/img_1348
|
33 |
+
2003/01/01/big/img_331
|
34 |
+
2002/08/23/big/img_536
|
35 |
+
2002/07/30/big/img_224
|
36 |
+
2002/08/10/big/img_763
|
37 |
+
2002/08/21/big/img_293
|
38 |
+
2002/08/15/big/img_1211
|
39 |
+
2002/08/15/big/img_1194
|
40 |
+
2003/01/15/big/img_390
|
41 |
+
2002/08/06/big/img_2893
|
42 |
+
2002/08/17/big/img_691
|
43 |
+
2002/08/07/big/img_1695
|
44 |
+
2002/08/16/big/img_829
|
45 |
+
2002/07/25/big/img_201
|
46 |
+
2002/08/23/big/img_36
|
47 |
+
2003/01/15/big/img_763
|
48 |
+
2003/01/15/big/img_637
|
49 |
+
2002/08/22/big/img_592
|
50 |
+
2002/07/25/big/img_817
|
51 |
+
2003/01/15/big/img_1219
|
52 |
+
2002/08/05/big/img_3508
|
53 |
+
2002/08/15/big/img_1108
|
54 |
+
2002/07/19/big/img_488
|
55 |
+
2003/01/16/big/img_704
|
56 |
+
2003/01/13/big/img_1087
|
57 |
+
2002/08/10/big/img_670
|
58 |
+
2002/07/24/big/img_104
|
59 |
+
2002/08/27/big/img_19823
|
60 |
+
2002/09/01/big/img_16229
|
61 |
+
2003/01/13/big/img_846
|
62 |
+
2002/08/04/big/img_412
|
63 |
+
2002/07/22/big/img_554
|
64 |
+
2002/08/12/big/img_331
|
65 |
+
2002/08/02/big/img_533
|
66 |
+
2002/08/12/big/img_259
|
67 |
+
2002/08/18/big/img_328
|
68 |
+
2003/01/14/big/img_630
|
69 |
+
2002/08/05/big/img_3541
|
70 |
+
2002/08/06/big/img_2390
|
71 |
+
2002/08/20/big/img_150
|
72 |
+
2002/08/02/big/img_1231
|
73 |
+
2002/08/16/big/img_710
|
74 |
+
2002/08/19/big/img_591
|
75 |
+
2002/07/22/big/img_725
|
76 |
+
2002/07/24/big/img_820
|
77 |
+
2003/01/13/big/img_568
|
78 |
+
2002/08/22/big/img_853
|
79 |
+
2002/08/09/big/img_648
|
80 |
+
2002/08/23/big/img_528
|
81 |
+
2003/01/14/big/img_888
|
82 |
+
2002/08/30/big/img_18201
|
83 |
+
2002/08/13/big/img_965
|
84 |
+
2003/01/14/big/img_660
|
85 |
+
2002/07/19/big/img_517
|
86 |
+
2003/01/14/big/img_406
|
87 |
+
2002/08/30/big/img_18433
|
88 |
+
2002/08/07/big/img_1630
|
89 |
+
2002/08/06/big/img_2717
|
90 |
+
2002/08/21/big/img_470
|
91 |
+
2002/07/23/big/img_633
|
92 |
+
2002/08/20/big/img_915
|
93 |
+
2002/08/16/big/img_893
|
94 |
+
2002/07/29/big/img_644
|
95 |
+
2002/08/15/big/img_529
|
96 |
+
2002/08/16/big/img_668
|
97 |
+
2002/08/07/big/img_1871
|
98 |
+
2002/07/25/big/img_192
|
99 |
+
2002/07/31/big/img_961
|
100 |
+
2002/08/19/big/img_738
|
101 |
+
2002/07/31/big/img_382
|
102 |
+
2002/08/19/big/img_298
|
103 |
+
2003/01/17/big/img_608
|
104 |
+
2002/08/21/big/img_514
|
105 |
+
2002/07/23/big/img_183
|
106 |
+
2003/01/17/big/img_536
|
107 |
+
2002/07/24/big/img_478
|
108 |
+
2002/08/06/big/img_2997
|
109 |
+
2002/09/02/big/img_15380
|
110 |
+
2002/08/07/big/img_1153
|
111 |
+
2002/07/31/big/img_967
|
112 |
+
2002/07/31/big/img_711
|
113 |
+
2002/08/26/big/img_664
|
114 |
+
2003/01/01/big/img_326
|
115 |
+
2002/08/24/big/img_775
|
116 |
+
2002/08/08/big/img_961
|
117 |
+
2002/08/16/big/img_77
|
118 |
+
2002/08/12/big/img_296
|
119 |
+
2002/07/22/big/img_905
|
120 |
+
2003/01/13/big/img_284
|
121 |
+
2002/08/13/big/img_887
|
122 |
+
2002/08/24/big/img_849
|
123 |
+
2002/07/30/big/img_345
|
124 |
+
2002/08/18/big/img_419
|
125 |
+
2002/08/01/big/img_1347
|
126 |
+
2002/08/05/big/img_3670
|
127 |
+
2002/07/21/big/img_479
|
128 |
+
2002/08/08/big/img_913
|
129 |
+
2002/09/02/big/img_15828
|
130 |
+
2002/08/30/big/img_18194
|
131 |
+
2002/08/08/big/img_471
|
132 |
+
2002/08/22/big/img_734
|
133 |
+
2002/08/09/big/img_586
|
134 |
+
2002/08/09/big/img_454
|
135 |
+
2002/07/29/big/img_47
|
136 |
+
2002/07/19/big/img_381
|
137 |
+
2002/07/29/big/img_733
|
138 |
+
2002/08/20/big/img_327
|
139 |
+
2002/07/21/big/img_96
|
140 |
+
2002/08/06/big/img_2680
|
141 |
+
2002/07/25/big/img_919
|
142 |
+
2002/07/21/big/img_158
|
143 |
+
2002/07/22/big/img_801
|
144 |
+
2002/07/22/big/img_567
|
145 |
+
2002/07/24/big/img_804
|
146 |
+
2002/07/24/big/img_690
|
147 |
+
2003/01/15/big/img_576
|
148 |
+
2002/08/14/big/img_335
|
149 |
+
2003/01/13/big/img_390
|
150 |
+
2002/08/11/big/img_258
|
151 |
+
2002/07/23/big/img_917
|
152 |
+
2002/08/15/big/img_525
|
153 |
+
2003/01/15/big/img_505
|
154 |
+
2002/07/30/big/img_886
|
155 |
+
2003/01/16/big/img_640
|
156 |
+
2003/01/14/big/img_642
|
157 |
+
2003/01/17/big/img_844
|
158 |
+
2002/08/04/big/img_571
|
159 |
+
2002/08/29/big/img_18702
|
160 |
+
2003/01/15/big/img_240
|
161 |
+
2002/07/29/big/img_553
|
162 |
+
2002/08/10/big/img_354
|
163 |
+
2002/08/18/big/img_17
|
164 |
+
2003/01/15/big/img_782
|
165 |
+
2002/07/27/big/img_382
|
166 |
+
2002/08/14/big/img_970
|
167 |
+
2003/01/16/big/img_70
|
168 |
+
2003/01/16/big/img_625
|
169 |
+
2002/08/18/big/img_341
|
170 |
+
2002/08/26/big/img_188
|
171 |
+
2002/08/09/big/img_405
|
172 |
+
2002/08/02/big/img_37
|
173 |
+
2002/08/13/big/img_748
|
174 |
+
2002/07/22/big/img_399
|
175 |
+
2002/07/25/big/img_844
|
176 |
+
2002/08/12/big/img_340
|
177 |
+
2003/01/13/big/img_815
|
178 |
+
2002/08/26/big/img_5
|
179 |
+
2002/08/10/big/img_158
|
180 |
+
2002/08/18/big/img_95
|
181 |
+
2002/07/29/big/img_1297
|
182 |
+
2003/01/13/big/img_508
|
183 |
+
2002/09/01/big/img_16680
|
184 |
+
2003/01/16/big/img_338
|
185 |
+
2002/08/13/big/img_517
|
186 |
+
2002/07/22/big/img_626
|
187 |
+
2002/08/06/big/img_3024
|
188 |
+
2002/07/26/big/img_499
|
189 |
+
2003/01/13/big/img_387
|
190 |
+
2002/08/31/big/img_18025
|
191 |
+
2002/08/13/big/img_520
|
192 |
+
2003/01/16/big/img_576
|
193 |
+
2002/07/26/big/img_121
|
194 |
+
2002/08/25/big/img_703
|
195 |
+
2002/08/26/big/img_615
|
196 |
+
2002/08/17/big/img_434
|
197 |
+
2002/08/02/big/img_677
|
198 |
+
2002/08/18/big/img_276
|
199 |
+
2002/08/05/big/img_3672
|
200 |
+
2002/07/26/big/img_700
|
201 |
+
2002/07/31/big/img_277
|
202 |
+
2003/01/14/big/img_220
|
203 |
+
2002/08/23/big/img_232
|
204 |
+
2002/08/31/big/img_17422
|
205 |
+
2002/07/22/big/img_508
|
206 |
+
2002/08/13/big/img_681
|
207 |
+
2003/01/15/big/img_638
|
208 |
+
2002/08/30/big/img_18408
|
209 |
+
2003/01/14/big/img_533
|
210 |
+
2003/01/17/big/img_12
|
211 |
+
2002/08/28/big/img_19388
|
212 |
+
2002/08/08/big/img_133
|
213 |
+
2002/07/26/big/img_885
|
214 |
+
2002/08/19/big/img_387
|
215 |
+
2002/08/27/big/img_19976
|
216 |
+
2002/08/26/big/img_118
|
217 |
+
2002/08/28/big/img_19146
|
218 |
+
2002/08/05/big/img_3259
|
219 |
+
2002/08/15/big/img_536
|
220 |
+
2002/07/22/big/img_279
|
221 |
+
2002/07/22/big/img_9
|
222 |
+
2002/08/13/big/img_301
|
223 |
+
2002/08/15/big/img_974
|
224 |
+
2002/08/06/big/img_2355
|
225 |
+
2002/08/01/big/img_1526
|
226 |
+
2002/08/03/big/img_417
|
227 |
+
2002/08/04/big/img_407
|
228 |
+
2002/08/15/big/img_1029
|
229 |
+
2002/07/29/big/img_700
|
230 |
+
2002/08/01/big/img_1463
|
231 |
+
2002/08/31/big/img_17365
|
232 |
+
2002/07/28/big/img_223
|
233 |
+
2002/07/19/big/img_827
|
234 |
+
2002/07/27/big/img_531
|
235 |
+
2002/07/19/big/img_845
|
236 |
+
2002/08/20/big/img_382
|
237 |
+
2002/07/31/big/img_268
|
238 |
+
2002/08/27/big/img_19705
|
239 |
+
2002/08/02/big/img_830
|
240 |
+
2002/08/23/big/img_250
|
241 |
+
2002/07/20/big/img_777
|
242 |
+
2002/08/21/big/img_879
|
243 |
+
2002/08/26/big/img_20146
|
244 |
+
2002/08/23/big/img_789
|
245 |
+
2002/08/06/big/img_2683
|
246 |
+
2002/08/25/big/img_576
|
247 |
+
2002/08/09/big/img_498
|
248 |
+
2002/08/08/big/img_384
|
249 |
+
2002/08/26/big/img_592
|
250 |
+
2002/07/29/big/img_1470
|
251 |
+
2002/08/21/big/img_452
|
252 |
+
2002/08/30/big/img_18395
|
253 |
+
2002/08/15/big/img_215
|
254 |
+
2002/07/21/big/img_643
|
255 |
+
2002/07/22/big/img_209
|
256 |
+
2003/01/17/big/img_346
|
257 |
+
2002/08/25/big/img_658
|
258 |
+
2002/08/21/big/img_221
|
259 |
+
2002/08/14/big/img_60
|
260 |
+
2003/01/17/big/img_885
|
261 |
+
2003/01/16/big/img_482
|
262 |
+
2002/08/19/big/img_593
|
263 |
+
2002/08/08/big/img_233
|
264 |
+
2002/07/30/big/img_458
|
265 |
+
2002/07/23/big/img_384
|
266 |
+
2003/01/15/big/img_670
|
267 |
+
2003/01/15/big/img_267
|
268 |
+
2002/08/26/big/img_540
|
269 |
+
2002/07/29/big/img_552
|
270 |
+
2002/07/30/big/img_997
|
271 |
+
2003/01/17/big/img_377
|
272 |
+
2002/08/21/big/img_265
|
273 |
+
2002/08/09/big/img_561
|
274 |
+
2002/07/31/big/img_945
|
275 |
+
2002/09/02/big/img_15252
|
276 |
+
2002/08/11/big/img_276
|
277 |
+
2002/07/22/big/img_491
|
278 |
+
2002/07/26/big/img_517
|
279 |
+
2002/08/14/big/img_726
|
280 |
+
2002/08/08/big/img_46
|
281 |
+
2002/08/28/big/img_19458
|
282 |
+
2002/08/06/big/img_2935
|
283 |
+
2002/07/29/big/img_1392
|
284 |
+
2002/08/13/big/img_776
|
285 |
+
2002/08/24/big/img_616
|
286 |
+
2002/08/14/big/img_1065
|
287 |
+
2002/07/29/big/img_889
|
288 |
+
2002/08/18/big/img_188
|
289 |
+
2002/08/07/big/img_1453
|
290 |
+
2002/08/02/big/img_760
|
291 |
+
2002/07/28/big/img_416
|
292 |
+
2002/08/07/big/img_1393
|
293 |
+
2002/08/26/big/img_292
|
294 |
+
2002/08/26/big/img_301
|
295 |
+
2003/01/13/big/img_195
|
296 |
+
2002/07/26/big/img_532
|
297 |
+
2002/08/20/big/img_550
|
298 |
+
2002/08/05/big/img_3658
|
299 |
+
2002/08/26/big/img_738
|
300 |
+
2002/09/02/big/img_15750
|
301 |
+
2003/01/17/big/img_451
|
302 |
+
2002/07/23/big/img_339
|
303 |
+
2002/08/16/big/img_637
|
304 |
+
2002/08/14/big/img_748
|
305 |
+
2002/08/06/big/img_2739
|
306 |
+
2002/07/25/big/img_482
|
307 |
+
2002/08/19/big/img_191
|
308 |
+
2002/08/26/big/img_537
|
309 |
+
2003/01/15/big/img_716
|
310 |
+
2003/01/15/big/img_767
|
311 |
+
2002/08/02/big/img_452
|
312 |
+
2002/08/08/big/img_1011
|
313 |
+
2002/08/10/big/img_144
|
314 |
+
2003/01/14/big/img_122
|
315 |
+
2002/07/24/big/img_586
|
316 |
+
2002/07/24/big/img_762
|
317 |
+
2002/08/20/big/img_369
|
318 |
+
2002/07/30/big/img_146
|
319 |
+
2002/08/23/big/img_396
|
320 |
+
2003/01/15/big/img_200
|
321 |
+
2002/08/15/big/img_1183
|
322 |
+
2003/01/14/big/img_698
|
323 |
+
2002/08/09/big/img_792
|
324 |
+
2002/08/06/big/img_2347
|
325 |
+
2002/07/31/big/img_911
|
326 |
+
2002/08/26/big/img_722
|
327 |
+
2002/08/23/big/img_621
|
328 |
+
2002/08/05/big/img_3790
|
329 |
+
2003/01/13/big/img_633
|
330 |
+
2002/08/09/big/img_224
|
331 |
+
2002/07/24/big/img_454
|
332 |
+
2002/07/21/big/img_202
|
333 |
+
2002/08/02/big/img_630
|
334 |
+
2002/08/30/big/img_18315
|
335 |
+
2002/07/19/big/img_491
|
336 |
+
2002/09/01/big/img_16456
|
337 |
+
2002/08/09/big/img_242
|
338 |
+
2002/07/25/big/img_595
|
339 |
+
2002/07/22/big/img_522
|
340 |
+
2002/08/01/big/img_1593
|
341 |
+
2002/07/29/big/img_336
|
342 |
+
2002/08/15/big/img_448
|
343 |
+
2002/08/28/big/img_19281
|
344 |
+
2002/07/29/big/img_342
|
345 |
+
2002/08/12/big/img_78
|
346 |
+
2003/01/14/big/img_525
|
347 |
+
2002/07/28/big/img_147
|
348 |
+
2002/08/11/big/img_353
|
349 |
+
2002/08/22/big/img_513
|
350 |
+
2002/08/04/big/img_721
|
351 |
+
2002/08/17/big/img_247
|
352 |
+
2003/01/14/big/img_891
|
353 |
+
2002/08/20/big/img_853
|
354 |
+
2002/07/19/big/img_414
|
355 |
+
2002/08/01/big/img_1530
|
356 |
+
2003/01/14/big/img_924
|
357 |
+
2002/08/22/big/img_468
|
358 |
+
2002/08/18/big/img_354
|
359 |
+
2002/08/30/big/img_18193
|
360 |
+
2002/08/23/big/img_492
|
361 |
+
2002/08/15/big/img_871
|
362 |
+
2002/08/12/big/img_494
|
363 |
+
2002/08/06/big/img_2470
|
364 |
+
2002/07/23/big/img_923
|
365 |
+
2002/08/26/big/img_155
|
366 |
+
2002/08/08/big/img_669
|
367 |
+
2002/07/23/big/img_404
|
368 |
+
2002/08/28/big/img_19421
|
369 |
+
2002/08/29/big/img_18993
|
370 |
+
2002/08/25/big/img_416
|
371 |
+
2003/01/17/big/img_434
|
372 |
+
2002/07/29/big/img_1370
|
373 |
+
2002/07/28/big/img_483
|
374 |
+
2002/08/11/big/img_50
|
375 |
+
2002/08/10/big/img_404
|
376 |
+
2002/09/02/big/img_15057
|
377 |
+
2003/01/14/big/img_911
|
378 |
+
2002/09/01/big/img_16697
|
379 |
+
2003/01/16/big/img_665
|
380 |
+
2002/09/01/big/img_16708
|
381 |
+
2002/08/22/big/img_612
|
382 |
+
2002/08/28/big/img_19471
|
383 |
+
2002/08/02/big/img_198
|
384 |
+
2003/01/16/big/img_527
|
385 |
+
2002/08/22/big/img_209
|
386 |
+
2002/08/30/big/img_18205
|
387 |
+
2003/01/14/big/img_114
|
388 |
+
2003/01/14/big/img_1028
|
389 |
+
2003/01/16/big/img_894
|
390 |
+
2003/01/14/big/img_837
|
391 |
+
2002/07/30/big/img_9
|
392 |
+
2002/08/06/big/img_2821
|
393 |
+
2002/08/04/big/img_85
|
394 |
+
2003/01/13/big/img_884
|
395 |
+
2002/07/22/big/img_570
|
396 |
+
2002/08/07/big/img_1773
|
397 |
+
2002/07/26/big/img_208
|
398 |
+
2003/01/17/big/img_946
|
399 |
+
2002/07/19/big/img_930
|
400 |
+
2003/01/01/big/img_698
|
401 |
+
2003/01/17/big/img_612
|
402 |
+
2002/07/19/big/img_372
|
403 |
+
2002/07/30/big/img_721
|
404 |
+
2003/01/14/big/img_649
|
405 |
+
2002/08/19/big/img_4
|
406 |
+
2002/07/25/big/img_1024
|
407 |
+
2003/01/15/big/img_601
|
408 |
+
2002/08/30/big/img_18470
|
409 |
+
2002/07/22/big/img_29
|
410 |
+
2002/08/07/big/img_1686
|
411 |
+
2002/07/20/big/img_294
|
412 |
+
2002/08/14/big/img_800
|
413 |
+
2002/08/19/big/img_353
|
414 |
+
2002/08/19/big/img_350
|
415 |
+
2002/08/05/big/img_3392
|
416 |
+
2002/08/09/big/img_622
|
417 |
+
2003/01/15/big/img_236
|
418 |
+
2002/08/11/big/img_643
|
419 |
+
2002/08/05/big/img_3458
|
420 |
+
2002/08/12/big/img_413
|
421 |
+
2002/08/22/big/img_415
|
422 |
+
2002/08/13/big/img_635
|
423 |
+
2002/08/07/big/img_1198
|
424 |
+
2002/08/04/big/img_873
|
425 |
+
2002/08/12/big/img_407
|
426 |
+
2003/01/15/big/img_346
|
427 |
+
2002/08/02/big/img_275
|
428 |
+
2002/08/17/big/img_997
|
429 |
+
2002/08/21/big/img_958
|
430 |
+
2002/08/20/big/img_579
|
431 |
+
2002/07/29/big/img_142
|
432 |
+
2003/01/14/big/img_1115
|
433 |
+
2002/08/16/big/img_365
|
434 |
+
2002/07/29/big/img_1414
|
435 |
+
2002/08/17/big/img_489
|
436 |
+
2002/08/13/big/img_1010
|
437 |
+
2002/07/31/big/img_276
|
438 |
+
2002/07/25/big/img_1000
|
439 |
+
2002/08/23/big/img_524
|
440 |
+
2002/08/28/big/img_19147
|
441 |
+
2003/01/13/big/img_433
|
442 |
+
2002/08/20/big/img_205
|
443 |
+
2003/01/01/big/img_458
|
444 |
+
2002/07/29/big/img_1449
|
445 |
+
2003/01/16/big/img_696
|
446 |
+
2002/08/28/big/img_19296
|
447 |
+
2002/08/29/big/img_18688
|
448 |
+
2002/08/21/big/img_767
|
449 |
+
2002/08/20/big/img_532
|
450 |
+
2002/08/26/big/img_187
|
451 |
+
2002/07/26/big/img_183
|
452 |
+
2002/07/27/big/img_890
|
453 |
+
2003/01/13/big/img_576
|
454 |
+
2002/07/30/big/img_15
|
455 |
+
2002/07/31/big/img_889
|
456 |
+
2002/08/31/big/img_17759
|
457 |
+
2003/01/14/big/img_1114
|
458 |
+
2002/07/19/big/img_445
|
459 |
+
2002/08/03/big/img_593
|
460 |
+
2002/07/24/big/img_750
|
461 |
+
2002/07/30/big/img_133
|
462 |
+
2002/08/25/big/img_671
|
463 |
+
2002/07/20/big/img_351
|
464 |
+
2002/08/31/big/img_17276
|
465 |
+
2002/08/05/big/img_3231
|
466 |
+
2002/09/02/big/img_15882
|
467 |
+
2002/08/14/big/img_115
|
468 |
+
2002/08/02/big/img_1148
|
469 |
+
2002/07/25/big/img_936
|
470 |
+
2002/07/31/big/img_639
|
471 |
+
2002/08/04/big/img_427
|
472 |
+
2002/08/22/big/img_843
|
473 |
+
2003/01/17/big/img_17
|
474 |
+
2003/01/13/big/img_690
|
475 |
+
2002/08/13/big/img_472
|
476 |
+
2002/08/09/big/img_425
|
477 |
+
2002/08/05/big/img_3450
|
478 |
+
2003/01/17/big/img_439
|
479 |
+
2002/08/13/big/img_539
|
480 |
+
2002/07/28/big/img_35
|
481 |
+
2002/08/16/big/img_241
|
482 |
+
2002/08/06/big/img_2898
|
483 |
+
2003/01/16/big/img_429
|
484 |
+
2002/08/05/big/img_3817
|
485 |
+
2002/08/27/big/img_19919
|
486 |
+
2002/07/19/big/img_422
|
487 |
+
2002/08/15/big/img_560
|
488 |
+
2002/07/23/big/img_750
|
489 |
+
2002/07/30/big/img_353
|
490 |
+
2002/08/05/big/img_43
|
491 |
+
2002/08/23/big/img_305
|
492 |
+
2002/08/01/big/img_2137
|
493 |
+
2002/08/30/big/img_18097
|
494 |
+
2002/08/01/big/img_1389
|
495 |
+
2002/08/02/big/img_308
|
496 |
+
2003/01/14/big/img_652
|
497 |
+
2002/08/01/big/img_1798
|
498 |
+
2003/01/14/big/img_732
|
499 |
+
2003/01/16/big/img_294
|
500 |
+
2002/08/26/big/img_213
|
501 |
+
2002/07/24/big/img_842
|
502 |
+
2003/01/13/big/img_630
|
503 |
+
2003/01/13/big/img_634
|
504 |
+
2002/08/06/big/img_2285
|
505 |
+
2002/08/01/big/img_2162
|
506 |
+
2002/08/30/big/img_18134
|
507 |
+
2002/08/02/big/img_1045
|
508 |
+
2002/08/01/big/img_2143
|
509 |
+
2002/07/25/big/img_135
|
510 |
+
2002/07/20/big/img_645
|
511 |
+
2002/08/05/big/img_3666
|
512 |
+
2002/08/14/big/img_523
|
513 |
+
2002/08/04/big/img_425
|
514 |
+
2003/01/14/big/img_137
|
515 |
+
2003/01/01/big/img_176
|
516 |
+
2002/08/15/big/img_505
|
517 |
+
2002/08/24/big/img_386
|
518 |
+
2002/08/05/big/img_3187
|
519 |
+
2002/08/15/big/img_419
|
520 |
+
2003/01/13/big/img_520
|
521 |
+
2002/08/04/big/img_444
|
522 |
+
2002/08/26/big/img_483
|
523 |
+
2002/08/05/big/img_3449
|
524 |
+
2002/08/30/big/img_18409
|
525 |
+
2002/08/28/big/img_19455
|
526 |
+
2002/08/27/big/img_20090
|
527 |
+
2002/07/23/big/img_625
|
528 |
+
2002/08/24/big/img_205
|
529 |
+
2002/08/08/big/img_938
|
530 |
+
2003/01/13/big/img_527
|
531 |
+
2002/08/07/big/img_1712
|
532 |
+
2002/07/24/big/img_801
|
533 |
+
2002/08/09/big/img_579
|
534 |
+
2003/01/14/big/img_41
|
535 |
+
2003/01/15/big/img_1130
|
536 |
+
2002/07/21/big/img_672
|
537 |
+
2002/08/07/big/img_1590
|
538 |
+
2003/01/01/big/img_532
|
539 |
+
2002/08/02/big/img_529
|
540 |
+
2002/08/05/big/img_3591
|
541 |
+
2002/08/23/big/img_5
|
542 |
+
2003/01/14/big/img_882
|
543 |
+
2002/08/28/big/img_19234
|
544 |
+
2002/07/24/big/img_398
|
545 |
+
2003/01/14/big/img_592
|
546 |
+
2002/08/22/big/img_548
|
547 |
+
2002/08/12/big/img_761
|
548 |
+
2003/01/16/big/img_497
|
549 |
+
2002/08/18/big/img_133
|
550 |
+
2002/08/08/big/img_874
|
551 |
+
2002/07/19/big/img_247
|
552 |
+
2002/08/15/big/img_170
|
553 |
+
2002/08/27/big/img_19679
|
554 |
+
2002/08/20/big/img_246
|
555 |
+
2002/08/24/big/img_358
|
556 |
+
2002/07/29/big/img_599
|
557 |
+
2002/08/01/big/img_1555
|
558 |
+
2002/07/30/big/img_491
|
559 |
+
2002/07/30/big/img_371
|
560 |
+
2003/01/16/big/img_682
|
561 |
+
2002/07/25/big/img_619
|
562 |
+
2003/01/15/big/img_587
|
563 |
+
2002/08/02/big/img_1212
|
564 |
+
2002/08/01/big/img_2152
|
565 |
+
2002/07/25/big/img_668
|
566 |
+
2003/01/16/big/img_574
|
567 |
+
2002/08/28/big/img_19464
|
568 |
+
2002/08/11/big/img_536
|
569 |
+
2002/07/24/big/img_201
|
570 |
+
2002/08/05/big/img_3488
|
571 |
+
2002/07/25/big/img_887
|
572 |
+
2002/07/22/big/img_789
|
573 |
+
2002/07/30/big/img_432
|
574 |
+
2002/08/16/big/img_166
|
575 |
+
2002/09/01/big/img_16333
|
576 |
+
2002/07/26/big/img_1010
|
577 |
+
2002/07/21/big/img_793
|
578 |
+
2002/07/22/big/img_720
|
579 |
+
2002/07/31/big/img_337
|
580 |
+
2002/07/27/big/img_185
|
581 |
+
2002/08/23/big/img_440
|
582 |
+
2002/07/31/big/img_801
|
583 |
+
2002/07/25/big/img_478
|
584 |
+
2003/01/14/big/img_171
|
585 |
+
2002/08/07/big/img_1054
|
586 |
+
2002/09/02/big/img_15659
|
587 |
+
2002/07/29/big/img_1348
|
588 |
+
2002/08/09/big/img_337
|
589 |
+
2002/08/26/big/img_684
|
590 |
+
2002/07/31/big/img_537
|
591 |
+
2002/08/15/big/img_808
|
592 |
+
2003/01/13/big/img_740
|
593 |
+
2002/08/07/big/img_1667
|
594 |
+
2002/08/03/big/img_404
|
595 |
+
2002/08/06/big/img_2520
|
596 |
+
2002/07/19/big/img_230
|
597 |
+
2002/07/19/big/img_356
|
598 |
+
2003/01/16/big/img_627
|
599 |
+
2002/08/04/big/img_474
|
600 |
+
2002/07/29/big/img_833
|
601 |
+
2002/07/25/big/img_176
|
602 |
+
2002/08/01/big/img_1684
|
603 |
+
2002/08/21/big/img_643
|
604 |
+
2002/08/27/big/img_19673
|
605 |
+
2002/08/02/big/img_838
|
606 |
+
2002/08/06/big/img_2378
|
607 |
+
2003/01/15/big/img_48
|
608 |
+
2002/07/30/big/img_470
|
609 |
+
2002/08/15/big/img_963
|
610 |
+
2002/08/24/big/img_444
|
611 |
+
2002/08/16/big/img_662
|
612 |
+
2002/08/15/big/img_1209
|
613 |
+
2002/07/24/big/img_25
|
614 |
+
2002/08/06/big/img_2740
|
615 |
+
2002/07/29/big/img_996
|
616 |
+
2002/08/31/big/img_18074
|
617 |
+
2002/08/04/big/img_343
|
618 |
+
2003/01/17/big/img_509
|
619 |
+
2003/01/13/big/img_726
|
620 |
+
2002/08/07/big/img_1466
|
621 |
+
2002/07/26/big/img_307
|
622 |
+
2002/08/10/big/img_598
|
623 |
+
2002/08/13/big/img_890
|
624 |
+
2002/08/14/big/img_997
|
625 |
+
2002/07/19/big/img_392
|
626 |
+
2002/08/02/big/img_475
|
627 |
+
2002/08/29/big/img_19038
|
628 |
+
2002/07/29/big/img_538
|
629 |
+
2002/07/29/big/img_502
|
630 |
+
2002/08/02/big/img_364
|
631 |
+
2002/08/31/big/img_17353
|
632 |
+
2002/08/08/big/img_539
|
633 |
+
2002/08/01/big/img_1449
|
634 |
+
2002/07/22/big/img_363
|
635 |
+
2002/08/02/big/img_90
|
636 |
+
2002/09/01/big/img_16867
|
637 |
+
2002/08/05/big/img_3371
|
638 |
+
2002/07/30/big/img_342
|
639 |
+
2002/08/07/big/img_1363
|
640 |
+
2002/08/22/big/img_790
|
641 |
+
2003/01/15/big/img_404
|
642 |
+
2002/08/05/big/img_3447
|
643 |
+
2002/09/01/big/img_16167
|
644 |
+
2003/01/13/big/img_840
|
645 |
+
2002/08/22/big/img_1001
|
646 |
+
2002/08/09/big/img_431
|
647 |
+
2002/07/27/big/img_618
|
648 |
+
2002/07/31/big/img_741
|
649 |
+
2002/07/30/big/img_964
|
650 |
+
2002/07/25/big/img_86
|
651 |
+
2002/07/29/big/img_275
|
652 |
+
2002/08/21/big/img_921
|
653 |
+
2002/07/26/big/img_892
|
654 |
+
2002/08/21/big/img_663
|
655 |
+
2003/01/13/big/img_567
|
656 |
+
2003/01/14/big/img_719
|
657 |
+
2002/07/28/big/img_251
|
658 |
+
2003/01/15/big/img_1123
|
659 |
+
2002/07/29/big/img_260
|
660 |
+
2002/08/24/big/img_337
|
661 |
+
2002/08/01/big/img_1914
|
662 |
+
2002/08/13/big/img_373
|
663 |
+
2003/01/15/big/img_589
|
664 |
+
2002/08/13/big/img_906
|
665 |
+
2002/07/26/big/img_270
|
666 |
+
2002/08/26/big/img_313
|
667 |
+
2002/08/25/big/img_694
|
668 |
+
2003/01/01/big/img_327
|
669 |
+
2002/07/23/big/img_261
|
670 |
+
2002/08/26/big/img_642
|
671 |
+
2002/07/29/big/img_918
|
672 |
+
2002/07/23/big/img_455
|
673 |
+
2002/07/24/big/img_612
|
674 |
+
2002/07/23/big/img_534
|
675 |
+
2002/07/19/big/img_534
|
676 |
+
2002/07/19/big/img_726
|
677 |
+
2002/08/01/big/img_2146
|
678 |
+
2002/08/02/big/img_543
|
679 |
+
2003/01/16/big/img_777
|
680 |
+
2002/07/30/big/img_484
|
681 |
+
2002/08/13/big/img_1161
|
682 |
+
2002/07/21/big/img_390
|
683 |
+
2002/08/06/big/img_2288
|
684 |
+
2002/08/21/big/img_677
|
685 |
+
2002/08/13/big/img_747
|
686 |
+
2002/08/15/big/img_1248
|
687 |
+
2002/07/31/big/img_416
|
688 |
+
2002/09/02/big/img_15259
|
689 |
+
2002/08/16/big/img_781
|
690 |
+
2002/08/24/big/img_754
|
691 |
+
2002/07/24/big/img_803
|
692 |
+
2002/08/20/big/img_609
|
693 |
+
2002/08/28/big/img_19571
|
694 |
+
2002/09/01/big/img_16140
|
695 |
+
2002/08/26/big/img_769
|
696 |
+
2002/07/20/big/img_588
|
697 |
+
2002/08/02/big/img_898
|
698 |
+
2002/07/21/big/img_466
|
699 |
+
2002/08/14/big/img_1046
|
700 |
+
2002/07/25/big/img_212
|
701 |
+
2002/08/26/big/img_353
|
702 |
+
2002/08/19/big/img_810
|
703 |
+
2002/08/31/big/img_17824
|
704 |
+
2002/08/12/big/img_631
|
705 |
+
2002/07/19/big/img_828
|
706 |
+
2002/07/24/big/img_130
|
707 |
+
2002/08/25/big/img_580
|
708 |
+
2002/07/31/big/img_699
|
709 |
+
2002/07/23/big/img_808
|
710 |
+
2002/07/31/big/img_377
|
711 |
+
2003/01/16/big/img_570
|
712 |
+
2002/09/01/big/img_16254
|
713 |
+
2002/07/21/big/img_471
|
714 |
+
2002/08/01/big/img_1548
|
715 |
+
2002/08/18/big/img_252
|
716 |
+
2002/08/19/big/img_576
|
717 |
+
2002/08/20/big/img_464
|
718 |
+
2002/07/27/big/img_735
|
719 |
+
2002/08/21/big/img_589
|
720 |
+
2003/01/15/big/img_1192
|
721 |
+
2002/08/09/big/img_302
|
722 |
+
2002/07/31/big/img_594
|
723 |
+
2002/08/23/big/img_19
|
724 |
+
2002/08/29/big/img_18819
|
725 |
+
2002/08/19/big/img_293
|
726 |
+
2002/07/30/big/img_331
|
727 |
+
2002/08/23/big/img_607
|
728 |
+
2002/07/30/big/img_363
|
729 |
+
2002/08/16/big/img_766
|
730 |
+
2003/01/13/big/img_481
|
731 |
+
2002/08/06/big/img_2515
|
732 |
+
2002/09/02/big/img_15913
|
733 |
+
2002/09/02/big/img_15827
|
734 |
+
2002/09/02/big/img_15053
|
735 |
+
2002/08/07/big/img_1576
|
736 |
+
2002/07/23/big/img_268
|
737 |
+
2002/08/21/big/img_152
|
738 |
+
2003/01/15/big/img_578
|
739 |
+
2002/07/21/big/img_589
|
740 |
+
2002/07/20/big/img_548
|
741 |
+
2002/08/27/big/img_19693
|
742 |
+
2002/08/31/big/img_17252
|
743 |
+
2002/07/31/big/img_138
|
744 |
+
2002/07/23/big/img_372
|
745 |
+
2002/08/16/big/img_695
|
746 |
+
2002/07/27/big/img_287
|
747 |
+
2002/08/15/big/img_315
|
748 |
+
2002/08/10/big/img_361
|
749 |
+
2002/07/29/big/img_899
|
750 |
+
2002/08/13/big/img_771
|
751 |
+
2002/08/21/big/img_92
|
752 |
+
2003/01/15/big/img_425
|
753 |
+
2003/01/16/big/img_450
|
754 |
+
2002/09/01/big/img_16942
|
755 |
+
2002/08/02/big/img_51
|
756 |
+
2002/09/02/big/img_15379
|
757 |
+
2002/08/24/big/img_147
|
758 |
+
2002/08/30/big/img_18122
|
759 |
+
2002/07/26/big/img_950
|
760 |
+
2002/08/07/big/img_1400
|
761 |
+
2002/08/17/big/img_468
|
762 |
+
2002/08/15/big/img_470
|
763 |
+
2002/07/30/big/img_318
|
764 |
+
2002/07/22/big/img_644
|
765 |
+
2002/08/27/big/img_19732
|
766 |
+
2002/07/23/big/img_601
|
767 |
+
2002/08/26/big/img_398
|
768 |
+
2002/08/21/big/img_428
|
769 |
+
2002/08/06/big/img_2119
|
770 |
+
2002/08/29/big/img_19103
|
771 |
+
2003/01/14/big/img_933
|
772 |
+
2002/08/11/big/img_674
|
773 |
+
2002/08/28/big/img_19420
|
774 |
+
2002/08/03/big/img_418
|
775 |
+
2002/08/17/big/img_312
|
776 |
+
2002/07/25/big/img_1044
|
777 |
+
2003/01/17/big/img_671
|
778 |
+
2002/08/30/big/img_18297
|
779 |
+
2002/07/25/big/img_755
|
780 |
+
2002/07/23/big/img_471
|
781 |
+
2002/08/21/big/img_39
|
782 |
+
2002/07/26/big/img_699
|
783 |
+
2003/01/14/big/img_33
|
784 |
+
2002/07/31/big/img_411
|
785 |
+
2002/08/16/big/img_645
|
786 |
+
2003/01/17/big/img_116
|
787 |
+
2002/09/02/big/img_15903
|
788 |
+
2002/08/20/big/img_120
|
789 |
+
2002/08/22/big/img_176
|
790 |
+
2002/07/29/big/img_1316
|
791 |
+
2002/08/27/big/img_19914
|
792 |
+
2002/07/22/big/img_719
|
793 |
+
2002/08/28/big/img_19239
|
794 |
+
2003/01/13/big/img_385
|
795 |
+
2002/08/08/big/img_525
|
796 |
+
2002/07/19/big/img_782
|
797 |
+
2002/08/13/big/img_843
|
798 |
+
2002/07/30/big/img_107
|
799 |
+
2002/08/11/big/img_752
|
800 |
+
2002/07/29/big/img_383
|
801 |
+
2002/08/26/big/img_249
|
802 |
+
2002/08/29/big/img_18860
|
803 |
+
2002/07/30/big/img_70
|
804 |
+
2002/07/26/big/img_194
|
805 |
+
2002/08/15/big/img_530
|
806 |
+
2002/08/08/big/img_816
|
807 |
+
2002/07/31/big/img_286
|
808 |
+
2003/01/13/big/img_294
|
809 |
+
2002/07/31/big/img_251
|
810 |
+
2002/07/24/big/img_13
|
811 |
+
2002/08/31/big/img_17938
|
812 |
+
2002/07/22/big/img_642
|
813 |
+
2003/01/14/big/img_728
|
814 |
+
2002/08/18/big/img_47
|
815 |
+
2002/08/22/big/img_306
|
816 |
+
2002/08/20/big/img_348
|
817 |
+
2002/08/15/big/img_764
|
818 |
+
2002/08/08/big/img_163
|
819 |
+
2002/07/23/big/img_531
|
820 |
+
2002/07/23/big/img_467
|
821 |
+
2003/01/16/big/img_743
|
822 |
+
2003/01/13/big/img_535
|
823 |
+
2002/08/02/big/img_523
|
824 |
+
2002/08/22/big/img_120
|
825 |
+
2002/08/11/big/img_496
|
826 |
+
2002/08/29/big/img_19075
|
827 |
+
2002/08/08/big/img_465
|
828 |
+
2002/08/09/big/img_790
|
829 |
+
2002/08/19/big/img_588
|
830 |
+
2002/08/23/big/img_407
|
831 |
+
2003/01/17/big/img_435
|
832 |
+
2002/08/24/big/img_398
|
833 |
+
2002/08/27/big/img_19899
|
834 |
+
2003/01/15/big/img_335
|
835 |
+
2002/08/13/big/img_493
|
836 |
+
2002/09/02/big/img_15460
|
837 |
+
2002/07/31/big/img_470
|
838 |
+
2002/08/05/big/img_3550
|
839 |
+
2002/07/28/big/img_123
|
840 |
+
2002/08/01/big/img_1498
|
841 |
+
2002/08/04/big/img_504
|
842 |
+
2003/01/17/big/img_427
|
843 |
+
2002/08/27/big/img_19708
|
844 |
+
2002/07/27/big/img_861
|
845 |
+
2002/07/25/big/img_685
|
846 |
+
2002/07/31/big/img_207
|
847 |
+
2003/01/14/big/img_745
|
848 |
+
2002/08/31/big/img_17756
|
849 |
+
2002/08/24/big/img_288
|
850 |
+
2002/08/18/big/img_181
|
851 |
+
2002/08/10/big/img_520
|
852 |
+
2002/08/25/big/img_705
|
853 |
+
2002/08/23/big/img_226
|
854 |
+
2002/08/04/big/img_727
|
855 |
+
2002/07/24/big/img_625
|
856 |
+
2002/08/28/big/img_19157
|
857 |
+
2002/08/23/big/img_586
|
858 |
+
2002/07/31/big/img_232
|
859 |
+
2003/01/13/big/img_240
|
860 |
+
2003/01/14/big/img_321
|
861 |
+
2003/01/15/big/img_533
|
862 |
+
2002/07/23/big/img_480
|
863 |
+
2002/07/24/big/img_371
|
864 |
+
2002/08/21/big/img_702
|
865 |
+
2002/08/31/big/img_17075
|
866 |
+
2002/09/02/big/img_15278
|
867 |
+
2002/07/29/big/img_246
|
868 |
+
2003/01/15/big/img_829
|
869 |
+
2003/01/15/big/img_1213
|
870 |
+
2003/01/16/big/img_441
|
871 |
+
2002/08/14/big/img_921
|
872 |
+
2002/07/23/big/img_425
|
873 |
+
2002/08/15/big/img_296
|
874 |
+
2002/07/19/big/img_135
|
875 |
+
2002/07/26/big/img_402
|
876 |
+
2003/01/17/big/img_88
|
877 |
+
2002/08/20/big/img_872
|
878 |
+
2002/08/13/big/img_1110
|
879 |
+
2003/01/16/big/img_1040
|
880 |
+
2002/07/23/big/img_9
|
881 |
+
2002/08/13/big/img_700
|
882 |
+
2002/08/16/big/img_371
|
883 |
+
2002/08/27/big/img_19966
|
884 |
+
2003/01/17/big/img_391
|
885 |
+
2002/08/18/big/img_426
|
886 |
+
2002/08/01/big/img_1618
|
887 |
+
2002/07/21/big/img_754
|
888 |
+
2003/01/14/big/img_1101
|
889 |
+
2003/01/16/big/img_1022
|
890 |
+
2002/07/22/big/img_275
|
891 |
+
2002/08/24/big/img_86
|
892 |
+
2002/08/17/big/img_582
|
893 |
+
2003/01/15/big/img_765
|
894 |
+
2003/01/17/big/img_449
|
895 |
+
2002/07/28/big/img_265
|
896 |
+
2003/01/13/big/img_552
|
897 |
+
2002/07/28/big/img_115
|
898 |
+
2003/01/16/big/img_56
|
899 |
+
2002/08/02/big/img_1232
|
900 |
+
2003/01/17/big/img_925
|
901 |
+
2002/07/22/big/img_445
|
902 |
+
2002/07/25/big/img_957
|
903 |
+
2002/07/20/big/img_589
|
904 |
+
2002/08/31/big/img_17107
|
905 |
+
2002/07/29/big/img_483
|
906 |
+
2002/08/14/big/img_1063
|
907 |
+
2002/08/07/big/img_1545
|
908 |
+
2002/08/14/big/img_680
|
909 |
+
2002/09/01/big/img_16694
|
910 |
+
2002/08/14/big/img_257
|
911 |
+
2002/08/11/big/img_726
|
912 |
+
2002/07/26/big/img_681
|
913 |
+
2002/07/25/big/img_481
|
914 |
+
2003/01/14/big/img_737
|
915 |
+
2002/08/28/big/img_19480
|
916 |
+
2003/01/16/big/img_362
|
917 |
+
2002/08/27/big/img_19865
|
918 |
+
2003/01/01/big/img_547
|
919 |
+
2002/09/02/big/img_15074
|
920 |
+
2002/08/01/big/img_1453
|
921 |
+
2002/08/22/big/img_594
|
922 |
+
2002/08/28/big/img_19263
|
923 |
+
2002/08/13/big/img_478
|
924 |
+
2002/07/29/big/img_1358
|
925 |
+
2003/01/14/big/img_1022
|
926 |
+
2002/08/16/big/img_450
|
927 |
+
2002/08/02/big/img_159
|
928 |
+
2002/07/26/big/img_781
|
929 |
+
2003/01/13/big/img_601
|
930 |
+
2002/08/20/big/img_407
|
931 |
+
2002/08/15/big/img_468
|
932 |
+
2002/08/31/big/img_17902
|
933 |
+
2002/08/16/big/img_81
|
934 |
+
2002/07/25/big/img_987
|
935 |
+
2002/07/25/big/img_500
|
936 |
+
2002/08/02/big/img_31
|
937 |
+
2002/08/18/big/img_538
|
938 |
+
2002/08/08/big/img_54
|
939 |
+
2002/07/23/big/img_686
|
940 |
+
2002/07/24/big/img_836
|
941 |
+
2003/01/17/big/img_734
|
942 |
+
2002/08/16/big/img_1055
|
943 |
+
2003/01/16/big/img_521
|
944 |
+
2002/07/25/big/img_612
|
945 |
+
2002/08/22/big/img_778
|
946 |
+
2002/08/03/big/img_251
|
947 |
+
2002/08/12/big/img_436
|
948 |
+
2002/08/23/big/img_705
|
949 |
+
2002/07/28/big/img_243
|
950 |
+
2002/07/25/big/img_1029
|
951 |
+
2002/08/20/big/img_287
|
952 |
+
2002/08/29/big/img_18739
|
953 |
+
2002/08/05/big/img_3272
|
954 |
+
2002/07/27/big/img_214
|
955 |
+
2003/01/14/big/img_5
|
956 |
+
2002/08/01/big/img_1380
|
957 |
+
2002/08/29/big/img_19097
|
958 |
+
2002/07/30/big/img_486
|
959 |
+
2002/08/29/big/img_18707
|
960 |
+
2002/08/10/big/img_559
|
961 |
+
2002/08/15/big/img_365
|
962 |
+
2002/08/09/big/img_525
|
963 |
+
2002/08/10/big/img_689
|
964 |
+
2002/07/25/big/img_502
|
965 |
+
2002/08/03/big/img_667
|
966 |
+
2002/08/10/big/img_855
|
967 |
+
2002/08/10/big/img_706
|
968 |
+
2002/08/18/big/img_603
|
969 |
+
2003/01/16/big/img_1055
|
970 |
+
2002/08/31/big/img_17890
|
971 |
+
2002/08/15/big/img_761
|
972 |
+
2003/01/15/big/img_489
|
973 |
+
2002/08/26/big/img_351
|
974 |
+
2002/08/01/big/img_1772
|
975 |
+
2002/08/31/big/img_17729
|
976 |
+
2002/07/25/big/img_609
|
977 |
+
2003/01/13/big/img_539
|
978 |
+
2002/07/27/big/img_686
|
979 |
+
2002/07/31/big/img_311
|
980 |
+
2002/08/22/big/img_799
|
981 |
+
2003/01/16/big/img_936
|
982 |
+
2002/08/31/big/img_17813
|
983 |
+
2002/08/04/big/img_862
|
984 |
+
2002/08/09/big/img_332
|
985 |
+
2002/07/20/big/img_148
|
986 |
+
2002/08/12/big/img_426
|
987 |
+
2002/07/24/big/img_69
|
988 |
+
2002/07/27/big/img_685
|
989 |
+
2002/08/02/big/img_480
|
990 |
+
2002/08/26/big/img_154
|
991 |
+
2002/07/24/big/img_598
|
992 |
+
2002/08/01/big/img_1881
|
993 |
+
2002/08/20/big/img_667
|
994 |
+
2003/01/14/big/img_495
|
995 |
+
2002/07/21/big/img_744
|
996 |
+
2002/07/30/big/img_150
|
997 |
+
2002/07/23/big/img_924
|
998 |
+
2002/08/08/big/img_272
|
999 |
+
2002/07/23/big/img_310
|
1000 |
+
2002/07/25/big/img_1011
|
1001 |
+
2002/09/02/big/img_15725
|
1002 |
+
2002/07/19/big/img_814
|
1003 |
+
2002/08/20/big/img_936
|
1004 |
+
2002/07/25/big/img_85
|
1005 |
+
2002/08/24/big/img_662
|
1006 |
+
2002/08/09/big/img_495
|
1007 |
+
2003/01/15/big/img_196
|
1008 |
+
2002/08/16/big/img_707
|
1009 |
+
2002/08/28/big/img_19370
|
1010 |
+
2002/08/06/big/img_2366
|
1011 |
+
2002/08/06/big/img_3012
|
1012 |
+
2002/08/01/big/img_1452
|
1013 |
+
2002/07/31/big/img_742
|
1014 |
+
2002/07/27/big/img_914
|
1015 |
+
2003/01/13/big/img_290
|
1016 |
+
2002/07/31/big/img_288
|
1017 |
+
2002/08/02/big/img_171
|
1018 |
+
2002/08/22/big/img_191
|
1019 |
+
2002/07/27/big/img_1066
|
1020 |
+
2002/08/12/big/img_383
|
1021 |
+
2003/01/17/big/img_1018
|
1022 |
+
2002/08/01/big/img_1785
|
1023 |
+
2002/08/11/big/img_390
|
1024 |
+
2002/08/27/big/img_20037
|
1025 |
+
2002/08/12/big/img_38
|
1026 |
+
2003/01/15/big/img_103
|
1027 |
+
2002/08/26/big/img_31
|
1028 |
+
2002/08/18/big/img_660
|
1029 |
+
2002/07/22/big/img_694
|
1030 |
+
2002/08/15/big/img_24
|
1031 |
+
2002/07/27/big/img_1077
|
1032 |
+
2002/08/01/big/img_1943
|
1033 |
+
2002/07/22/big/img_292
|
1034 |
+
2002/09/01/big/img_16857
|
1035 |
+
2002/07/22/big/img_892
|
1036 |
+
2003/01/14/big/img_46
|
1037 |
+
2002/08/09/big/img_469
|
1038 |
+
2002/08/09/big/img_414
|
1039 |
+
2003/01/16/big/img_40
|
1040 |
+
2002/08/28/big/img_19231
|
1041 |
+
2002/07/27/big/img_978
|
1042 |
+
2002/07/23/big/img_475
|
1043 |
+
2002/07/25/big/img_92
|
1044 |
+
2002/08/09/big/img_799
|
1045 |
+
2002/07/25/big/img_491
|
1046 |
+
2002/08/03/big/img_654
|
1047 |
+
2003/01/15/big/img_687
|
1048 |
+
2002/08/11/big/img_478
|
1049 |
+
2002/08/07/big/img_1664
|
1050 |
+
2002/08/20/big/img_362
|
1051 |
+
2002/08/01/big/img_1298
|
1052 |
+
2003/01/13/big/img_500
|
1053 |
+
2002/08/06/big/img_2896
|
1054 |
+
2002/08/30/big/img_18529
|
1055 |
+
2002/08/16/big/img_1020
|
1056 |
+
2002/07/29/big/img_892
|
1057 |
+
2002/08/29/big/img_18726
|
1058 |
+
2002/07/21/big/img_453
|
1059 |
+
2002/08/17/big/img_437
|
1060 |
+
2002/07/19/big/img_665
|
1061 |
+
2002/07/22/big/img_440
|
1062 |
+
2002/07/19/big/img_582
|
1063 |
+
2002/07/21/big/img_233
|
1064 |
+
2003/01/01/big/img_82
|
1065 |
+
2002/07/25/big/img_341
|
1066 |
+
2002/07/29/big/img_864
|
1067 |
+
2002/08/02/big/img_276
|
1068 |
+
2002/08/29/big/img_18654
|
1069 |
+
2002/07/27/big/img_1024
|
1070 |
+
2002/08/19/big/img_373
|
1071 |
+
2003/01/15/big/img_241
|
1072 |
+
2002/07/25/big/img_84
|
1073 |
+
2002/08/13/big/img_834
|
1074 |
+
2002/08/10/big/img_511
|
1075 |
+
2002/08/01/big/img_1627
|
1076 |
+
2002/08/08/big/img_607
|
1077 |
+
2002/08/06/big/img_2083
|
1078 |
+
2002/08/01/big/img_1486
|
1079 |
+
2002/08/08/big/img_700
|
1080 |
+
2002/08/01/big/img_1954
|
1081 |
+
2002/08/21/big/img_54
|
1082 |
+
2002/07/30/big/img_847
|
1083 |
+
2002/08/28/big/img_19169
|
1084 |
+
2002/07/21/big/img_549
|
1085 |
+
2002/08/03/big/img_693
|
1086 |
+
2002/07/31/big/img_1002
|
1087 |
+
2003/01/14/big/img_1035
|
1088 |
+
2003/01/16/big/img_622
|
1089 |
+
2002/07/30/big/img_1201
|
1090 |
+
2002/08/10/big/img_444
|
1091 |
+
2002/07/31/big/img_374
|
1092 |
+
2002/08/21/big/img_301
|
1093 |
+
2002/08/13/big/img_1095
|
1094 |
+
2003/01/13/big/img_288
|
1095 |
+
2002/07/25/big/img_232
|
1096 |
+
2003/01/13/big/img_967
|
1097 |
+
2002/08/26/big/img_360
|
1098 |
+
2002/08/05/big/img_67
|
1099 |
+
2002/08/29/big/img_18969
|
1100 |
+
2002/07/28/big/img_16
|
1101 |
+
2002/08/16/big/img_515
|
1102 |
+
2002/07/20/big/img_708
|
1103 |
+
2002/08/18/big/img_178
|
1104 |
+
2003/01/15/big/img_509
|
1105 |
+
2002/07/25/big/img_430
|
1106 |
+
2002/08/21/big/img_738
|
1107 |
+
2002/08/16/big/img_886
|
1108 |
+
2002/09/02/big/img_15605
|
1109 |
+
2002/09/01/big/img_16242
|
1110 |
+
2002/08/24/big/img_711
|
1111 |
+
2002/07/25/big/img_90
|
1112 |
+
2002/08/09/big/img_491
|
1113 |
+
2002/07/30/big/img_534
|
1114 |
+
2003/01/13/big/img_474
|
1115 |
+
2002/08/25/big/img_510
|
1116 |
+
2002/08/15/big/img_555
|
1117 |
+
2002/08/02/big/img_775
|
1118 |
+
2002/07/23/big/img_975
|
1119 |
+
2002/08/19/big/img_229
|
1120 |
+
2003/01/17/big/img_860
|
1121 |
+
2003/01/02/big/img_10
|
1122 |
+
2002/07/23/big/img_542
|
1123 |
+
2002/08/06/big/img_2535
|
1124 |
+
2002/07/22/big/img_37
|
1125 |
+
2002/08/06/big/img_2342
|
1126 |
+
2002/08/25/big/img_515
|
1127 |
+
2002/08/25/big/img_336
|
1128 |
+
2002/08/18/big/img_837
|
1129 |
+
2002/08/21/big/img_616
|
1130 |
+
2003/01/17/big/img_24
|
1131 |
+
2002/07/26/big/img_936
|
1132 |
+
2002/08/14/big/img_896
|
1133 |
+
2002/07/29/big/img_465
|
1134 |
+
2002/07/31/big/img_543
|
1135 |
+
2002/08/01/big/img_1411
|
1136 |
+
2002/08/02/big/img_423
|
1137 |
+
2002/08/21/big/img_44
|
1138 |
+
2002/07/31/big/img_11
|
1139 |
+
2003/01/15/big/img_628
|
1140 |
+
2003/01/15/big/img_605
|
1141 |
+
2002/07/30/big/img_571
|
1142 |
+
2002/07/23/big/img_428
|
1143 |
+
2002/08/15/big/img_942
|
1144 |
+
2002/07/26/big/img_531
|
1145 |
+
2003/01/16/big/img_59
|
1146 |
+
2002/08/02/big/img_410
|
1147 |
+
2002/07/31/big/img_230
|
1148 |
+
2002/08/19/big/img_806
|
1149 |
+
2003/01/14/big/img_462
|
1150 |
+
2002/08/16/big/img_370
|
1151 |
+
2002/08/13/big/img_380
|
1152 |
+
2002/08/16/big/img_932
|
1153 |
+
2002/07/19/big/img_393
|
1154 |
+
2002/08/20/big/img_764
|
1155 |
+
2002/08/15/big/img_616
|
1156 |
+
2002/07/26/big/img_267
|
1157 |
+
2002/07/27/big/img_1069
|
1158 |
+
2002/08/14/big/img_1041
|
1159 |
+
2003/01/13/big/img_594
|
1160 |
+
2002/09/01/big/img_16845
|
1161 |
+
2002/08/09/big/img_229
|
1162 |
+
2003/01/16/big/img_639
|
1163 |
+
2002/08/19/big/img_398
|
1164 |
+
2002/08/18/big/img_978
|
1165 |
+
2002/08/24/big/img_296
|
1166 |
+
2002/07/29/big/img_415
|
1167 |
+
2002/07/30/big/img_923
|
1168 |
+
2002/08/18/big/img_575
|
1169 |
+
2002/08/22/big/img_182
|
1170 |
+
2002/07/25/big/img_806
|
1171 |
+
2002/07/22/big/img_49
|
1172 |
+
2002/07/29/big/img_989
|
1173 |
+
2003/01/17/big/img_789
|
1174 |
+
2003/01/15/big/img_503
|
1175 |
+
2002/09/01/big/img_16062
|
1176 |
+
2003/01/17/big/img_794
|
1177 |
+
2002/08/15/big/img_564
|
1178 |
+
2003/01/15/big/img_222
|
1179 |
+
2002/08/01/big/img_1656
|
1180 |
+
2003/01/13/big/img_432
|
1181 |
+
2002/07/19/big/img_426
|
1182 |
+
2002/08/17/big/img_244
|
1183 |
+
2002/08/13/big/img_805
|
1184 |
+
2002/09/02/big/img_15067
|
1185 |
+
2002/08/11/big/img_58
|
1186 |
+
2002/08/22/big/img_636
|
1187 |
+
2002/07/22/big/img_416
|
1188 |
+
2002/08/13/big/img_836
|
1189 |
+
2002/08/26/big/img_363
|
1190 |
+
2002/07/30/big/img_917
|
1191 |
+
2003/01/14/big/img_206
|
1192 |
+
2002/08/12/big/img_311
|
1193 |
+
2002/08/31/big/img_17623
|
1194 |
+
2002/07/29/big/img_661
|
1195 |
+
2003/01/13/big/img_417
|
1196 |
+
2002/08/02/big/img_463
|
1197 |
+
2002/08/02/big/img_669
|
1198 |
+
2002/08/26/big/img_670
|
1199 |
+
2002/08/02/big/img_375
|
1200 |
+
2002/07/19/big/img_209
|
1201 |
+
2002/08/08/big/img_115
|
1202 |
+
2002/08/21/big/img_399
|
1203 |
+
2002/08/20/big/img_911
|
1204 |
+
2002/08/07/big/img_1212
|
1205 |
+
2002/08/20/big/img_578
|
1206 |
+
2002/08/22/big/img_554
|
1207 |
+
2002/08/21/big/img_484
|
1208 |
+
2002/07/25/big/img_450
|
1209 |
+
2002/08/03/big/img_542
|
1210 |
+
2002/08/15/big/img_561
|
1211 |
+
2002/07/23/big/img_360
|
1212 |
+
2002/08/30/big/img_18137
|
1213 |
+
2002/07/25/big/img_250
|
1214 |
+
2002/08/03/big/img_647
|
1215 |
+
2002/08/20/big/img_375
|
1216 |
+
2002/08/14/big/img_387
|
1217 |
+
2002/09/01/big/img_16990
|
1218 |
+
2002/08/28/big/img_19341
|
1219 |
+
2003/01/15/big/img_239
|
1220 |
+
2002/08/20/big/img_528
|
1221 |
+
2002/08/12/big/img_130
|
1222 |
+
2002/09/02/big/img_15108
|
1223 |
+
2003/01/15/big/img_372
|
1224 |
+
2002/08/16/big/img_678
|
1225 |
+
2002/08/04/big/img_623
|
1226 |
+
2002/07/23/big/img_477
|
1227 |
+
2002/08/28/big/img_19590
|
1228 |
+
2003/01/17/big/img_978
|
1229 |
+
2002/09/01/big/img_16692
|
1230 |
+
2002/07/20/big/img_109
|
1231 |
+
2002/08/06/big/img_2660
|
1232 |
+
2003/01/14/big/img_464
|
1233 |
+
2002/08/09/big/img_618
|
1234 |
+
2002/07/22/big/img_722
|
1235 |
+
2002/08/25/big/img_419
|
1236 |
+
2002/08/03/big/img_314
|
1237 |
+
2002/08/25/big/img_40
|
1238 |
+
2002/07/27/big/img_430
|
1239 |
+
2002/08/10/big/img_569
|
1240 |
+
2002/08/23/big/img_398
|
1241 |
+
2002/07/23/big/img_893
|
1242 |
+
2002/08/16/big/img_261
|
1243 |
+
2002/08/06/big/img_2668
|
1244 |
+
2002/07/22/big/img_835
|
1245 |
+
2002/09/02/big/img_15093
|
1246 |
+
2003/01/16/big/img_65
|
1247 |
+
2002/08/21/big/img_448
|
1248 |
+
2003/01/14/big/img_351
|
1249 |
+
2003/01/17/big/img_133
|
1250 |
+
2002/07/28/big/img_493
|
1251 |
+
2003/01/15/big/img_640
|
1252 |
+
2002/09/01/big/img_16880
|
1253 |
+
2002/08/15/big/img_350
|
1254 |
+
2002/08/20/big/img_624
|
1255 |
+
2002/08/25/big/img_604
|
1256 |
+
2002/08/06/big/img_2200
|
1257 |
+
2002/08/23/big/img_290
|
1258 |
+
2002/08/13/big/img_1152
|
1259 |
+
2003/01/14/big/img_251
|
1260 |
+
2002/08/02/big/img_538
|
1261 |
+
2002/08/22/big/img_613
|
1262 |
+
2003/01/13/big/img_351
|
1263 |
+
2002/08/18/big/img_368
|
1264 |
+
2002/07/23/big/img_392
|
1265 |
+
2002/07/25/big/img_198
|
1266 |
+
2002/07/25/big/img_418
|
1267 |
+
2002/08/26/big/img_614
|
1268 |
+
2002/07/23/big/img_405
|
1269 |
+
2003/01/14/big/img_445
|
1270 |
+
2002/07/25/big/img_326
|
1271 |
+
2002/08/10/big/img_734
|
1272 |
+
2003/01/14/big/img_530
|
1273 |
+
2002/08/08/big/img_561
|
1274 |
+
2002/08/29/big/img_18990
|
1275 |
+
2002/08/10/big/img_576
|
1276 |
+
2002/07/29/big/img_1494
|
1277 |
+
2002/07/19/big/img_198
|
1278 |
+
2002/08/10/big/img_562
|
1279 |
+
2002/07/22/big/img_901
|
1280 |
+
2003/01/14/big/img_37
|
1281 |
+
2002/09/02/big/img_15629
|
1282 |
+
2003/01/14/big/img_58
|
1283 |
+
2002/08/01/big/img_1364
|
1284 |
+
2002/07/27/big/img_636
|
1285 |
+
2003/01/13/big/img_241
|
1286 |
+
2002/09/01/big/img_16988
|
1287 |
+
2003/01/13/big/img_560
|
1288 |
+
2002/08/09/big/img_533
|
1289 |
+
2002/07/31/big/img_249
|
1290 |
+
2003/01/17/big/img_1007
|
1291 |
+
2002/07/21/big/img_64
|
1292 |
+
2003/01/13/big/img_537
|
1293 |
+
2003/01/15/big/img_606
|
1294 |
+
2002/08/18/big/img_651
|
1295 |
+
2002/08/24/big/img_405
|
1296 |
+
2002/07/26/big/img_837
|
1297 |
+
2002/08/09/big/img_562
|
1298 |
+
2002/08/01/big/img_1983
|
1299 |
+
2002/08/03/big/img_514
|
1300 |
+
2002/07/29/big/img_314
|
1301 |
+
2002/08/12/big/img_493
|
1302 |
+
2003/01/14/big/img_121
|
1303 |
+
2003/01/14/big/img_479
|
1304 |
+
2002/08/04/big/img_410
|
1305 |
+
2002/07/22/big/img_607
|
1306 |
+
2003/01/17/big/img_417
|
1307 |
+
2002/07/20/big/img_547
|
1308 |
+
2002/08/13/big/img_396
|
1309 |
+
2002/08/31/big/img_17538
|
1310 |
+
2002/08/13/big/img_187
|
1311 |
+
2002/08/12/big/img_328
|
1312 |
+
2003/01/14/big/img_569
|
1313 |
+
2002/07/27/big/img_1081
|
1314 |
+
2002/08/14/big/img_504
|
1315 |
+
2002/08/23/big/img_785
|
1316 |
+
2002/07/26/big/img_339
|
1317 |
+
2002/08/07/big/img_1156
|
1318 |
+
2002/08/07/big/img_1456
|
1319 |
+
2002/08/23/big/img_378
|
1320 |
+
2002/08/27/big/img_19719
|
1321 |
+
2002/07/31/big/img_39
|
1322 |
+
2002/07/31/big/img_883
|
1323 |
+
2003/01/14/big/img_676
|
1324 |
+
2002/07/29/big/img_214
|
1325 |
+
2002/07/26/big/img_669
|
1326 |
+
2002/07/25/big/img_202
|
1327 |
+
2002/08/08/big/img_259
|
1328 |
+
2003/01/17/big/img_943
|
1329 |
+
2003/01/15/big/img_512
|
1330 |
+
2002/08/05/big/img_3295
|
1331 |
+
2002/08/27/big/img_19685
|
1332 |
+
2002/08/08/big/img_277
|
1333 |
+
2002/08/30/big/img_18154
|
1334 |
+
2002/07/22/big/img_663
|
1335 |
+
2002/08/29/big/img_18914
|
1336 |
+
2002/07/31/big/img_908
|
1337 |
+
2002/08/27/big/img_19926
|
1338 |
+
2003/01/13/big/img_791
|
1339 |
+
2003/01/15/big/img_827
|
1340 |
+
2002/08/18/big/img_878
|
1341 |
+
2002/08/14/big/img_670
|
1342 |
+
2002/07/20/big/img_182
|
1343 |
+
2002/08/15/big/img_291
|
1344 |
+
2002/08/06/big/img_2600
|
1345 |
+
2002/07/23/big/img_587
|
1346 |
+
2002/08/14/big/img_577
|
1347 |
+
2003/01/15/big/img_585
|
1348 |
+
2002/07/30/big/img_310
|
1349 |
+
2002/08/03/big/img_658
|
1350 |
+
2002/08/10/big/img_157
|
1351 |
+
2002/08/19/big/img_811
|
1352 |
+
2002/07/29/big/img_1318
|
1353 |
+
2002/08/04/big/img_104
|
1354 |
+
2002/07/30/big/img_332
|
1355 |
+
2002/07/24/big/img_789
|
1356 |
+
2002/07/29/big/img_516
|
1357 |
+
2002/07/23/big/img_843
|
1358 |
+
2002/08/01/big/img_1528
|
1359 |
+
2002/08/13/big/img_798
|
1360 |
+
2002/08/07/big/img_1729
|
1361 |
+
2002/08/28/big/img_19448
|
1362 |
+
2003/01/16/big/img_95
|
1363 |
+
2002/08/12/big/img_473
|
1364 |
+
2002/07/27/big/img_269
|
1365 |
+
2003/01/16/big/img_621
|
1366 |
+
2002/07/29/big/img_772
|
1367 |
+
2002/07/24/big/img_171
|
1368 |
+
2002/07/19/big/img_429
|
1369 |
+
2002/08/07/big/img_1933
|
1370 |
+
2002/08/27/big/img_19629
|
1371 |
+
2002/08/05/big/img_3688
|
1372 |
+
2002/08/07/big/img_1691
|
1373 |
+
2002/07/23/big/img_600
|
1374 |
+
2002/07/29/big/img_666
|
1375 |
+
2002/08/25/big/img_566
|
1376 |
+
2002/08/06/big/img_2659
|
1377 |
+
2002/08/29/big/img_18929
|
1378 |
+
2002/08/16/big/img_407
|
1379 |
+
2002/08/18/big/img_774
|
1380 |
+
2002/08/19/big/img_249
|
1381 |
+
2002/08/06/big/img_2427
|
1382 |
+
2002/08/29/big/img_18899
|
1383 |
+
2002/08/01/big/img_1818
|
1384 |
+
2002/07/31/big/img_108
|
1385 |
+
2002/07/29/big/img_500
|
1386 |
+
2002/08/11/big/img_115
|
1387 |
+
2002/07/19/big/img_521
|
1388 |
+
2002/08/02/big/img_1163
|
1389 |
+
2002/07/22/big/img_62
|
1390 |
+
2002/08/13/big/img_466
|
1391 |
+
2002/08/21/big/img_956
|
1392 |
+
2002/08/23/big/img_602
|
1393 |
+
2002/08/20/big/img_858
|
1394 |
+
2002/07/25/big/img_690
|
1395 |
+
2002/07/19/big/img_130
|
1396 |
+
2002/08/04/big/img_874
|
1397 |
+
2002/07/26/big/img_489
|
1398 |
+
2002/07/22/big/img_548
|
1399 |
+
2002/08/10/big/img_191
|
1400 |
+
2002/07/25/big/img_1051
|
1401 |
+
2002/08/18/big/img_473
|
1402 |
+
2002/08/12/big/img_755
|
1403 |
+
2002/08/18/big/img_413
|
1404 |
+
2002/08/08/big/img_1044
|
1405 |
+
2002/08/17/big/img_680
|
1406 |
+
2002/08/26/big/img_235
|
1407 |
+
2002/08/20/big/img_330
|
1408 |
+
2002/08/22/big/img_344
|
1409 |
+
2002/08/09/big/img_593
|
1410 |
+
2002/07/31/big/img_1006
|
1411 |
+
2002/08/14/big/img_337
|
1412 |
+
2002/08/16/big/img_728
|
1413 |
+
2002/07/24/big/img_834
|
1414 |
+
2002/08/04/big/img_552
|
1415 |
+
2002/09/02/big/img_15213
|
1416 |
+
2002/07/25/big/img_725
|
1417 |
+
2002/08/30/big/img_18290
|
1418 |
+
2003/01/01/big/img_475
|
1419 |
+
2002/07/27/big/img_1083
|
1420 |
+
2002/08/29/big/img_18955
|
1421 |
+
2002/08/31/big/img_17232
|
1422 |
+
2002/08/08/big/img_480
|
1423 |
+
2002/08/01/big/img_1311
|
1424 |
+
2002/07/30/big/img_745
|
1425 |
+
2002/08/03/big/img_649
|
1426 |
+
2002/08/12/big/img_193
|
1427 |
+
2002/07/29/big/img_228
|
1428 |
+
2002/07/25/big/img_836
|
1429 |
+
2002/08/20/big/img_400
|
1430 |
+
2002/07/30/big/img_507
|
1431 |
+
2002/09/02/big/img_15072
|
1432 |
+
2002/07/26/big/img_658
|
1433 |
+
2002/07/28/big/img_503
|
1434 |
+
2002/08/05/big/img_3814
|
1435 |
+
2002/08/24/big/img_745
|
1436 |
+
2003/01/13/big/img_817
|
1437 |
+
2002/08/08/big/img_579
|
1438 |
+
2002/07/22/big/img_251
|
1439 |
+
2003/01/13/big/img_689
|
1440 |
+
2002/07/25/big/img_407
|
1441 |
+
2002/08/13/big/img_1050
|
1442 |
+
2002/08/14/big/img_733
|
1443 |
+
2002/07/24/big/img_82
|
1444 |
+
2003/01/17/big/img_288
|
1445 |
+
2003/01/15/big/img_475
|
1446 |
+
2002/08/14/big/img_620
|
1447 |
+
2002/08/21/big/img_167
|
1448 |
+
2002/07/19/big/img_300
|
1449 |
+
2002/07/26/big/img_219
|
1450 |
+
2002/08/01/big/img_1468
|
1451 |
+
2002/07/23/big/img_260
|
1452 |
+
2002/08/09/big/img_555
|
1453 |
+
2002/07/19/big/img_160
|
1454 |
+
2002/08/02/big/img_1060
|
1455 |
+
2003/01/14/big/img_149
|
1456 |
+
2002/08/15/big/img_346
|
1457 |
+
2002/08/24/big/img_597
|
1458 |
+
2002/08/22/big/img_502
|
1459 |
+
2002/08/30/big/img_18228
|
1460 |
+
2002/07/21/big/img_766
|
1461 |
+
2003/01/15/big/img_841
|
1462 |
+
2002/07/24/big/img_516
|
1463 |
+
2002/08/02/big/img_265
|
1464 |
+
2002/08/15/big/img_1243
|
1465 |
+
2003/01/15/big/img_223
|
1466 |
+
2002/08/04/big/img_236
|
1467 |
+
2002/07/22/big/img_309
|
1468 |
+
2002/07/20/big/img_656
|
1469 |
+
2002/07/31/big/img_412
|
1470 |
+
2002/09/01/big/img_16462
|
1471 |
+
2003/01/16/big/img_431
|
1472 |
+
2002/07/22/big/img_793
|
1473 |
+
2002/08/15/big/img_877
|
1474 |
+
2002/07/26/big/img_282
|
1475 |
+
2002/07/25/big/img_529
|
1476 |
+
2002/08/24/big/img_613
|
1477 |
+
2003/01/17/big/img_700
|
1478 |
+
2002/08/06/big/img_2526
|
1479 |
+
2002/08/24/big/img_394
|
1480 |
+
2002/08/21/big/img_521
|
1481 |
+
2002/08/25/big/img_560
|
1482 |
+
2002/07/29/big/img_966
|
1483 |
+
2002/07/25/big/img_448
|
1484 |
+
2003/01/13/big/img_782
|
1485 |
+
2002/08/21/big/img_296
|
1486 |
+
2002/09/01/big/img_16755
|
1487 |
+
2002/08/05/big/img_3552
|
1488 |
+
2002/09/02/big/img_15823
|
1489 |
+
2003/01/14/big/img_193
|
1490 |
+
2002/07/21/big/img_159
|
1491 |
+
2002/08/02/big/img_564
|
1492 |
+
2002/08/16/big/img_300
|
1493 |
+
2002/07/19/big/img_269
|
1494 |
+
2002/08/13/big/img_676
|
1495 |
+
2002/07/28/big/img_57
|
1496 |
+
2002/08/05/big/img_3318
|
1497 |
+
2002/07/31/big/img_218
|
1498 |
+
2002/08/21/big/img_898
|
1499 |
+
2002/07/29/big/img_109
|
1500 |
+
2002/07/19/big/img_854
|
1501 |
+
2002/08/23/big/img_311
|
1502 |
+
2002/08/14/big/img_318
|
1503 |
+
2002/07/25/big/img_523
|
1504 |
+
2002/07/21/big/img_678
|
1505 |
+
2003/01/17/big/img_690
|
1506 |
+
2002/08/28/big/img_19503
|
1507 |
+
2002/08/18/big/img_251
|
1508 |
+
2002/08/22/big/img_672
|
1509 |
+
2002/08/20/big/img_663
|
1510 |
+
2002/08/02/big/img_148
|
1511 |
+
2002/09/02/big/img_15580
|
1512 |
+
2002/07/25/big/img_778
|
1513 |
+
2002/08/14/big/img_565
|
1514 |
+
2002/08/12/big/img_374
|
1515 |
+
2002/08/13/big/img_1018
|
1516 |
+
2002/08/20/big/img_474
|
1517 |
+
2002/08/25/big/img_33
|
1518 |
+
2002/08/02/big/img_1190
|
1519 |
+
2002/08/08/big/img_864
|
1520 |
+
2002/08/14/big/img_1071
|
1521 |
+
2002/08/30/big/img_18103
|
1522 |
+
2002/08/18/big/img_533
|
1523 |
+
2003/01/16/big/img_650
|
1524 |
+
2002/07/25/big/img_108
|
1525 |
+
2002/07/26/big/img_81
|
1526 |
+
2002/07/27/big/img_543
|
1527 |
+
2002/07/29/big/img_521
|
1528 |
+
2003/01/13/big/img_434
|
1529 |
+
2002/08/26/big/img_674
|
1530 |
+
2002/08/06/big/img_2932
|
1531 |
+
2002/08/07/big/img_1262
|
1532 |
+
2003/01/15/big/img_201
|
1533 |
+
2003/01/16/big/img_673
|
1534 |
+
2002/09/02/big/img_15988
|
1535 |
+
2002/07/29/big/img_1306
|
1536 |
+
2003/01/14/big/img_1072
|
1537 |
+
2002/08/30/big/img_18232
|
1538 |
+
2002/08/05/big/img_3711
|
1539 |
+
2002/07/23/big/img_775
|
1540 |
+
2002/08/01/big/img_16
|
1541 |
+
2003/01/16/big/img_630
|
1542 |
+
2002/08/22/big/img_695
|
1543 |
+
2002/08/14/big/img_51
|
1544 |
+
2002/08/14/big/img_782
|
1545 |
+
2002/08/24/big/img_742
|
1546 |
+
2003/01/14/big/img_512
|
1547 |
+
2003/01/15/big/img_1183
|
1548 |
+
2003/01/15/big/img_714
|
1549 |
+
2002/08/01/big/img_2078
|
1550 |
+
2002/07/31/big/img_682
|
1551 |
+
2002/09/02/big/img_15687
|
1552 |
+
2002/07/26/big/img_518
|
1553 |
+
2002/08/27/big/img_19676
|
1554 |
+
2002/09/02/big/img_15969
|
1555 |
+
2002/08/02/big/img_931
|
1556 |
+
2002/08/25/big/img_508
|
1557 |
+
2002/08/29/big/img_18616
|
1558 |
+
2002/07/22/big/img_839
|
1559 |
+
2002/07/28/big/img_313
|
1560 |
+
2003/01/14/big/img_155
|
1561 |
+
2002/08/02/big/img_1105
|
1562 |
+
2002/08/09/big/img_53
|
1563 |
+
2002/08/16/big/img_469
|
1564 |
+
2002/08/15/big/img_502
|
1565 |
+
2002/08/20/big/img_575
|
1566 |
+
2002/07/25/big/img_138
|
1567 |
+
2003/01/16/big/img_579
|
1568 |
+
2002/07/19/big/img_352
|
1569 |
+
2003/01/14/big/img_762
|
1570 |
+
2003/01/01/big/img_588
|
1571 |
+
2002/08/02/big/img_981
|
1572 |
+
2002/08/21/big/img_447
|
1573 |
+
2002/09/01/big/img_16151
|
1574 |
+
2003/01/14/big/img_769
|
1575 |
+
2002/08/23/big/img_461
|
1576 |
+
2002/08/17/big/img_240
|
1577 |
+
2002/09/02/big/img_15220
|
1578 |
+
2002/07/19/big/img_408
|
1579 |
+
2002/09/02/big/img_15496
|
1580 |
+
2002/07/29/big/img_758
|
1581 |
+
2002/08/28/big/img_19392
|
1582 |
+
2002/08/06/big/img_2723
|
1583 |
+
2002/08/31/big/img_17752
|
1584 |
+
2002/08/23/big/img_469
|
1585 |
+
2002/08/13/big/img_515
|
1586 |
+
2002/09/02/big/img_15551
|
1587 |
+
2002/08/03/big/img_462
|
1588 |
+
2002/07/24/big/img_613
|
1589 |
+
2002/07/22/big/img_61
|
1590 |
+
2002/08/08/big/img_171
|
1591 |
+
2002/08/21/big/img_177
|
1592 |
+
2003/01/14/big/img_105
|
1593 |
+
2002/08/02/big/img_1017
|
1594 |
+
2002/08/22/big/img_106
|
1595 |
+
2002/07/27/big/img_542
|
1596 |
+
2002/07/21/big/img_665
|
1597 |
+
2002/07/23/big/img_595
|
1598 |
+
2002/08/04/big/img_657
|
1599 |
+
2002/08/29/big/img_19002
|
1600 |
+
2003/01/15/big/img_550
|
1601 |
+
2002/08/14/big/img_662
|
1602 |
+
2002/07/20/big/img_425
|
1603 |
+
2002/08/30/big/img_18528
|
1604 |
+
2002/07/26/big/img_611
|
1605 |
+
2002/07/22/big/img_849
|
1606 |
+
2002/08/07/big/img_1655
|
1607 |
+
2002/08/21/big/img_638
|
1608 |
+
2003/01/17/big/img_732
|
1609 |
+
2003/01/01/big/img_496
|
1610 |
+
2002/08/18/big/img_713
|
1611 |
+
2002/08/08/big/img_109
|
1612 |
+
2002/07/27/big/img_1008
|
1613 |
+
2002/07/20/big/img_559
|
1614 |
+
2002/08/16/big/img_699
|
1615 |
+
2002/08/31/big/img_17702
|
1616 |
+
2002/07/31/big/img_1013
|
1617 |
+
2002/08/01/big/img_2027
|
1618 |
+
2002/08/02/big/img_1001
|
1619 |
+
2002/08/03/big/img_210
|
1620 |
+
2002/08/01/big/img_2087
|
1621 |
+
2003/01/14/big/img_199
|
1622 |
+
2002/07/29/big/img_48
|
1623 |
+
2002/07/19/big/img_727
|
1624 |
+
2002/08/09/big/img_249
|
1625 |
+
2002/08/04/big/img_632
|
1626 |
+
2002/08/22/big/img_620
|
1627 |
+
2003/01/01/big/img_457
|
1628 |
+
2002/08/05/big/img_3223
|
1629 |
+
2002/07/27/big/img_240
|
1630 |
+
2002/07/25/big/img_797
|
1631 |
+
2002/08/13/big/img_430
|
1632 |
+
2002/07/25/big/img_615
|
1633 |
+
2002/08/12/big/img_28
|
1634 |
+
2002/07/30/big/img_220
|
1635 |
+
2002/07/24/big/img_89
|
1636 |
+
2002/08/21/big/img_357
|
1637 |
+
2002/08/09/big/img_590
|
1638 |
+
2003/01/13/big/img_525
|
1639 |
+
2002/08/17/big/img_818
|
1640 |
+
2003/01/02/big/img_7
|
1641 |
+
2002/07/26/big/img_636
|
1642 |
+
2003/01/13/big/img_1122
|
1643 |
+
2002/07/23/big/img_810
|
1644 |
+
2002/08/20/big/img_888
|
1645 |
+
2002/07/27/big/img_3
|
1646 |
+
2002/08/15/big/img_451
|
1647 |
+
2002/09/02/big/img_15787
|
1648 |
+
2002/07/31/big/img_281
|
1649 |
+
2002/08/05/big/img_3274
|
1650 |
+
2002/08/07/big/img_1254
|
1651 |
+
2002/07/31/big/img_27
|
1652 |
+
2002/08/01/big/img_1366
|
1653 |
+
2002/07/30/big/img_182
|
1654 |
+
2002/08/27/big/img_19690
|
1655 |
+
2002/07/29/big/img_68
|
1656 |
+
2002/08/23/big/img_754
|
1657 |
+
2002/07/30/big/img_540
|
1658 |
+
2002/08/27/big/img_20063
|
1659 |
+
2002/08/14/big/img_471
|
1660 |
+
2002/08/02/big/img_615
|
1661 |
+
2002/07/30/big/img_186
|
1662 |
+
2002/08/25/big/img_150
|
1663 |
+
2002/07/27/big/img_626
|
1664 |
+
2002/07/20/big/img_225
|
1665 |
+
2003/01/15/big/img_1252
|
1666 |
+
2002/07/19/big/img_367
|
1667 |
+
2003/01/15/big/img_582
|
1668 |
+
2002/08/09/big/img_572
|
1669 |
+
2002/08/08/big/img_428
|
1670 |
+
2003/01/15/big/img_639
|
1671 |
+
2002/08/28/big/img_19245
|
1672 |
+
2002/07/24/big/img_321
|
1673 |
+
2002/08/02/big/img_662
|
1674 |
+
2002/08/08/big/img_1033
|
1675 |
+
2003/01/17/big/img_867
|
1676 |
+
2002/07/22/big/img_652
|
1677 |
+
2003/01/14/big/img_224
|
1678 |
+
2002/08/18/big/img_49
|
1679 |
+
2002/07/26/big/img_46
|
1680 |
+
2002/08/31/big/img_18021
|
1681 |
+
2002/07/25/big/img_151
|
1682 |
+
2002/08/23/big/img_540
|
1683 |
+
2002/08/25/big/img_693
|
1684 |
+
2002/07/23/big/img_340
|
1685 |
+
2002/07/28/big/img_117
|
1686 |
+
2002/09/02/big/img_15768
|
1687 |
+
2002/08/26/big/img_562
|
1688 |
+
2002/07/24/big/img_480
|
1689 |
+
2003/01/15/big/img_341
|
1690 |
+
2002/08/10/big/img_783
|
1691 |
+
2002/08/20/big/img_132
|
1692 |
+
2003/01/14/big/img_370
|
1693 |
+
2002/07/20/big/img_720
|
1694 |
+
2002/08/03/big/img_144
|
1695 |
+
2002/08/20/big/img_538
|
1696 |
+
2002/08/01/big/img_1745
|
1697 |
+
2002/08/11/big/img_683
|
1698 |
+
2002/08/03/big/img_328
|
1699 |
+
2002/08/10/big/img_793
|
1700 |
+
2002/08/14/big/img_689
|
1701 |
+
2002/08/02/big/img_162
|
1702 |
+
2003/01/17/big/img_411
|
1703 |
+
2002/07/31/big/img_361
|
1704 |
+
2002/08/15/big/img_289
|
1705 |
+
2002/08/08/big/img_254
|
1706 |
+
2002/08/15/big/img_996
|
1707 |
+
2002/08/20/big/img_785
|
1708 |
+
2002/07/24/big/img_511
|
1709 |
+
2002/08/06/big/img_2614
|
1710 |
+
2002/08/29/big/img_18733
|
1711 |
+
2002/08/17/big/img_78
|
1712 |
+
2002/07/30/big/img_378
|
1713 |
+
2002/08/31/big/img_17947
|
1714 |
+
2002/08/26/big/img_88
|
1715 |
+
2002/07/30/big/img_558
|
1716 |
+
2002/08/02/big/img_67
|
1717 |
+
2003/01/14/big/img_325
|
1718 |
+
2002/07/29/big/img_1357
|
1719 |
+
2002/07/19/big/img_391
|
1720 |
+
2002/07/30/big/img_307
|
1721 |
+
2003/01/13/big/img_219
|
1722 |
+
2002/07/24/big/img_807
|
1723 |
+
2002/08/23/big/img_543
|
1724 |
+
2002/08/29/big/img_18620
|
1725 |
+
2002/07/22/big/img_769
|
1726 |
+
2002/08/26/big/img_503
|
1727 |
+
2002/07/30/big/img_78
|
1728 |
+
2002/08/14/big/img_1036
|
1729 |
+
2002/08/09/big/img_58
|
1730 |
+
2002/07/24/big/img_616
|
1731 |
+
2002/08/02/big/img_464
|
1732 |
+
2002/07/26/big/img_576
|
1733 |
+
2002/07/22/big/img_273
|
1734 |
+
2003/01/16/big/img_470
|
1735 |
+
2002/07/29/big/img_329
|
1736 |
+
2002/07/30/big/img_1086
|
1737 |
+
2002/07/31/big/img_353
|
1738 |
+
2002/09/02/big/img_15275
|
1739 |
+
2003/01/17/big/img_555
|
1740 |
+
2002/08/26/big/img_212
|
1741 |
+
2002/08/01/big/img_1692
|
1742 |
+
2003/01/15/big/img_600
|
1743 |
+
2002/07/29/big/img_825
|
1744 |
+
2002/08/08/big/img_68
|
1745 |
+
2002/08/10/big/img_719
|
1746 |
+
2002/07/31/big/img_636
|
1747 |
+
2002/07/29/big/img_325
|
1748 |
+
2002/07/21/big/img_515
|
1749 |
+
2002/07/22/big/img_705
|
1750 |
+
2003/01/13/big/img_818
|
1751 |
+
2002/08/09/big/img_486
|
1752 |
+
2002/08/22/big/img_141
|
1753 |
+
2002/07/22/big/img_303
|
1754 |
+
2002/08/09/big/img_393
|
1755 |
+
2002/07/29/big/img_963
|
1756 |
+
2002/08/02/big/img_1215
|
1757 |
+
2002/08/19/big/img_674
|
1758 |
+
2002/08/12/big/img_690
|
1759 |
+
2002/08/21/big/img_637
|
1760 |
+
2002/08/21/big/img_841
|
1761 |
+
2002/08/24/big/img_71
|
1762 |
+
2002/07/25/big/img_596
|
1763 |
+
2002/07/24/big/img_864
|
1764 |
+
2002/08/18/big/img_293
|
1765 |
+
2003/01/14/big/img_657
|
1766 |
+
2002/08/15/big/img_411
|
1767 |
+
2002/08/16/big/img_348
|
1768 |
+
2002/08/05/big/img_3157
|
1769 |
+
2002/07/20/big/img_663
|
1770 |
+
2003/01/13/big/img_654
|
1771 |
+
2003/01/16/big/img_433
|
1772 |
+
2002/08/30/big/img_18200
|
1773 |
+
2002/08/12/big/img_226
|
1774 |
+
2003/01/16/big/img_491
|
1775 |
+
2002/08/08/big/img_666
|
1776 |
+
2002/07/19/big/img_576
|
1777 |
+
2003/01/15/big/img_776
|
1778 |
+
2003/01/16/big/img_899
|
1779 |
+
2002/07/19/big/img_397
|
1780 |
+
2002/08/14/big/img_44
|
1781 |
+
2003/01/15/big/img_762
|
1782 |
+
2002/08/02/big/img_982
|
1783 |
+
2002/09/02/big/img_15234
|
1784 |
+
2002/08/17/big/img_556
|
1785 |
+
2002/08/21/big/img_410
|
1786 |
+
2002/08/21/big/img_386
|
1787 |
+
2002/07/19/big/img_690
|
1788 |
+
2002/08/05/big/img_3052
|
1789 |
+
2002/08/14/big/img_219
|
1790 |
+
2002/08/16/big/img_273
|
1791 |
+
2003/01/15/big/img_752
|
1792 |
+
2002/08/08/big/img_184
|
1793 |
+
2002/07/31/big/img_743
|
1794 |
+
2002/08/23/big/img_338
|
1795 |
+
2003/01/14/big/img_1055
|
1796 |
+
2002/08/05/big/img_3405
|
1797 |
+
2003/01/15/big/img_17
|
1798 |
+
2002/08/03/big/img_141
|
1799 |
+
2002/08/14/big/img_549
|
1800 |
+
2002/07/27/big/img_1034
|
1801 |
+
2002/07/31/big/img_932
|
1802 |
+
2002/08/30/big/img_18487
|
1803 |
+
2002/09/02/big/img_15814
|
1804 |
+
2002/08/01/big/img_2086
|
1805 |
+
2002/09/01/big/img_16535
|
1806 |
+
2002/07/22/big/img_500
|
1807 |
+
2003/01/13/big/img_400
|
1808 |
+
2002/08/25/big/img_607
|
1809 |
+
2002/08/30/big/img_18384
|
1810 |
+
2003/01/14/big/img_951
|
1811 |
+
2002/08/13/big/img_1150
|
1812 |
+
2002/08/08/big/img_1022
|
1813 |
+
2002/08/10/big/img_428
|
1814 |
+
2002/08/28/big/img_19242
|
1815 |
+
2002/08/05/big/img_3098
|
1816 |
+
2002/07/23/big/img_400
|
1817 |
+
2002/08/26/big/img_365
|
1818 |
+
2002/07/20/big/img_318
|
1819 |
+
2002/08/13/big/img_740
|
1820 |
+
2003/01/16/big/img_37
|
1821 |
+
2002/08/26/big/img_274
|
1822 |
+
2002/08/02/big/img_205
|
1823 |
+
2002/08/21/big/img_695
|
1824 |
+
2002/08/06/big/img_2289
|
1825 |
+
2002/08/20/big/img_794
|
1826 |
+
2002/08/18/big/img_438
|
1827 |
+
2002/08/07/big/img_1380
|
1828 |
+
2002/08/02/big/img_737
|
1829 |
+
2002/08/07/big/img_1651
|
1830 |
+
2002/08/15/big/img_1238
|
1831 |
+
2002/08/01/big/img_1681
|
1832 |
+
2002/08/06/big/img_3017
|
1833 |
+
2002/07/23/big/img_706
|
1834 |
+
2002/07/31/big/img_392
|
1835 |
+
2002/08/09/big/img_539
|
1836 |
+
2002/07/29/big/img_835
|
1837 |
+
2002/08/26/big/img_723
|
1838 |
+
2002/08/28/big/img_19235
|
1839 |
+
2003/01/16/big/img_353
|
1840 |
+
2002/08/10/big/img_150
|
1841 |
+
2002/08/29/big/img_19025
|
1842 |
+
2002/08/21/big/img_310
|
1843 |
+
2002/08/10/big/img_823
|
1844 |
+
2002/07/26/big/img_981
|
1845 |
+
2002/08/11/big/img_288
|
1846 |
+
2002/08/19/big/img_534
|
1847 |
+
2002/08/21/big/img_300
|
1848 |
+
2002/07/31/big/img_49
|
1849 |
+
2002/07/30/big/img_469
|
1850 |
+
2002/08/28/big/img_19197
|
1851 |
+
2002/08/25/big/img_205
|
1852 |
+
2002/08/10/big/img_390
|
1853 |
+
2002/08/23/big/img_291
|
1854 |
+
2002/08/26/big/img_230
|
1855 |
+
2002/08/18/big/img_76
|
1856 |
+
2002/07/23/big/img_409
|
1857 |
+
2002/08/14/big/img_1053
|
1858 |
+
2003/01/14/big/img_291
|
1859 |
+
2002/08/10/big/img_503
|
1860 |
+
2002/08/27/big/img_19928
|
1861 |
+
2002/08/03/big/img_563
|
1862 |
+
2002/08/17/big/img_250
|
1863 |
+
2002/08/06/big/img_2381
|
1864 |
+
2002/08/17/big/img_948
|
1865 |
+
2002/08/06/big/img_2710
|
1866 |
+
2002/07/22/big/img_696
|
1867 |
+
2002/07/31/big/img_670
|
1868 |
+
2002/08/12/big/img_594
|
1869 |
+
2002/07/29/big/img_624
|
1870 |
+
2003/01/17/big/img_934
|
1871 |
+
2002/08/03/big/img_584
|
1872 |
+
2002/08/22/big/img_1003
|
1873 |
+
2002/08/05/big/img_3396
|
1874 |
+
2003/01/13/big/img_570
|
1875 |
+
2002/08/02/big/img_219
|
1876 |
+
2002/09/02/big/img_15774
|
1877 |
+
2002/08/16/big/img_818
|
1878 |
+
2002/08/23/big/img_402
|
1879 |
+
2003/01/14/big/img_552
|
1880 |
+
2002/07/29/big/img_71
|
1881 |
+
2002/08/05/big/img_3592
|
1882 |
+
2002/08/16/big/img_80
|
1883 |
+
2002/07/27/big/img_672
|
1884 |
+
2003/01/13/big/img_470
|
1885 |
+
2003/01/16/big/img_702
|
1886 |
+
2002/09/01/big/img_16130
|
1887 |
+
2002/08/08/big/img_240
|
1888 |
+
2002/09/01/big/img_16338
|
1889 |
+
2002/07/26/big/img_312
|
1890 |
+
2003/01/14/big/img_538
|
1891 |
+
2002/07/20/big/img_695
|
1892 |
+
2002/08/30/big/img_18098
|
1893 |
+
2002/08/25/big/img_259
|
1894 |
+
2002/08/16/big/img_1042
|
1895 |
+
2002/08/09/big/img_837
|
1896 |
+
2002/08/31/big/img_17760
|
1897 |
+
2002/07/31/big/img_14
|
1898 |
+
2002/08/09/big/img_361
|
1899 |
+
2003/01/16/big/img_107
|
1900 |
+
2002/08/14/big/img_124
|
1901 |
+
2002/07/19/big/img_463
|
1902 |
+
2003/01/15/big/img_275
|
1903 |
+
2002/07/25/big/img_1151
|
1904 |
+
2002/07/29/big/img_1501
|
1905 |
+
2002/08/27/big/img_19889
|
1906 |
+
2002/08/29/big/img_18603
|
1907 |
+
2003/01/17/big/img_601
|
1908 |
+
2002/08/25/big/img_355
|
1909 |
+
2002/08/08/big/img_297
|
1910 |
+
2002/08/20/big/img_290
|
1911 |
+
2002/07/31/big/img_195
|
1912 |
+
2003/01/01/big/img_336
|
1913 |
+
2002/08/18/big/img_369
|
1914 |
+
2002/07/25/big/img_621
|
1915 |
+
2002/08/11/big/img_508
|
1916 |
+
2003/01/14/big/img_458
|
1917 |
+
2003/01/15/big/img_795
|
1918 |
+
2002/08/12/big/img_498
|
1919 |
+
2002/08/01/big/img_1734
|
1920 |
+
2002/08/02/big/img_246
|
1921 |
+
2002/08/16/big/img_565
|
1922 |
+
2002/08/11/big/img_475
|
1923 |
+
2002/08/22/big/img_408
|
1924 |
+
2002/07/28/big/img_78
|
1925 |
+
2002/07/21/big/img_81
|
1926 |
+
2003/01/14/big/img_697
|
1927 |
+
2002/08/14/big/img_661
|
1928 |
+
2002/08/15/big/img_507
|
1929 |
+
2002/08/19/big/img_55
|
1930 |
+
2002/07/22/big/img_152
|
1931 |
+
2003/01/14/big/img_470
|
1932 |
+
2002/08/03/big/img_379
|
1933 |
+
2002/08/22/big/img_506
|
1934 |
+
2003/01/16/big/img_966
|
1935 |
+
2002/08/18/big/img_698
|
1936 |
+
2002/08/24/big/img_528
|
1937 |
+
2002/08/23/big/img_10
|
1938 |
+
2002/08/01/big/img_1655
|
1939 |
+
2002/08/22/big/img_953
|
1940 |
+
2002/07/19/big/img_630
|
1941 |
+
2002/07/22/big/img_889
|
1942 |
+
2002/08/16/big/img_351
|
1943 |
+
2003/01/16/big/img_83
|
1944 |
+
2002/07/19/big/img_805
|
1945 |
+
2002/08/14/big/img_704
|
1946 |
+
2002/07/19/big/img_389
|
1947 |
+
2002/08/31/big/img_17765
|
1948 |
+
2002/07/29/big/img_606
|
1949 |
+
2003/01/17/big/img_939
|
1950 |
+
2002/09/02/big/img_15081
|
1951 |
+
2002/08/21/big/img_181
|
1952 |
+
2002/07/29/big/img_1321
|
1953 |
+
2002/07/21/big/img_497
|
1954 |
+
2002/07/20/big/img_539
|
1955 |
+
2002/08/24/big/img_119
|
1956 |
+
2002/08/01/big/img_1281
|
1957 |
+
2002/07/26/big/img_207
|
1958 |
+
2002/07/26/big/img_432
|
1959 |
+
2002/07/27/big/img_1006
|
1960 |
+
2002/08/05/big/img_3087
|
1961 |
+
2002/08/14/big/img_252
|
1962 |
+
2002/08/14/big/img_798
|
1963 |
+
2002/07/24/big/img_538
|
1964 |
+
2002/09/02/big/img_15507
|
1965 |
+
2002/08/08/big/img_901
|
1966 |
+
2003/01/14/big/img_557
|
1967 |
+
2002/08/07/big/img_1819
|
1968 |
+
2002/08/04/big/img_470
|
1969 |
+
2002/08/01/big/img_1504
|
1970 |
+
2002/08/16/big/img_1070
|
1971 |
+
2002/08/16/big/img_372
|
1972 |
+
2002/08/23/big/img_416
|
1973 |
+
2002/08/30/big/img_18208
|
1974 |
+
2002/08/01/big/img_2043
|
1975 |
+
2002/07/22/big/img_385
|
1976 |
+
2002/08/22/big/img_466
|
1977 |
+
2002/08/21/big/img_869
|
1978 |
+
2002/08/28/big/img_19429
|
1979 |
+
2002/08/02/big/img_770
|
1980 |
+
2002/07/23/big/img_433
|
1981 |
+
2003/01/14/big/img_13
|
1982 |
+
2002/07/27/big/img_953
|
1983 |
+
2002/09/02/big/img_15728
|
1984 |
+
2002/08/01/big/img_1361
|
1985 |
+
2002/08/29/big/img_18897
|
1986 |
+
2002/08/26/big/img_534
|
1987 |
+
2002/08/11/big/img_121
|
1988 |
+
2002/08/26/big/img_20130
|
1989 |
+
2002/07/31/big/img_363
|
1990 |
+
2002/08/13/big/img_978
|
1991 |
+
2002/07/25/big/img_835
|
1992 |
+
2002/08/02/big/img_906
|
1993 |
+
2003/01/14/big/img_548
|
1994 |
+
2002/07/30/big/img_80
|
1995 |
+
2002/07/26/big/img_982
|
1996 |
+
2003/01/16/big/img_99
|
1997 |
+
2002/08/19/big/img_362
|
1998 |
+
2002/08/24/big/img_376
|
1999 |
+
2002/08/07/big/img_1264
|
2000 |
+
2002/07/27/big/img_938
|
2001 |
+
2003/01/17/big/img_535
|
2002 |
+
2002/07/26/big/img_457
|
2003 |
+
2002/08/08/big/img_848
|
2004 |
+
2003/01/15/big/img_859
|
2005 |
+
2003/01/15/big/img_622
|
2006 |
+
2002/07/30/big/img_403
|
2007 |
+
2002/07/29/big/img_217
|
2008 |
+
2002/07/26/big/img_891
|
2009 |
+
2002/07/24/big/img_70
|
2010 |
+
2002/08/25/big/img_619
|
2011 |
+
2002/08/05/big/img_3375
|
2012 |
+
2002/08/01/big/img_2160
|
2013 |
+
2002/08/06/big/img_2227
|
2014 |
+
2003/01/14/big/img_117
|
2015 |
+
2002/08/14/big/img_227
|
2016 |
+
2002/08/13/big/img_565
|
2017 |
+
2002/08/19/big/img_625
|
2018 |
+
2002/08/03/big/img_812
|
2019 |
+
2002/07/24/big/img_41
|
2020 |
+
2002/08/16/big/img_235
|
2021 |
+
2002/07/29/big/img_759
|
2022 |
+
2002/07/21/big/img_433
|
2023 |
+
2002/07/29/big/img_190
|
2024 |
+
2003/01/16/big/img_435
|
2025 |
+
2003/01/13/big/img_708
|
2026 |
+
2002/07/30/big/img_57
|
2027 |
+
2002/08/22/big/img_162
|
2028 |
+
2003/01/01/big/img_558
|
2029 |
+
2003/01/15/big/img_604
|
2030 |
+
2002/08/16/big/img_935
|
2031 |
+
2002/08/20/big/img_394
|
2032 |
+
2002/07/28/big/img_465
|
2033 |
+
2002/09/02/big/img_15534
|
2034 |
+
2002/08/16/big/img_87
|
2035 |
+
2002/07/22/big/img_469
|
2036 |
+
2002/08/12/big/img_245
|
2037 |
+
2003/01/13/big/img_236
|
2038 |
+
2002/08/06/big/img_2736
|
2039 |
+
2002/08/03/big/img_348
|
2040 |
+
2003/01/14/big/img_218
|
2041 |
+
2002/07/26/big/img_232
|
2042 |
+
2003/01/15/big/img_244
|
2043 |
+
2002/07/25/big/img_1121
|
2044 |
+
2002/08/01/big/img_1484
|
2045 |
+
2002/07/26/big/img_541
|
2046 |
+
2002/08/07/big/img_1244
|
2047 |
+
2002/07/31/big/img_3
|
2048 |
+
2002/08/30/big/img_18437
|
2049 |
+
2002/08/29/big/img_19094
|
2050 |
+
2002/08/01/big/img_1355
|
2051 |
+
2002/08/19/big/img_338
|
2052 |
+
2002/07/19/big/img_255
|
2053 |
+
2002/07/21/big/img_76
|
2054 |
+
2002/08/25/big/img_199
|
2055 |
+
2002/08/12/big/img_740
|
2056 |
+
2002/07/30/big/img_852
|
2057 |
+
2002/08/15/big/img_599
|
2058 |
+
2002/08/23/big/img_254
|
2059 |
+
2002/08/19/big/img_125
|
2060 |
+
2002/07/24/big/img_2
|
2061 |
+
2002/08/04/big/img_145
|
2062 |
+
2002/08/05/big/img_3137
|
2063 |
+
2002/07/28/big/img_463
|
2064 |
+
2003/01/14/big/img_801
|
2065 |
+
2002/07/23/big/img_366
|
2066 |
+
2002/08/26/big/img_600
|
2067 |
+
2002/08/26/big/img_649
|
2068 |
+
2002/09/02/big/img_15849
|
2069 |
+
2002/07/26/big/img_248
|
2070 |
+
2003/01/13/big/img_200
|
2071 |
+
2002/08/07/big/img_1794
|
2072 |
+
2002/08/31/big/img_17270
|
2073 |
+
2002/08/23/big/img_608
|
2074 |
+
2003/01/13/big/img_837
|
2075 |
+
2002/08/23/big/img_581
|
2076 |
+
2002/08/20/big/img_754
|
2077 |
+
2002/08/18/big/img_183
|
2078 |
+
2002/08/20/big/img_328
|
2079 |
+
2002/07/22/big/img_494
|
2080 |
+
2002/07/29/big/img_399
|
2081 |
+
2002/08/28/big/img_19284
|
2082 |
+
2002/08/08/big/img_566
|
2083 |
+
2002/07/25/big/img_376
|
2084 |
+
2002/07/23/big/img_138
|
2085 |
+
2002/07/25/big/img_435
|
2086 |
+
2002/08/17/big/img_685
|
2087 |
+
2002/07/19/big/img_90
|
2088 |
+
2002/07/20/big/img_716
|
2089 |
+
2002/08/31/big/img_17458
|
2090 |
+
2002/08/26/big/img_461
|
2091 |
+
2002/07/25/big/img_355
|
2092 |
+
2002/08/06/big/img_2152
|
2093 |
+
2002/07/27/big/img_932
|
2094 |
+
2002/07/23/big/img_232
|
2095 |
+
2002/08/08/big/img_1020
|
2096 |
+
2002/07/31/big/img_366
|
2097 |
+
2002/08/06/big/img_2667
|
2098 |
+
2002/08/21/big/img_465
|
2099 |
+
2002/08/15/big/img_305
|
2100 |
+
2002/08/02/big/img_247
|
2101 |
+
2002/07/28/big/img_46
|
2102 |
+
2002/08/27/big/img_19922
|
2103 |
+
2002/08/23/big/img_643
|
2104 |
+
2003/01/13/big/img_624
|
2105 |
+
2002/08/23/big/img_625
|
2106 |
+
2002/08/05/big/img_3787
|
2107 |
+
2003/01/13/big/img_627
|
2108 |
+
2002/09/01/big/img_16381
|
2109 |
+
2002/08/05/big/img_3668
|
2110 |
+
2002/07/21/big/img_535
|
2111 |
+
2002/08/27/big/img_19680
|
2112 |
+
2002/07/22/big/img_413
|
2113 |
+
2002/07/29/big/img_481
|
2114 |
+
2003/01/15/big/img_496
|
2115 |
+
2002/07/23/big/img_701
|
2116 |
+
2002/08/29/big/img_18670
|
2117 |
+
2002/07/28/big/img_319
|
2118 |
+
2003/01/14/big/img_517
|
2119 |
+
2002/07/26/big/img_256
|
2120 |
+
2003/01/16/big/img_593
|
2121 |
+
2002/07/30/big/img_956
|
2122 |
+
2002/07/30/big/img_667
|
2123 |
+
2002/07/25/big/img_100
|
2124 |
+
2002/08/11/big/img_570
|
2125 |
+
2002/07/26/big/img_745
|
2126 |
+
2002/08/04/big/img_834
|
2127 |
+
2002/08/25/big/img_521
|
2128 |
+
2002/08/01/big/img_2148
|
2129 |
+
2002/09/02/big/img_15183
|
2130 |
+
2002/08/22/big/img_514
|
2131 |
+
2002/08/23/big/img_477
|
2132 |
+
2002/07/23/big/img_336
|
2133 |
+
2002/07/26/big/img_481
|
2134 |
+
2002/08/20/big/img_409
|
2135 |
+
2002/07/23/big/img_918
|
2136 |
+
2002/08/09/big/img_474
|
2137 |
+
2002/08/02/big/img_929
|
2138 |
+
2002/08/31/big/img_17932
|
2139 |
+
2002/08/19/big/img_161
|
2140 |
+
2002/08/09/big/img_667
|
2141 |
+
2002/07/31/big/img_805
|
2142 |
+
2002/09/02/big/img_15678
|
2143 |
+
2002/08/31/big/img_17509
|
2144 |
+
2002/08/29/big/img_18998
|
2145 |
+
2002/07/23/big/img_301
|
2146 |
+
2002/08/07/big/img_1612
|
2147 |
+
2002/08/06/big/img_2472
|
2148 |
+
2002/07/23/big/img_466
|
2149 |
+
2002/08/27/big/img_19634
|
2150 |
+
2003/01/16/big/img_16
|
2151 |
+
2002/08/14/big/img_193
|
2152 |
+
2002/08/21/big/img_340
|
2153 |
+
2002/08/27/big/img_19799
|
2154 |
+
2002/08/01/big/img_1345
|
2155 |
+
2002/08/07/big/img_1448
|
2156 |
+
2002/08/11/big/img_324
|
2157 |
+
2003/01/16/big/img_754
|
2158 |
+
2002/08/13/big/img_418
|
2159 |
+
2003/01/16/big/img_544
|
2160 |
+
2002/08/19/big/img_135
|
2161 |
+
2002/08/10/big/img_455
|
2162 |
+
2002/08/10/big/img_693
|
2163 |
+
2002/08/31/big/img_17967
|
2164 |
+
2002/08/28/big/img_19229
|
2165 |
+
2002/08/04/big/img_811
|
2166 |
+
2002/09/01/big/img_16225
|
2167 |
+
2003/01/16/big/img_428
|
2168 |
+
2002/09/02/big/img_15295
|
2169 |
+
2002/07/26/big/img_108
|
2170 |
+
2002/07/21/big/img_477
|
2171 |
+
2002/08/07/big/img_1354
|
2172 |
+
2002/08/23/big/img_246
|
2173 |
+
2002/08/16/big/img_652
|
2174 |
+
2002/07/27/big/img_553
|
2175 |
+
2002/07/31/big/img_346
|
2176 |
+
2002/08/04/big/img_537
|
2177 |
+
2002/08/08/big/img_498
|
2178 |
+
2002/08/29/big/img_18956
|
2179 |
+
2003/01/13/big/img_922
|
2180 |
+
2002/08/31/big/img_17425
|
2181 |
+
2002/07/26/big/img_438
|
2182 |
+
2002/08/19/big/img_185
|
2183 |
+
2003/01/16/big/img_33
|
2184 |
+
2002/08/10/big/img_252
|
2185 |
+
2002/07/29/big/img_598
|
2186 |
+
2002/08/27/big/img_19820
|
2187 |
+
2002/08/06/big/img_2664
|
2188 |
+
2002/08/20/big/img_705
|
2189 |
+
2003/01/14/big/img_816
|
2190 |
+
2002/08/03/big/img_552
|
2191 |
+
2002/07/25/big/img_561
|
2192 |
+
2002/07/25/big/img_934
|
2193 |
+
2002/08/01/big/img_1893
|
2194 |
+
2003/01/14/big/img_746
|
2195 |
+
2003/01/16/big/img_519
|
2196 |
+
2002/08/03/big/img_681
|
2197 |
+
2002/07/24/big/img_808
|
2198 |
+
2002/08/14/big/img_803
|
2199 |
+
2002/08/25/big/img_155
|
2200 |
+
2002/07/30/big/img_1107
|
2201 |
+
2002/08/29/big/img_18882
|
2202 |
+
2003/01/15/big/img_598
|
2203 |
+
2002/08/19/big/img_122
|
2204 |
+
2002/07/30/big/img_428
|
2205 |
+
2002/07/24/big/img_684
|
2206 |
+
2002/08/22/big/img_192
|
2207 |
+
2002/08/22/big/img_543
|
2208 |
+
2002/08/07/big/img_1318
|
2209 |
+
2002/08/18/big/img_25
|
2210 |
+
2002/07/26/big/img_583
|
2211 |
+
2002/07/20/big/img_464
|
2212 |
+
2002/08/19/big/img_664
|
2213 |
+
2002/08/24/big/img_861
|
2214 |
+
2002/09/01/big/img_16136
|
2215 |
+
2002/08/22/big/img_400
|
2216 |
+
2002/08/12/big/img_445
|
2217 |
+
2003/01/14/big/img_174
|
2218 |
+
2002/08/27/big/img_19677
|
2219 |
+
2002/08/31/big/img_17214
|
2220 |
+
2002/08/30/big/img_18175
|
2221 |
+
2003/01/17/big/img_402
|
2222 |
+
2002/08/06/big/img_2396
|
2223 |
+
2002/08/18/big/img_448
|
2224 |
+
2002/08/21/big/img_165
|
2225 |
+
2002/08/31/big/img_17609
|
2226 |
+
2003/01/01/big/img_151
|
2227 |
+
2002/08/26/big/img_372
|
2228 |
+
2002/09/02/big/img_15994
|
2229 |
+
2002/07/26/big/img_660
|
2230 |
+
2002/09/02/big/img_15197
|
2231 |
+
2002/07/29/big/img_258
|
2232 |
+
2002/08/30/big/img_18525
|
2233 |
+
2003/01/13/big/img_368
|
2234 |
+
2002/07/29/big/img_1538
|
2235 |
+
2002/07/21/big/img_787
|
2236 |
+
2002/08/18/big/img_152
|
2237 |
+
2002/08/06/big/img_2379
|
2238 |
+
2003/01/17/big/img_864
|
2239 |
+
2002/08/27/big/img_19998
|
2240 |
+
2002/08/01/big/img_1634
|
2241 |
+
2002/07/25/big/img_414
|
2242 |
+
2002/08/22/big/img_627
|
2243 |
+
2002/08/07/big/img_1669
|
2244 |
+
2002/08/16/big/img_1052
|
2245 |
+
2002/08/31/big/img_17796
|
2246 |
+
2002/08/18/big/img_199
|
2247 |
+
2002/09/02/big/img_15147
|
2248 |
+
2002/08/09/big/img_460
|
2249 |
+
2002/08/14/big/img_581
|
2250 |
+
2002/08/30/big/img_18286
|
2251 |
+
2002/07/26/big/img_337
|
2252 |
+
2002/08/18/big/img_589
|
2253 |
+
2003/01/14/big/img_866
|
2254 |
+
2002/07/20/big/img_624
|
2255 |
+
2002/08/01/big/img_1801
|
2256 |
+
2002/07/24/big/img_683
|
2257 |
+
2002/08/09/big/img_725
|
2258 |
+
2003/01/14/big/img_34
|
2259 |
+
2002/07/30/big/img_144
|
2260 |
+
2002/07/30/big/img_706
|
2261 |
+
2002/08/08/big/img_394
|
2262 |
+
2002/08/19/big/img_619
|
2263 |
+
2002/08/06/big/img_2703
|
2264 |
+
2002/08/29/big/img_19034
|
2265 |
+
2002/07/24/big/img_67
|
2266 |
+
2002/08/27/big/img_19841
|
2267 |
+
2002/08/19/big/img_427
|
2268 |
+
2003/01/14/big/img_333
|
2269 |
+
2002/09/01/big/img_16406
|
2270 |
+
2002/07/19/big/img_882
|
2271 |
+
2002/08/17/big/img_238
|
2272 |
+
2003/01/14/big/img_739
|
2273 |
+
2002/07/22/big/img_151
|
2274 |
+
2002/08/21/big/img_743
|
2275 |
+
2002/07/25/big/img_1048
|
2276 |
+
2002/07/30/big/img_395
|
2277 |
+
2003/01/13/big/img_584
|
2278 |
+
2002/08/13/big/img_742
|
2279 |
+
2002/08/13/big/img_1168
|
2280 |
+
2003/01/14/big/img_147
|
2281 |
+
2002/07/26/big/img_803
|
2282 |
+
2002/08/05/big/img_3298
|
2283 |
+
2002/08/07/big/img_1451
|
2284 |
+
2002/08/16/big/img_424
|
2285 |
+
2002/07/29/big/img_1069
|
2286 |
+
2002/09/01/big/img_16735
|
2287 |
+
2002/07/21/big/img_637
|
2288 |
+
2003/01/14/big/img_585
|
2289 |
+
2002/08/02/big/img_358
|
2290 |
+
2003/01/13/big/img_358
|
2291 |
+
2002/08/14/big/img_198
|
2292 |
+
2002/08/17/big/img_935
|
2293 |
+
2002/08/04/big/img_42
|
2294 |
+
2002/08/30/big/img_18245
|
2295 |
+
2002/07/25/big/img_158
|
2296 |
+
2002/08/22/big/img_744
|
2297 |
+
2002/08/06/big/img_2291
|
2298 |
+
2002/08/05/big/img_3044
|
2299 |
+
2002/07/30/big/img_272
|
2300 |
+
2002/08/23/big/img_641
|
2301 |
+
2002/07/24/big/img_797
|
2302 |
+
2002/07/30/big/img_392
|
2303 |
+
2003/01/14/big/img_447
|
2304 |
+
2002/07/31/big/img_898
|
2305 |
+
2002/08/06/big/img_2812
|
2306 |
+
2002/08/13/big/img_564
|
2307 |
+
2002/07/22/big/img_43
|
2308 |
+
2002/07/26/big/img_634
|
2309 |
+
2002/07/19/big/img_843
|
2310 |
+
2002/08/26/big/img_58
|
2311 |
+
2002/07/21/big/img_375
|
2312 |
+
2002/08/25/big/img_729
|
2313 |
+
2002/07/19/big/img_561
|
2314 |
+
2003/01/15/big/img_884
|
2315 |
+
2002/07/25/big/img_891
|
2316 |
+
2002/08/09/big/img_558
|
2317 |
+
2002/08/26/big/img_587
|
2318 |
+
2002/08/13/big/img_1146
|
2319 |
+
2002/09/02/big/img_15153
|
2320 |
+
2002/07/26/big/img_316
|
2321 |
+
2002/08/01/big/img_1940
|
2322 |
+
2002/08/26/big/img_90
|
2323 |
+
2003/01/13/big/img_347
|
2324 |
+
2002/07/25/big/img_520
|
2325 |
+
2002/08/29/big/img_18718
|
2326 |
+
2002/08/28/big/img_19219
|
2327 |
+
2002/08/13/big/img_375
|
2328 |
+
2002/07/20/big/img_719
|
2329 |
+
2002/08/31/big/img_17431
|
2330 |
+
2002/07/28/big/img_192
|
2331 |
+
2002/08/26/big/img_259
|
2332 |
+
2002/08/18/big/img_484
|
2333 |
+
2002/07/29/big/img_580
|
2334 |
+
2002/07/26/big/img_84
|
2335 |
+
2002/08/02/big/img_302
|
2336 |
+
2002/08/31/big/img_17007
|
2337 |
+
2003/01/15/big/img_543
|
2338 |
+
2002/09/01/big/img_16488
|
2339 |
+
2002/08/22/big/img_798
|
2340 |
+
2002/07/30/big/img_383
|
2341 |
+
2002/08/04/big/img_668
|
2342 |
+
2002/08/13/big/img_156
|
2343 |
+
2002/08/07/big/img_1353
|
2344 |
+
2002/07/25/big/img_281
|
2345 |
+
2003/01/14/big/img_587
|
2346 |
+
2003/01/15/big/img_524
|
2347 |
+
2002/08/19/big/img_726
|
2348 |
+
2002/08/21/big/img_709
|
2349 |
+
2002/08/26/big/img_465
|
2350 |
+
2002/07/31/big/img_658
|
2351 |
+
2002/08/28/big/img_19148
|
2352 |
+
2002/07/23/big/img_423
|
2353 |
+
2002/08/16/big/img_758
|
2354 |
+
2002/08/22/big/img_523
|
2355 |
+
2002/08/16/big/img_591
|
2356 |
+
2002/08/23/big/img_845
|
2357 |
+
2002/07/26/big/img_678
|
2358 |
+
2002/08/09/big/img_806
|
2359 |
+
2002/08/06/big/img_2369
|
2360 |
+
2002/07/29/big/img_457
|
2361 |
+
2002/07/19/big/img_278
|
2362 |
+
2002/08/30/big/img_18107
|
2363 |
+
2002/07/26/big/img_444
|
2364 |
+
2002/08/20/big/img_278
|
2365 |
+
2002/08/26/big/img_92
|
2366 |
+
2002/08/26/big/img_257
|
2367 |
+
2002/07/25/big/img_266
|
2368 |
+
2002/08/05/big/img_3829
|
2369 |
+
2002/07/26/big/img_757
|
2370 |
+
2002/07/29/big/img_1536
|
2371 |
+
2002/08/09/big/img_472
|
2372 |
+
2003/01/17/big/img_480
|
2373 |
+
2002/08/28/big/img_19355
|
2374 |
+
2002/07/26/big/img_97
|
2375 |
+
2002/08/06/big/img_2503
|
2376 |
+
2002/07/19/big/img_254
|
2377 |
+
2002/08/01/big/img_1470
|
2378 |
+
2002/08/21/big/img_42
|
2379 |
+
2002/08/20/big/img_217
|
2380 |
+
2002/08/06/big/img_2459
|
2381 |
+
2002/07/19/big/img_552
|
2382 |
+
2002/08/13/big/img_717
|
2383 |
+
2002/08/12/big/img_586
|
2384 |
+
2002/08/20/big/img_411
|
2385 |
+
2003/01/13/big/img_768
|
2386 |
+
2002/08/07/big/img_1747
|
2387 |
+
2002/08/15/big/img_385
|
2388 |
+
2002/08/01/big/img_1648
|
2389 |
+
2002/08/15/big/img_311
|
2390 |
+
2002/08/21/big/img_95
|
2391 |
+
2002/08/09/big/img_108
|
2392 |
+
2002/08/21/big/img_398
|
2393 |
+
2002/08/17/big/img_340
|
2394 |
+
2002/08/14/big/img_474
|
2395 |
+
2002/08/13/big/img_294
|
2396 |
+
2002/08/24/big/img_840
|
2397 |
+
2002/08/09/big/img_808
|
2398 |
+
2002/08/23/big/img_491
|
2399 |
+
2002/07/28/big/img_33
|
2400 |
+
2003/01/13/big/img_664
|
2401 |
+
2002/08/02/big/img_261
|
2402 |
+
2002/08/09/big/img_591
|
2403 |
+
2002/07/26/big/img_309
|
2404 |
+
2003/01/14/big/img_372
|
2405 |
+
2002/08/19/big/img_581
|
2406 |
+
2002/08/19/big/img_168
|
2407 |
+
2002/08/26/big/img_422
|
2408 |
+
2002/07/24/big/img_106
|
2409 |
+
2002/08/01/big/img_1936
|
2410 |
+
2002/08/05/big/img_3764
|
2411 |
+
2002/08/21/big/img_266
|
2412 |
+
2002/08/31/big/img_17968
|
2413 |
+
2002/08/01/big/img_1941
|
2414 |
+
2002/08/15/big/img_550
|
2415 |
+
2002/08/14/big/img_13
|
2416 |
+
2002/07/30/big/img_171
|
2417 |
+
2003/01/13/big/img_490
|
2418 |
+
2002/07/25/big/img_427
|
2419 |
+
2002/07/19/big/img_770
|
2420 |
+
2002/08/12/big/img_759
|
2421 |
+
2003/01/15/big/img_1360
|
2422 |
+
2002/08/05/big/img_3692
|
2423 |
+
2003/01/16/big/img_30
|
2424 |
+
2002/07/25/big/img_1026
|
2425 |
+
2002/07/22/big/img_288
|
2426 |
+
2002/08/29/big/img_18801
|
2427 |
+
2002/07/24/big/img_793
|
2428 |
+
2002/08/13/big/img_178
|
2429 |
+
2002/08/06/big/img_2322
|
2430 |
+
2003/01/14/big/img_560
|
2431 |
+
2002/08/18/big/img_408
|
2432 |
+
2003/01/16/big/img_915
|
2433 |
+
2003/01/16/big/img_679
|
2434 |
+
2002/08/07/big/img_1552
|
2435 |
+
2002/08/29/big/img_19050
|
2436 |
+
2002/08/01/big/img_2172
|
2437 |
+
2002/07/31/big/img_30
|
2438 |
+
2002/07/30/big/img_1019
|
2439 |
+
2002/07/30/big/img_587
|
2440 |
+
2003/01/13/big/img_773
|
2441 |
+
2002/07/30/big/img_410
|
2442 |
+
2002/07/28/big/img_65
|
2443 |
+
2002/08/05/big/img_3138
|
2444 |
+
2002/07/23/big/img_541
|
2445 |
+
2002/08/22/big/img_963
|
2446 |
+
2002/07/27/big/img_657
|
2447 |
+
2002/07/30/big/img_1051
|
2448 |
+
2003/01/16/big/img_150
|
2449 |
+
2002/07/31/big/img_519
|
2450 |
+
2002/08/01/big/img_1961
|
2451 |
+
2002/08/05/big/img_3752
|
2452 |
+
2002/07/23/big/img_631
|
2453 |
+
2003/01/14/big/img_237
|
2454 |
+
2002/07/28/big/img_21
|
2455 |
+
2002/07/22/big/img_813
|
2456 |
+
2002/08/05/big/img_3563
|
2457 |
+
2003/01/17/big/img_620
|
2458 |
+
2002/07/19/big/img_523
|
2459 |
+
2002/07/30/big/img_904
|
2460 |
+
2002/08/29/big/img_18642
|
2461 |
+
2002/08/11/big/img_492
|
2462 |
+
2002/08/01/big/img_2130
|
2463 |
+
2002/07/25/big/img_618
|
2464 |
+
2002/08/17/big/img_305
|
2465 |
+
2003/01/16/big/img_520
|
2466 |
+
2002/07/26/big/img_495
|
2467 |
+
2002/08/17/big/img_164
|
2468 |
+
2002/08/03/big/img_440
|
2469 |
+
2002/07/24/big/img_441
|
2470 |
+
2002/08/06/big/img_2146
|
2471 |
+
2002/08/11/big/img_558
|
2472 |
+
2002/08/02/big/img_545
|
2473 |
+
2002/08/31/big/img_18090
|
2474 |
+
2003/01/01/big/img_136
|
2475 |
+
2002/07/25/big/img_1099
|
2476 |
+
2003/01/13/big/img_728
|
2477 |
+
2003/01/16/big/img_197
|
2478 |
+
2002/07/26/big/img_651
|
2479 |
+
2002/08/11/big/img_676
|
2480 |
+
2003/01/15/big/img_10
|
2481 |
+
2002/08/21/big/img_250
|
2482 |
+
2002/08/14/big/img_325
|
2483 |
+
2002/08/04/big/img_390
|
2484 |
+
2002/07/24/big/img_554
|
2485 |
+
2003/01/16/big/img_333
|
2486 |
+
2002/07/31/big/img_922
|
2487 |
+
2002/09/02/big/img_15586
|
2488 |
+
2003/01/16/big/img_184
|
2489 |
+
2002/07/22/big/img_766
|
2490 |
+
2002/07/21/big/img_608
|
2491 |
+
2002/08/07/big/img_1578
|
2492 |
+
2002/08/17/big/img_961
|
2493 |
+
2002/07/27/big/img_324
|
2494 |
+
2002/08/05/big/img_3765
|
2495 |
+
2002/08/23/big/img_462
|
2496 |
+
2003/01/16/big/img_382
|
2497 |
+
2002/08/27/big/img_19838
|
2498 |
+
2002/08/01/big/img_1505
|
2499 |
+
2002/08/21/big/img_662
|
2500 |
+
2002/08/14/big/img_605
|
2501 |
+
2002/08/19/big/img_816
|
2502 |
+
2002/07/29/big/img_136
|
2503 |
+
2002/08/20/big/img_719
|
2504 |
+
2002/08/06/big/img_2826
|
2505 |
+
2002/08/10/big/img_630
|
2506 |
+
2003/01/17/big/img_973
|
2507 |
+
2002/08/14/big/img_116
|
2508 |
+
2002/08/02/big/img_666
|
2509 |
+
2002/08/21/big/img_710
|
2510 |
+
2002/08/05/big/img_55
|
2511 |
+
2002/07/31/big/img_229
|
2512 |
+
2002/08/01/big/img_1549
|
2513 |
+
2002/07/23/big/img_432
|
2514 |
+
2002/07/21/big/img_430
|
2515 |
+
2002/08/21/big/img_549
|
2516 |
+
2002/08/08/big/img_985
|
2517 |
+
2002/07/20/big/img_610
|
2518 |
+
2002/07/23/big/img_978
|
2519 |
+
2002/08/23/big/img_219
|
2520 |
+
2002/07/25/big/img_175
|
2521 |
+
2003/01/15/big/img_230
|
2522 |
+
2002/08/23/big/img_385
|
2523 |
+
2002/07/31/big/img_879
|
2524 |
+
2002/08/12/big/img_495
|
2525 |
+
2002/08/22/big/img_499
|
2526 |
+
2002/08/30/big/img_18322
|
2527 |
+
2002/08/15/big/img_795
|
2528 |
+
2002/08/13/big/img_835
|
2529 |
+
2003/01/17/big/img_930
|
2530 |
+
2002/07/30/big/img_873
|
2531 |
+
2002/08/11/big/img_257
|
2532 |
+
2002/07/31/big/img_593
|
2533 |
+
2002/08/21/big/img_916
|
2534 |
+
2003/01/13/big/img_814
|
2535 |
+
2002/07/25/big/img_722
|
2536 |
+
2002/08/16/big/img_379
|
2537 |
+
2002/07/31/big/img_497
|
2538 |
+
2002/07/22/big/img_602
|
2539 |
+
2002/08/21/big/img_642
|
2540 |
+
2002/08/21/big/img_614
|
2541 |
+
2002/08/23/big/img_482
|
2542 |
+
2002/07/29/big/img_603
|
2543 |
+
2002/08/13/big/img_705
|
2544 |
+
2002/07/23/big/img_833
|
2545 |
+
2003/01/14/big/img_511
|
2546 |
+
2002/07/24/big/img_376
|
2547 |
+
2002/08/17/big/img_1030
|
2548 |
+
2002/08/05/big/img_3576
|
2549 |
+
2002/08/16/big/img_540
|
2550 |
+
2002/07/22/big/img_630
|
2551 |
+
2002/08/10/big/img_180
|
2552 |
+
2002/08/14/big/img_905
|
2553 |
+
2002/08/29/big/img_18777
|
2554 |
+
2002/08/22/big/img_693
|
2555 |
+
2003/01/16/big/img_933
|
2556 |
+
2002/08/20/big/img_555
|
2557 |
+
2002/08/15/big/img_549
|
2558 |
+
2003/01/14/big/img_830
|
2559 |
+
2003/01/16/big/img_64
|
2560 |
+
2002/08/27/big/img_19670
|
2561 |
+
2002/08/22/big/img_729
|
2562 |
+
2002/07/27/big/img_981
|
2563 |
+
2002/08/09/big/img_458
|
2564 |
+
2003/01/17/big/img_884
|
2565 |
+
2002/07/25/big/img_639
|
2566 |
+
2002/08/31/big/img_18008
|
2567 |
+
2002/08/22/big/img_249
|
2568 |
+
2002/08/17/big/img_971
|
2569 |
+
2002/08/04/big/img_308
|
2570 |
+
2002/07/28/big/img_362
|
2571 |
+
2002/08/12/big/img_142
|
2572 |
+
2002/08/26/big/img_61
|
2573 |
+
2002/08/14/big/img_422
|
2574 |
+
2002/07/19/big/img_607
|
2575 |
+
2003/01/15/big/img_717
|
2576 |
+
2002/08/01/big/img_1475
|
2577 |
+
2002/08/29/big/img_19061
|
2578 |
+
2003/01/01/big/img_346
|
2579 |
+
2002/07/20/big/img_315
|
2580 |
+
2003/01/15/big/img_756
|
2581 |
+
2002/08/15/big/img_879
|
2582 |
+
2002/08/08/big/img_615
|
2583 |
+
2003/01/13/big/img_431
|
2584 |
+
2002/08/05/big/img_3233
|
2585 |
+
2002/08/24/big/img_526
|
2586 |
+
2003/01/13/big/img_717
|
2587 |
+
2002/09/01/big/img_16408
|
2588 |
+
2002/07/22/big/img_217
|
2589 |
+
2002/07/31/big/img_960
|
2590 |
+
2002/08/21/big/img_610
|
2591 |
+
2002/08/05/big/img_3753
|
2592 |
+
2002/08/03/big/img_151
|
2593 |
+
2002/08/21/big/img_267
|
2594 |
+
2002/08/01/big/img_2175
|
2595 |
+
2002/08/04/big/img_556
|
2596 |
+
2002/08/21/big/img_527
|
2597 |
+
2002/09/02/big/img_15800
|
2598 |
+
2002/07/27/big/img_156
|
2599 |
+
2002/07/20/big/img_590
|
2600 |
+
2002/08/15/big/img_700
|
2601 |
+
2002/08/08/big/img_444
|
2602 |
+
2002/07/25/big/img_94
|
2603 |
+
2002/07/24/big/img_778
|
2604 |
+
2002/08/14/big/img_694
|
2605 |
+
2002/07/20/big/img_666
|
2606 |
+
2002/08/02/big/img_200
|
2607 |
+
2002/08/02/big/img_578
|
2608 |
+
2003/01/17/big/img_332
|
2609 |
+
2002/09/01/big/img_16352
|
2610 |
+
2002/08/27/big/img_19668
|
2611 |
+
2002/07/23/big/img_823
|
2612 |
+
2002/08/13/big/img_431
|
2613 |
+
2003/01/16/big/img_463
|
2614 |
+
2002/08/27/big/img_19711
|
2615 |
+
2002/08/23/big/img_154
|
2616 |
+
2002/07/31/big/img_360
|
2617 |
+
2002/08/23/big/img_555
|
2618 |
+
2002/08/10/big/img_561
|
2619 |
+
2003/01/14/big/img_550
|
2620 |
+
2002/08/07/big/img_1370
|
2621 |
+
2002/07/30/big/img_1184
|
2622 |
+
2002/08/01/big/img_1445
|
2623 |
+
2002/08/23/big/img_22
|
2624 |
+
2002/07/30/big/img_606
|
2625 |
+
2003/01/17/big/img_271
|
2626 |
+
2002/08/31/big/img_17316
|
2627 |
+
2002/08/16/big/img_973
|
2628 |
+
2002/07/26/big/img_77
|
2629 |
+
2002/07/20/big/img_788
|
2630 |
+
2002/08/06/big/img_2426
|
2631 |
+
2002/08/07/big/img_1498
|
2632 |
+
2002/08/16/big/img_358
|
2633 |
+
2002/08/06/big/img_2851
|
2634 |
+
2002/08/12/big/img_359
|
2635 |
+
2002/08/01/big/img_1521
|
2636 |
+
2002/08/02/big/img_709
|
2637 |
+
2002/08/20/big/img_935
|
2638 |
+
2002/08/12/big/img_188
|
2639 |
+
2002/08/24/big/img_411
|
2640 |
+
2002/08/22/big/img_680
|
2641 |
+
2002/08/06/big/img_2480
|
2642 |
+
2002/07/20/big/img_627
|
2643 |
+
2002/07/30/big/img_214
|
2644 |
+
2002/07/25/big/img_354
|
2645 |
+
2002/08/02/big/img_636
|
2646 |
+
2003/01/15/big/img_661
|
2647 |
+
2002/08/07/big/img_1327
|
2648 |
+
2002/08/01/big/img_2108
|
2649 |
+
2002/08/31/big/img_17919
|
2650 |
+
2002/08/29/big/img_18768
|
2651 |
+
2002/08/05/big/img_3840
|
2652 |
+
2002/07/26/big/img_242
|
2653 |
+
2003/01/14/big/img_451
|
2654 |
+
2002/08/20/big/img_923
|
2655 |
+
2002/08/27/big/img_19908
|
2656 |
+
2002/08/16/big/img_282
|
2657 |
+
2002/08/19/big/img_440
|
2658 |
+
2003/01/01/big/img_230
|
2659 |
+
2002/08/08/big/img_212
|
2660 |
+
2002/07/20/big/img_443
|
2661 |
+
2002/08/25/big/img_635
|
2662 |
+
2003/01/13/big/img_1169
|
2663 |
+
2002/07/26/big/img_998
|
2664 |
+
2002/08/15/big/img_995
|
2665 |
+
2002/08/06/big/img_3002
|
2666 |
+
2002/07/29/big/img_460
|
2667 |
+
2003/01/14/big/img_925
|
2668 |
+
2002/07/23/big/img_539
|
2669 |
+
2002/08/16/big/img_694
|
2670 |
+
2003/01/13/big/img_459
|
2671 |
+
2002/07/23/big/img_249
|
2672 |
+
2002/08/20/big/img_539
|
2673 |
+
2002/08/04/big/img_186
|
2674 |
+
2002/08/26/big/img_264
|
2675 |
+
2002/07/22/big/img_704
|
2676 |
+
2002/08/25/big/img_277
|
2677 |
+
2002/08/22/big/img_988
|
2678 |
+
2002/07/29/big/img_504
|
2679 |
+
2002/08/05/big/img_3600
|
2680 |
+
2002/08/30/big/img_18380
|
2681 |
+
2003/01/14/big/img_937
|
2682 |
+
2002/08/21/big/img_254
|
2683 |
+
2002/08/10/big/img_130
|
2684 |
+
2002/08/20/big/img_339
|
2685 |
+
2003/01/14/big/img_428
|
2686 |
+
2002/08/20/big/img_889
|
2687 |
+
2002/08/31/big/img_17637
|
2688 |
+
2002/07/26/big/img_644
|
2689 |
+
2002/09/01/big/img_16776
|
2690 |
+
2002/08/06/big/img_2239
|
2691 |
+
2002/08/06/big/img_2646
|
2692 |
+
2003/01/13/big/img_491
|
2693 |
+
2002/08/10/big/img_579
|
2694 |
+
2002/08/21/big/img_713
|
2695 |
+
2002/08/22/big/img_482
|
2696 |
+
2002/07/22/big/img_167
|
2697 |
+
2002/07/24/big/img_539
|
2698 |
+
2002/08/14/big/img_721
|
2699 |
+
2002/07/25/big/img_389
|
2700 |
+
2002/09/01/big/img_16591
|
2701 |
+
2002/08/13/big/img_543
|
2702 |
+
2003/01/14/big/img_432
|
2703 |
+
2002/08/09/big/img_287
|
2704 |
+
2002/07/26/big/img_126
|
2705 |
+
2002/08/23/big/img_412
|
2706 |
+
2002/08/15/big/img_1034
|
2707 |
+
2002/08/28/big/img_19485
|
2708 |
+
2002/07/31/big/img_236
|
2709 |
+
2002/07/30/big/img_523
|
2710 |
+
2002/07/19/big/img_141
|
2711 |
+
2003/01/17/big/img_957
|
2712 |
+
2002/08/04/big/img_81
|
2713 |
+
2002/07/25/big/img_206
|
2714 |
+
2002/08/15/big/img_716
|
2715 |
+
2002/08/13/big/img_403
|
2716 |
+
2002/08/15/big/img_685
|
2717 |
+
2002/07/26/big/img_884
|
2718 |
+
2002/07/19/big/img_499
|
2719 |
+
2002/07/23/big/img_772
|
2720 |
+
2002/07/27/big/img_752
|
2721 |
+
2003/01/14/big/img_493
|
2722 |
+
2002/08/25/big/img_664
|
2723 |
+
2002/07/31/big/img_334
|
2724 |
+
2002/08/26/big/img_678
|
2725 |
+
2002/09/01/big/img_16541
|
2726 |
+
2003/01/14/big/img_347
|
2727 |
+
2002/07/23/big/img_187
|
2728 |
+
2002/07/30/big/img_1163
|
2729 |
+
2002/08/05/big/img_35
|
2730 |
+
2002/08/22/big/img_944
|
2731 |
+
2002/08/07/big/img_1239
|
2732 |
+
2002/07/29/big/img_1215
|
2733 |
+
2002/08/03/big/img_312
|
2734 |
+
2002/08/05/big/img_3523
|
2735 |
+
2002/07/29/big/img_218
|
2736 |
+
2002/08/13/big/img_672
|
2737 |
+
2002/08/16/big/img_205
|
2738 |
+
2002/08/17/big/img_594
|
2739 |
+
2002/07/29/big/img_1411
|
2740 |
+
2002/07/30/big/img_942
|
2741 |
+
2003/01/16/big/img_312
|
2742 |
+
2002/08/08/big/img_312
|
2743 |
+
2002/07/25/big/img_15
|
2744 |
+
2002/08/09/big/img_839
|
2745 |
+
2002/08/01/big/img_2069
|
2746 |
+
2002/08/31/big/img_17512
|
2747 |
+
2002/08/01/big/img_3
|
2748 |
+
2002/07/31/big/img_320
|
2749 |
+
2003/01/15/big/img_1265
|
2750 |
+
2002/08/14/big/img_563
|
2751 |
+
2002/07/31/big/img_167
|
2752 |
+
2002/08/20/big/img_374
|
2753 |
+
2002/08/13/big/img_406
|
2754 |
+
2002/08/08/big/img_625
|
2755 |
+
2002/08/02/big/img_314
|
2756 |
+
2002/08/27/big/img_19964
|
2757 |
+
2002/09/01/big/img_16670
|
2758 |
+
2002/07/31/big/img_599
|
2759 |
+
2002/08/29/big/img_18906
|
2760 |
+
2002/07/24/big/img_373
|
2761 |
+
2002/07/26/big/img_513
|
2762 |
+
2002/09/02/big/img_15497
|
2763 |
+
2002/08/19/big/img_117
|
2764 |
+
2003/01/01/big/img_158
|
2765 |
+
2002/08/24/big/img_178
|
2766 |
+
2003/01/13/big/img_935
|
2767 |
+
2002/08/13/big/img_609
|
2768 |
+
2002/08/30/big/img_18341
|
2769 |
+
2002/08/25/big/img_674
|
2770 |
+
2003/01/13/big/img_209
|
2771 |
+
2002/08/13/big/img_258
|
2772 |
+
2002/08/05/big/img_3543
|
2773 |
+
2002/08/07/big/img_1970
|
2774 |
+
2002/08/06/big/img_3004
|
2775 |
+
2003/01/17/big/img_487
|
2776 |
+
2002/08/24/big/img_873
|
2777 |
+
2002/08/29/big/img_18730
|
2778 |
+
2002/08/09/big/img_375
|
2779 |
+
2003/01/16/big/img_751
|
2780 |
+
2002/08/02/big/img_603
|
2781 |
+
2002/08/19/big/img_325
|
2782 |
+
2002/09/01/big/img_16420
|
2783 |
+
2002/08/05/big/img_3633
|
2784 |
+
2002/08/21/big/img_516
|
2785 |
+
2002/07/19/big/img_501
|
2786 |
+
2002/07/26/big/img_688
|
2787 |
+
2002/07/24/big/img_256
|
2788 |
+
2002/07/25/big/img_438
|
2789 |
+
2002/07/31/big/img_1017
|
2790 |
+
2002/08/22/big/img_512
|
2791 |
+
2002/07/21/big/img_543
|
2792 |
+
2002/08/08/big/img_223
|
2793 |
+
2002/08/19/big/img_189
|
2794 |
+
2002/08/12/big/img_630
|
2795 |
+
2002/07/30/big/img_958
|
2796 |
+
2002/07/28/big/img_208
|
2797 |
+
2002/08/31/big/img_17691
|
2798 |
+
2002/07/22/big/img_542
|
2799 |
+
2002/07/19/big/img_741
|
2800 |
+
2002/07/19/big/img_158
|
2801 |
+
2002/08/15/big/img_399
|
2802 |
+
2002/08/01/big/img_2159
|
2803 |
+
2002/08/14/big/img_455
|
2804 |
+
2002/08/17/big/img_1011
|
2805 |
+
2002/08/26/big/img_744
|
2806 |
+
2002/08/12/big/img_624
|
2807 |
+
2003/01/17/big/img_821
|
2808 |
+
2002/08/16/big/img_980
|
2809 |
+
2002/07/28/big/img_281
|
2810 |
+
2002/07/25/big/img_171
|
2811 |
+
2002/08/03/big/img_116
|
2812 |
+
2002/07/22/big/img_467
|
2813 |
+
2002/07/31/big/img_750
|
2814 |
+
2002/07/26/big/img_435
|
2815 |
+
2002/07/19/big/img_822
|
2816 |
+
2002/08/13/big/img_626
|
2817 |
+
2002/08/11/big/img_344
|
2818 |
+
2002/08/02/big/img_473
|
2819 |
+
2002/09/01/big/img_16817
|
2820 |
+
2002/08/01/big/img_1275
|
2821 |
+
2002/08/28/big/img_19270
|
2822 |
+
2002/07/23/big/img_607
|
2823 |
+
2002/08/09/big/img_316
|
2824 |
+
2002/07/29/big/img_626
|
2825 |
+
2002/07/24/big/img_824
|
2826 |
+
2002/07/22/big/img_342
|
2827 |
+
2002/08/08/big/img_794
|
2828 |
+
2002/08/07/big/img_1209
|
2829 |
+
2002/07/19/big/img_18
|
2830 |
+
2002/08/25/big/img_634
|
2831 |
+
2002/07/24/big/img_730
|
2832 |
+
2003/01/17/big/img_356
|
2833 |
+
2002/07/23/big/img_305
|
2834 |
+
2002/07/30/big/img_453
|
2835 |
+
2003/01/13/big/img_972
|
2836 |
+
2002/08/06/big/img_2610
|
2837 |
+
2002/08/29/big/img_18920
|
2838 |
+
2002/07/31/big/img_123
|
2839 |
+
2002/07/26/big/img_979
|
2840 |
+
2002/08/24/big/img_635
|
2841 |
+
2002/08/05/big/img_3704
|
2842 |
+
2002/08/07/big/img_1358
|
2843 |
+
2002/07/22/big/img_306
|
2844 |
+
2002/08/13/big/img_619
|
2845 |
+
2002/08/02/big/img_366
|
face_detect/data/__init__.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from .wider_face import WiderFaceDetection, detection_collate
|
2 |
+
from .data_augment import *
|
3 |
+
from .config import *
|
face_detect/data/config.py
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# config.py
|
2 |
+
|
3 |
+
cfg_mnet = {
|
4 |
+
'name': 'mobilenet0.25',
|
5 |
+
'min_sizes': [[16, 32], [64, 128], [256, 512]],
|
6 |
+
'steps': [8, 16, 32],
|
7 |
+
'variance': [0.1, 0.2],
|
8 |
+
'clip': False,
|
9 |
+
'loc_weight': 2.0,
|
10 |
+
'gpu_train': True,
|
11 |
+
'batch_size': 32,
|
12 |
+
'ngpu': 1,
|
13 |
+
'epoch': 250,
|
14 |
+
'decay1': 190,
|
15 |
+
'decay2': 220,
|
16 |
+
'image_size': 640,
|
17 |
+
'pretrain': False,
|
18 |
+
'return_layers': {'stage1': 1, 'stage2': 2, 'stage3': 3},
|
19 |
+
'in_channel': 32,
|
20 |
+
'out_channel': 64
|
21 |
+
}
|
22 |
+
|
23 |
+
cfg_re50 = {
|
24 |
+
'name': 'Resnet50',
|
25 |
+
'min_sizes': [[16, 32], [64, 128], [256, 512]],
|
26 |
+
'steps': [8, 16, 32],
|
27 |
+
'variance': [0.1, 0.2],
|
28 |
+
'clip': False,
|
29 |
+
'loc_weight': 2.0,
|
30 |
+
'gpu_train': True,
|
31 |
+
'batch_size': 24,
|
32 |
+
'ngpu': 4,
|
33 |
+
'epoch': 100,
|
34 |
+
'decay1': 70,
|
35 |
+
'decay2': 90,
|
36 |
+
'image_size': 840,
|
37 |
+
'pretrain': False,
|
38 |
+
'return_layers': {'layer2': 1, 'layer3': 2, 'layer4': 3},
|
39 |
+
'in_channel': 256,
|
40 |
+
'out_channel': 256
|
41 |
+
}
|
42 |
+
|
face_detect/data/data_augment.py
ADDED
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import numpy as np
|
3 |
+
import random
|
4 |
+
from utils.box_utils import matrix_iof
|
5 |
+
|
6 |
+
|
7 |
+
def _crop(image, boxes, labels, landm, img_dim):
|
8 |
+
height, width, _ = image.shape
|
9 |
+
pad_image_flag = True
|
10 |
+
|
11 |
+
for _ in range(250):
|
12 |
+
"""
|
13 |
+
if random.uniform(0, 1) <= 0.2:
|
14 |
+
scale = 1.0
|
15 |
+
else:
|
16 |
+
scale = random.uniform(0.3, 1.0)
|
17 |
+
"""
|
18 |
+
PRE_SCALES = [0.3, 0.45, 0.6, 0.8, 1.0]
|
19 |
+
scale = random.choice(PRE_SCALES)
|
20 |
+
short_side = min(width, height)
|
21 |
+
w = int(scale * short_side)
|
22 |
+
h = w
|
23 |
+
|
24 |
+
if width == w:
|
25 |
+
l = 0
|
26 |
+
else:
|
27 |
+
l = random.randrange(width - w)
|
28 |
+
if height == h:
|
29 |
+
t = 0
|
30 |
+
else:
|
31 |
+
t = random.randrange(height - h)
|
32 |
+
roi = np.array((l, t, l + w, t + h))
|
33 |
+
|
34 |
+
value = matrix_iof(boxes, roi[np.newaxis])
|
35 |
+
flag = (value >= 1)
|
36 |
+
if not flag.any():
|
37 |
+
continue
|
38 |
+
|
39 |
+
centers = (boxes[:, :2] + boxes[:, 2:]) / 2
|
40 |
+
mask_a = np.logical_and(roi[:2] < centers, centers < roi[2:]).all(axis=1)
|
41 |
+
boxes_t = boxes[mask_a].copy()
|
42 |
+
labels_t = labels[mask_a].copy()
|
43 |
+
landms_t = landm[mask_a].copy()
|
44 |
+
landms_t = landms_t.reshape([-1, 5, 2])
|
45 |
+
|
46 |
+
if boxes_t.shape[0] == 0:
|
47 |
+
continue
|
48 |
+
|
49 |
+
image_t = image[roi[1]:roi[3], roi[0]:roi[2]]
|
50 |
+
|
51 |
+
boxes_t[:, :2] = np.maximum(boxes_t[:, :2], roi[:2])
|
52 |
+
boxes_t[:, :2] -= roi[:2]
|
53 |
+
boxes_t[:, 2:] = np.minimum(boxes_t[:, 2:], roi[2:])
|
54 |
+
boxes_t[:, 2:] -= roi[:2]
|
55 |
+
|
56 |
+
# landm
|
57 |
+
landms_t[:, :, :2] = landms_t[:, :, :2] - roi[:2]
|
58 |
+
landms_t[:, :, :2] = np.maximum(landms_t[:, :, :2], np.array([0, 0]))
|
59 |
+
landms_t[:, :, :2] = np.minimum(landms_t[:, :, :2], roi[2:] - roi[:2])
|
60 |
+
landms_t = landms_t.reshape([-1, 10])
|
61 |
+
|
62 |
+
|
63 |
+
# make sure that the cropped image contains at least one face > 16 pixel at training image scale
|
64 |
+
b_w_t = (boxes_t[:, 2] - boxes_t[:, 0] + 1) / w * img_dim
|
65 |
+
b_h_t = (boxes_t[:, 3] - boxes_t[:, 1] + 1) / h * img_dim
|
66 |
+
mask_b = np.minimum(b_w_t, b_h_t) > 0.0
|
67 |
+
boxes_t = boxes_t[mask_b]
|
68 |
+
labels_t = labels_t[mask_b]
|
69 |
+
landms_t = landms_t[mask_b]
|
70 |
+
|
71 |
+
if boxes_t.shape[0] == 0:
|
72 |
+
continue
|
73 |
+
|
74 |
+
pad_image_flag = False
|
75 |
+
|
76 |
+
return image_t, boxes_t, labels_t, landms_t, pad_image_flag
|
77 |
+
return image, boxes, labels, landm, pad_image_flag
|
78 |
+
|
79 |
+
|
80 |
+
def _distort(image):
|
81 |
+
|
82 |
+
def _convert(image, alpha=1, beta=0):
|
83 |
+
tmp = image.astype(float) * alpha + beta
|
84 |
+
tmp[tmp < 0] = 0
|
85 |
+
tmp[tmp > 255] = 255
|
86 |
+
image[:] = tmp
|
87 |
+
|
88 |
+
image = image.copy()
|
89 |
+
|
90 |
+
if random.randrange(2):
|
91 |
+
|
92 |
+
#brightness distortion
|
93 |
+
if random.randrange(2):
|
94 |
+
_convert(image, beta=random.uniform(-32, 32))
|
95 |
+
|
96 |
+
#contrast distortion
|
97 |
+
if random.randrange(2):
|
98 |
+
_convert(image, alpha=random.uniform(0.5, 1.5))
|
99 |
+
|
100 |
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
|
101 |
+
|
102 |
+
#saturation distortion
|
103 |
+
if random.randrange(2):
|
104 |
+
_convert(image[:, :, 1], alpha=random.uniform(0.5, 1.5))
|
105 |
+
|
106 |
+
#hue distortion
|
107 |
+
if random.randrange(2):
|
108 |
+
tmp = image[:, :, 0].astype(int) + random.randint(-18, 18)
|
109 |
+
tmp %= 180
|
110 |
+
image[:, :, 0] = tmp
|
111 |
+
|
112 |
+
image = cv2.cvtColor(image, cv2.COLOR_HSV2BGR)
|
113 |
+
|
114 |
+
else:
|
115 |
+
|
116 |
+
#brightness distortion
|
117 |
+
if random.randrange(2):
|
118 |
+
_convert(image, beta=random.uniform(-32, 32))
|
119 |
+
|
120 |
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
|
121 |
+
|
122 |
+
#saturation distortion
|
123 |
+
if random.randrange(2):
|
124 |
+
_convert(image[:, :, 1], alpha=random.uniform(0.5, 1.5))
|
125 |
+
|
126 |
+
#hue distortion
|
127 |
+
if random.randrange(2):
|
128 |
+
tmp = image[:, :, 0].astype(int) + random.randint(-18, 18)
|
129 |
+
tmp %= 180
|
130 |
+
image[:, :, 0] = tmp
|
131 |
+
|
132 |
+
image = cv2.cvtColor(image, cv2.COLOR_HSV2BGR)
|
133 |
+
|
134 |
+
#contrast distortion
|
135 |
+
if random.randrange(2):
|
136 |
+
_convert(image, alpha=random.uniform(0.5, 1.5))
|
137 |
+
|
138 |
+
return image
|
139 |
+
|
140 |
+
|
141 |
+
def _expand(image, boxes, fill, p):
|
142 |
+
if random.randrange(2):
|
143 |
+
return image, boxes
|
144 |
+
|
145 |
+
height, width, depth = image.shape
|
146 |
+
|
147 |
+
scale = random.uniform(1, p)
|
148 |
+
w = int(scale * width)
|
149 |
+
h = int(scale * height)
|
150 |
+
|
151 |
+
left = random.randint(0, w - width)
|
152 |
+
top = random.randint(0, h - height)
|
153 |
+
|
154 |
+
boxes_t = boxes.copy()
|
155 |
+
boxes_t[:, :2] += (left, top)
|
156 |
+
boxes_t[:, 2:] += (left, top)
|
157 |
+
expand_image = np.empty(
|
158 |
+
(h, w, depth),
|
159 |
+
dtype=image.dtype)
|
160 |
+
expand_image[:, :] = fill
|
161 |
+
expand_image[top:top + height, left:left + width] = image
|
162 |
+
image = expand_image
|
163 |
+
|
164 |
+
return image, boxes_t
|
165 |
+
|
166 |
+
|
167 |
+
def _mirror(image, boxes, landms):
|
168 |
+
_, width, _ = image.shape
|
169 |
+
if random.randrange(2):
|
170 |
+
image = image[:, ::-1]
|
171 |
+
boxes = boxes.copy()
|
172 |
+
boxes[:, 0::2] = width - boxes[:, 2::-2]
|
173 |
+
|
174 |
+
# landm
|
175 |
+
landms = landms.copy()
|
176 |
+
landms = landms.reshape([-1, 5, 2])
|
177 |
+
landms[:, :, 0] = width - landms[:, :, 0]
|
178 |
+
tmp = landms[:, 1, :].copy()
|
179 |
+
landms[:, 1, :] = landms[:, 0, :]
|
180 |
+
landms[:, 0, :] = tmp
|
181 |
+
tmp1 = landms[:, 4, :].copy()
|
182 |
+
landms[:, 4, :] = landms[:, 3, :]
|
183 |
+
landms[:, 3, :] = tmp1
|
184 |
+
landms = landms.reshape([-1, 10])
|
185 |
+
|
186 |
+
return image, boxes, landms
|
187 |
+
|
188 |
+
|
189 |
+
def _pad_to_square(image, rgb_mean, pad_image_flag):
|
190 |
+
if not pad_image_flag:
|
191 |
+
return image
|
192 |
+
height, width, _ = image.shape
|
193 |
+
long_side = max(width, height)
|
194 |
+
image_t = np.empty((long_side, long_side, 3), dtype=image.dtype)
|
195 |
+
image_t[:, :] = rgb_mean
|
196 |
+
image_t[0:0 + height, 0:0 + width] = image
|
197 |
+
return image_t
|
198 |
+
|
199 |
+
|
200 |
+
def _resize_subtract_mean(image, insize, rgb_mean):
|
201 |
+
interp_methods = [cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_NEAREST, cv2.INTER_LANCZOS4]
|
202 |
+
interp_method = interp_methods[random.randrange(5)]
|
203 |
+
image = cv2.resize(image, (insize, insize), interpolation=interp_method)
|
204 |
+
image = image.astype(np.float32)
|
205 |
+
image -= rgb_mean
|
206 |
+
return image.transpose(2, 0, 1)
|
207 |
+
|
208 |
+
|
209 |
+
class preproc(object):
|
210 |
+
|
211 |
+
def __init__(self, img_dim, rgb_means):
|
212 |
+
self.img_dim = img_dim
|
213 |
+
self.rgb_means = rgb_means
|
214 |
+
|
215 |
+
def __call__(self, image, targets):
|
216 |
+
assert targets.shape[0] > 0, "this image does not have gt"
|
217 |
+
|
218 |
+
boxes = targets[:, :4].copy()
|
219 |
+
labels = targets[:, -1].copy()
|
220 |
+
landm = targets[:, 4:-1].copy()
|
221 |
+
|
222 |
+
image_t, boxes_t, labels_t, landm_t, pad_image_flag = _crop(image, boxes, labels, landm, self.img_dim)
|
223 |
+
image_t = _distort(image_t)
|
224 |
+
image_t = _pad_to_square(image_t,self.rgb_means, pad_image_flag)
|
225 |
+
image_t, boxes_t, landm_t = _mirror(image_t, boxes_t, landm_t)
|
226 |
+
height, width, _ = image_t.shape
|
227 |
+
image_t = _resize_subtract_mean(image_t, self.img_dim, self.rgb_means)
|
228 |
+
boxes_t[:, 0::2] /= width
|
229 |
+
boxes_t[:, 1::2] /= height
|
230 |
+
|
231 |
+
landm_t[:, 0::2] /= width
|
232 |
+
landm_t[:, 1::2] /= height
|
233 |
+
|
234 |
+
labels_t = np.expand_dims(labels_t, 1)
|
235 |
+
targets_t = np.hstack((boxes_t, landm_t, labels_t))
|
236 |
+
|
237 |
+
return image_t, targets_t
|
face_detect/data/wider_face.py
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import os.path
|
3 |
+
import sys
|
4 |
+
import torch
|
5 |
+
import torch.utils.data as data
|
6 |
+
import cv2
|
7 |
+
import numpy as np
|
8 |
+
|
9 |
+
class WiderFaceDetection(data.Dataset):
|
10 |
+
def __init__(self, txt_path, preproc=None):
|
11 |
+
self.preproc = preproc
|
12 |
+
self.imgs_path = []
|
13 |
+
self.words = []
|
14 |
+
f = open(txt_path,'r')
|
15 |
+
lines = f.readlines()
|
16 |
+
isFirst = True
|
17 |
+
labels = []
|
18 |
+
for line in lines:
|
19 |
+
line = line.rstrip()
|
20 |
+
if line.startswith('#'):
|
21 |
+
if isFirst is True:
|
22 |
+
isFirst = False
|
23 |
+
else:
|
24 |
+
labels_copy = labels.copy()
|
25 |
+
self.words.append(labels_copy)
|
26 |
+
labels.clear()
|
27 |
+
path = line[2:]
|
28 |
+
path = txt_path.replace('label.txt','images/') + path
|
29 |
+
self.imgs_path.append(path)
|
30 |
+
else:
|
31 |
+
line = line.split(' ')
|
32 |
+
label = [float(x) for x in line]
|
33 |
+
labels.append(label)
|
34 |
+
|
35 |
+
self.words.append(labels)
|
36 |
+
|
37 |
+
def __len__(self):
|
38 |
+
return len(self.imgs_path)
|
39 |
+
|
40 |
+
def __getitem__(self, index):
|
41 |
+
img = cv2.imread(self.imgs_path[index])
|
42 |
+
height, width, _ = img.shape
|
43 |
+
|
44 |
+
labels = self.words[index]
|
45 |
+
annotations = np.zeros((0, 15))
|
46 |
+
if len(labels) == 0:
|
47 |
+
return annotations
|
48 |
+
for idx, label in enumerate(labels):
|
49 |
+
annotation = np.zeros((1, 15))
|
50 |
+
# bbox
|
51 |
+
annotation[0, 0] = label[0] # x1
|
52 |
+
annotation[0, 1] = label[1] # y1
|
53 |
+
annotation[0, 2] = label[0] + label[2] # x2
|
54 |
+
annotation[0, 3] = label[1] + label[3] # y2
|
55 |
+
|
56 |
+
# landmarks
|
57 |
+
annotation[0, 4] = label[4] # l0_x
|
58 |
+
annotation[0, 5] = label[5] # l0_y
|
59 |
+
annotation[0, 6] = label[7] # l1_x
|
60 |
+
annotation[0, 7] = label[8] # l1_y
|
61 |
+
annotation[0, 8] = label[10] # l2_x
|
62 |
+
annotation[0, 9] = label[11] # l2_y
|
63 |
+
annotation[0, 10] = label[13] # l3_x
|
64 |
+
annotation[0, 11] = label[14] # l3_y
|
65 |
+
annotation[0, 12] = label[16] # l4_x
|
66 |
+
annotation[0, 13] = label[17] # l4_y
|
67 |
+
if (annotation[0, 4]<0):
|
68 |
+
annotation[0, 14] = -1
|
69 |
+
else:
|
70 |
+
annotation[0, 14] = 1
|
71 |
+
|
72 |
+
annotations = np.append(annotations, annotation, axis=0)
|
73 |
+
target = np.array(annotations)
|
74 |
+
if self.preproc is not None:
|
75 |
+
img, target = self.preproc(img, target)
|
76 |
+
|
77 |
+
return torch.from_numpy(img), target
|
78 |
+
|
79 |
+
def detection_collate(batch):
|
80 |
+
"""Custom collate fn for dealing with batches of images that have a different
|
81 |
+
number of associated object annotations (bounding boxes).
|
82 |
+
|
83 |
+
Arguments:
|
84 |
+
batch: (tuple) A tuple of tensor images and lists of annotations
|
85 |
+
|
86 |
+
Return:
|
87 |
+
A tuple containing:
|
88 |
+
1) (tensor) batch of images stacked on their 0 dim
|
89 |
+
2) (list of tensors) annotations for a given image are stacked on 0 dim
|
90 |
+
"""
|
91 |
+
targets = []
|
92 |
+
imgs = []
|
93 |
+
for _, sample in enumerate(batch):
|
94 |
+
for _, tup in enumerate(sample):
|
95 |
+
if torch.is_tensor(tup):
|
96 |
+
imgs.append(tup)
|
97 |
+
elif isinstance(tup, type(np.empty(0))):
|
98 |
+
annos = torch.from_numpy(tup).float()
|
99 |
+
targets.append(annos)
|
100 |
+
|
101 |
+
return (torch.stack(imgs, 0), targets)
|
face_detect/facemodels/__init__.py
ADDED
File without changes
|
face_detect/facemodels/net.py
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import time
|
2 |
+
import torch
|
3 |
+
import torch.nn as nn
|
4 |
+
import torchvision.models._utils as _utils
|
5 |
+
import torchvision.models as models
|
6 |
+
import torch.nn.functional as F
|
7 |
+
from torch.autograd import Variable
|
8 |
+
|
9 |
+
def conv_bn(inp, oup, stride = 1, leaky = 0):
|
10 |
+
return nn.Sequential(
|
11 |
+
nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
|
12 |
+
nn.BatchNorm2d(oup),
|
13 |
+
nn.LeakyReLU(negative_slope=leaky, inplace=True)
|
14 |
+
)
|
15 |
+
|
16 |
+
def conv_bn_no_relu(inp, oup, stride):
|
17 |
+
return nn.Sequential(
|
18 |
+
nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
|
19 |
+
nn.BatchNorm2d(oup),
|
20 |
+
)
|
21 |
+
|
22 |
+
def conv_bn1X1(inp, oup, stride, leaky=0):
|
23 |
+
return nn.Sequential(
|
24 |
+
nn.Conv2d(inp, oup, 1, stride, padding=0, bias=False),
|
25 |
+
nn.BatchNorm2d(oup),
|
26 |
+
nn.LeakyReLU(negative_slope=leaky, inplace=True)
|
27 |
+
)
|
28 |
+
|
29 |
+
def conv_dw(inp, oup, stride, leaky=0.1):
|
30 |
+
return nn.Sequential(
|
31 |
+
nn.Conv2d(inp, inp, 3, stride, 1, groups=inp, bias=False),
|
32 |
+
nn.BatchNorm2d(inp),
|
33 |
+
nn.LeakyReLU(negative_slope= leaky,inplace=True),
|
34 |
+
|
35 |
+
nn.Conv2d(inp, oup, 1, 1, 0, bias=False),
|
36 |
+
nn.BatchNorm2d(oup),
|
37 |
+
nn.LeakyReLU(negative_slope= leaky,inplace=True),
|
38 |
+
)
|
39 |
+
|
40 |
+
class SSH(nn.Module):
|
41 |
+
def __init__(self, in_channel, out_channel):
|
42 |
+
super(SSH, self).__init__()
|
43 |
+
assert out_channel % 4 == 0
|
44 |
+
leaky = 0
|
45 |
+
if (out_channel <= 64):
|
46 |
+
leaky = 0.1
|
47 |
+
self.conv3X3 = conv_bn_no_relu(in_channel, out_channel//2, stride=1)
|
48 |
+
|
49 |
+
self.conv5X5_1 = conv_bn(in_channel, out_channel//4, stride=1, leaky = leaky)
|
50 |
+
self.conv5X5_2 = conv_bn_no_relu(out_channel//4, out_channel//4, stride=1)
|
51 |
+
|
52 |
+
self.conv7X7_2 = conv_bn(out_channel//4, out_channel//4, stride=1, leaky = leaky)
|
53 |
+
self.conv7x7_3 = conv_bn_no_relu(out_channel//4, out_channel//4, stride=1)
|
54 |
+
|
55 |
+
def forward(self, input):
|
56 |
+
conv3X3 = self.conv3X3(input)
|
57 |
+
|
58 |
+
conv5X5_1 = self.conv5X5_1(input)
|
59 |
+
conv5X5 = self.conv5X5_2(conv5X5_1)
|
60 |
+
|
61 |
+
conv7X7_2 = self.conv7X7_2(conv5X5_1)
|
62 |
+
conv7X7 = self.conv7x7_3(conv7X7_2)
|
63 |
+
|
64 |
+
out = torch.cat([conv3X3, conv5X5, conv7X7], dim=1)
|
65 |
+
out = F.relu(out)
|
66 |
+
return out
|
67 |
+
|
68 |
+
class FPN(nn.Module):
|
69 |
+
def __init__(self,in_channels_list,out_channels):
|
70 |
+
super(FPN,self).__init__()
|
71 |
+
leaky = 0
|
72 |
+
if (out_channels <= 64):
|
73 |
+
leaky = 0.1
|
74 |
+
self.output1 = conv_bn1X1(in_channels_list[0], out_channels, stride = 1, leaky = leaky)
|
75 |
+
self.output2 = conv_bn1X1(in_channels_list[1], out_channels, stride = 1, leaky = leaky)
|
76 |
+
self.output3 = conv_bn1X1(in_channels_list[2], out_channels, stride = 1, leaky = leaky)
|
77 |
+
|
78 |
+
self.merge1 = conv_bn(out_channels, out_channels, leaky = leaky)
|
79 |
+
self.merge2 = conv_bn(out_channels, out_channels, leaky = leaky)
|
80 |
+
|
81 |
+
def forward(self, input):
|
82 |
+
# names = list(input.keys())
|
83 |
+
input = list(input.values())
|
84 |
+
|
85 |
+
output1 = self.output1(input[0])
|
86 |
+
output2 = self.output2(input[1])
|
87 |
+
output3 = self.output3(input[2])
|
88 |
+
|
89 |
+
up3 = F.interpolate(output3, size=[output2.size(2), output2.size(3)], mode="nearest")
|
90 |
+
output2 = output2 + up3
|
91 |
+
output2 = self.merge2(output2)
|
92 |
+
|
93 |
+
up2 = F.interpolate(output2, size=[output1.size(2), output1.size(3)], mode="nearest")
|
94 |
+
output1 = output1 + up2
|
95 |
+
output1 = self.merge1(output1)
|
96 |
+
|
97 |
+
out = [output1, output2, output3]
|
98 |
+
return out
|
99 |
+
|
100 |
+
|
101 |
+
|
102 |
+
class MobileNetV1(nn.Module):
|
103 |
+
def __init__(self):
|
104 |
+
super(MobileNetV1, self).__init__()
|
105 |
+
self.stage1 = nn.Sequential(
|
106 |
+
conv_bn(3, 8, 2, leaky = 0.1), # 3
|
107 |
+
conv_dw(8, 16, 1), # 7
|
108 |
+
conv_dw(16, 32, 2), # 11
|
109 |
+
conv_dw(32, 32, 1), # 19
|
110 |
+
conv_dw(32, 64, 2), # 27
|
111 |
+
conv_dw(64, 64, 1), # 43
|
112 |
+
)
|
113 |
+
self.stage2 = nn.Sequential(
|
114 |
+
conv_dw(64, 128, 2), # 43 + 16 = 59
|
115 |
+
conv_dw(128, 128, 1), # 59 + 32 = 91
|
116 |
+
conv_dw(128, 128, 1), # 91 + 32 = 123
|
117 |
+
conv_dw(128, 128, 1), # 123 + 32 = 155
|
118 |
+
conv_dw(128, 128, 1), # 155 + 32 = 187
|
119 |
+
conv_dw(128, 128, 1), # 187 + 32 = 219
|
120 |
+
)
|
121 |
+
self.stage3 = nn.Sequential(
|
122 |
+
conv_dw(128, 256, 2), # 219 +3 2 = 241
|
123 |
+
conv_dw(256, 256, 1), # 241 + 64 = 301
|
124 |
+
)
|
125 |
+
self.avg = nn.AdaptiveAvgPool2d((1,1))
|
126 |
+
self.fc = nn.Linear(256, 1000)
|
127 |
+
|
128 |
+
def forward(self, x):
|
129 |
+
x = self.stage1(x)
|
130 |
+
x = self.stage2(x)
|
131 |
+
x = self.stage3(x)
|
132 |
+
x = self.avg(x)
|
133 |
+
# x = self.model(x)
|
134 |
+
x = x.view(-1, 256)
|
135 |
+
x = self.fc(x)
|
136 |
+
return x
|
137 |
+
|
face_detect/facemodels/retinaface.py
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import torch.nn as nn
|
3 |
+
import torchvision.models.detection.backbone_utils as backbone_utils
|
4 |
+
import torchvision.models._utils as _utils
|
5 |
+
import torch.nn.functional as F
|
6 |
+
from collections import OrderedDict
|
7 |
+
|
8 |
+
from facemodels.net import MobileNetV1 as MobileNetV1
|
9 |
+
from facemodels.net import FPN as FPN
|
10 |
+
from facemodels.net import SSH as SSH
|
11 |
+
|
12 |
+
|
13 |
+
|
14 |
+
class ClassHead(nn.Module):
|
15 |
+
def __init__(self,inchannels=512,num_anchors=3):
|
16 |
+
super(ClassHead,self).__init__()
|
17 |
+
self.num_anchors = num_anchors
|
18 |
+
self.conv1x1 = nn.Conv2d(inchannels,self.num_anchors*2,kernel_size=(1,1),stride=1,padding=0)
|
19 |
+
|
20 |
+
def forward(self,x):
|
21 |
+
out = self.conv1x1(x)
|
22 |
+
out = out.permute(0,2,3,1).contiguous()
|
23 |
+
|
24 |
+
return out.view(out.shape[0], -1, 2)
|
25 |
+
|
26 |
+
class BboxHead(nn.Module):
|
27 |
+
def __init__(self,inchannels=512,num_anchors=3):
|
28 |
+
super(BboxHead,self).__init__()
|
29 |
+
self.conv1x1 = nn.Conv2d(inchannels,num_anchors*4,kernel_size=(1,1),stride=1,padding=0)
|
30 |
+
|
31 |
+
def forward(self,x):
|
32 |
+
out = self.conv1x1(x)
|
33 |
+
out = out.permute(0,2,3,1).contiguous()
|
34 |
+
|
35 |
+
return out.view(out.shape[0], -1, 4)
|
36 |
+
|
37 |
+
class LandmarkHead(nn.Module):
|
38 |
+
def __init__(self,inchannels=512,num_anchors=3):
|
39 |
+
super(LandmarkHead,self).__init__()
|
40 |
+
self.conv1x1 = nn.Conv2d(inchannels,num_anchors*10,kernel_size=(1,1),stride=1,padding=0)
|
41 |
+
|
42 |
+
def forward(self,x):
|
43 |
+
out = self.conv1x1(x)
|
44 |
+
out = out.permute(0,2,3,1).contiguous()
|
45 |
+
|
46 |
+
return out.view(out.shape[0], -1, 10)
|
47 |
+
|
48 |
+
class RetinaFace(nn.Module):
|
49 |
+
def __init__(self, cfg = None, phase = 'train'):
|
50 |
+
"""
|
51 |
+
:param cfg: Network related settings.
|
52 |
+
:param phase: train or test.
|
53 |
+
"""
|
54 |
+
super(RetinaFace,self).__init__()
|
55 |
+
self.phase = phase
|
56 |
+
backbone = None
|
57 |
+
if cfg['name'] == 'mobilenet0.25':
|
58 |
+
backbone = MobileNetV1()
|
59 |
+
if cfg['pretrain']:
|
60 |
+
checkpoint = torch.load("./weights/mobilenetV1X0.25_pretrain.tar", map_location=torch.device('cpu'))
|
61 |
+
from collections import OrderedDict
|
62 |
+
new_state_dict = OrderedDict()
|
63 |
+
for k, v in checkpoint['state_dict'].items():
|
64 |
+
name = k[7:] # remove module.
|
65 |
+
new_state_dict[name] = v
|
66 |
+
# load params
|
67 |
+
backbone.load_state_dict(new_state_dict)
|
68 |
+
elif cfg['name'] == 'Resnet50':
|
69 |
+
import torchvision.models as models
|
70 |
+
backbone = models.resnet50(pretrained=cfg['pretrain'])
|
71 |
+
|
72 |
+
self.body = _utils.IntermediateLayerGetter(backbone, cfg['return_layers'])
|
73 |
+
in_channels_stage2 = cfg['in_channel']
|
74 |
+
in_channels_list = [
|
75 |
+
in_channels_stage2 * 2,
|
76 |
+
in_channels_stage2 * 4,
|
77 |
+
in_channels_stage2 * 8,
|
78 |
+
]
|
79 |
+
out_channels = cfg['out_channel']
|
80 |
+
self.fpn = FPN(in_channels_list,out_channels)
|
81 |
+
self.ssh1 = SSH(out_channels, out_channels)
|
82 |
+
self.ssh2 = SSH(out_channels, out_channels)
|
83 |
+
self.ssh3 = SSH(out_channels, out_channels)
|
84 |
+
|
85 |
+
self.ClassHead = self._make_class_head(fpn_num=3, inchannels=cfg['out_channel'])
|
86 |
+
self.BboxHead = self._make_bbox_head(fpn_num=3, inchannels=cfg['out_channel'])
|
87 |
+
self.LandmarkHead = self._make_landmark_head(fpn_num=3, inchannels=cfg['out_channel'])
|
88 |
+
|
89 |
+
def _make_class_head(self,fpn_num=3,inchannels=64,anchor_num=2):
|
90 |
+
classhead = nn.ModuleList()
|
91 |
+
for i in range(fpn_num):
|
92 |
+
classhead.append(ClassHead(inchannels,anchor_num))
|
93 |
+
return classhead
|
94 |
+
|
95 |
+
def _make_bbox_head(self,fpn_num=3,inchannels=64,anchor_num=2):
|
96 |
+
bboxhead = nn.ModuleList()
|
97 |
+
for i in range(fpn_num):
|
98 |
+
bboxhead.append(BboxHead(inchannels,anchor_num))
|
99 |
+
return bboxhead
|
100 |
+
|
101 |
+
def _make_landmark_head(self,fpn_num=3,inchannels=64,anchor_num=2):
|
102 |
+
landmarkhead = nn.ModuleList()
|
103 |
+
for i in range(fpn_num):
|
104 |
+
landmarkhead.append(LandmarkHead(inchannels,anchor_num))
|
105 |
+
return landmarkhead
|
106 |
+
|
107 |
+
def forward(self,inputs):
|
108 |
+
out = self.body(inputs)
|
109 |
+
|
110 |
+
# FPN
|
111 |
+
fpn = self.fpn(out)
|
112 |
+
|
113 |
+
# SSH
|
114 |
+
feature1 = self.ssh1(fpn[0])
|
115 |
+
feature2 = self.ssh2(fpn[1])
|
116 |
+
feature3 = self.ssh3(fpn[2])
|
117 |
+
features = [feature1, feature2, feature3]
|
118 |
+
|
119 |
+
bbox_regressions = torch.cat([self.BboxHead[i](feature) for i, feature in enumerate(features)], dim=1)
|
120 |
+
classifications = torch.cat([self.ClassHead[i](feature) for i, feature in enumerate(features)],dim=1)
|
121 |
+
ldm_regressions = torch.cat([self.LandmarkHead[i](feature) for i, feature in enumerate(features)], dim=1)
|
122 |
+
|
123 |
+
if self.phase == 'train':
|
124 |
+
output = (bbox_regressions, classifications, ldm_regressions)
|
125 |
+
else:
|
126 |
+
output = (bbox_regressions, F.softmax(classifications, dim=-1), ldm_regressions)
|
127 |
+
return output
|
face_detect/layers/__init__.py
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
from .functions import *
|
2 |
+
from .modules import *
|
face_detect/layers/functions/prior_box.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from itertools import product as product
|
3 |
+
import numpy as np
|
4 |
+
from math import ceil
|
5 |
+
|
6 |
+
|
7 |
+
class PriorBox(object):
|
8 |
+
def __init__(self, cfg, image_size=None, phase='train'):
|
9 |
+
super(PriorBox, self).__init__()
|
10 |
+
self.min_sizes = cfg['min_sizes']
|
11 |
+
self.steps = cfg['steps']
|
12 |
+
self.clip = cfg['clip']
|
13 |
+
self.image_size = image_size
|
14 |
+
self.feature_maps = [[ceil(self.image_size[0]/step), ceil(self.image_size[1]/step)] for step in self.steps]
|
15 |
+
self.name = "s"
|
16 |
+
|
17 |
+
def forward(self):
|
18 |
+
anchors = []
|
19 |
+
for k, f in enumerate(self.feature_maps):
|
20 |
+
min_sizes = self.min_sizes[k]
|
21 |
+
for i, j in product(range(f[0]), range(f[1])):
|
22 |
+
for min_size in min_sizes:
|
23 |
+
s_kx = min_size / self.image_size[1]
|
24 |
+
s_ky = min_size / self.image_size[0]
|
25 |
+
dense_cx = [x * self.steps[k] / self.image_size[1] for x in [j + 0.5]]
|
26 |
+
dense_cy = [y * self.steps[k] / self.image_size[0] for y in [i + 0.5]]
|
27 |
+
for cy, cx in product(dense_cy, dense_cx):
|
28 |
+
anchors += [cx, cy, s_kx, s_ky]
|
29 |
+
|
30 |
+
# back to torch land
|
31 |
+
output = torch.Tensor(anchors).view(-1, 4)
|
32 |
+
if self.clip:
|
33 |
+
output.clamp_(max=1, min=0)
|
34 |
+
return output
|
face_detect/layers/modules/__init__.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from .multibox_loss import MultiBoxLoss
|
2 |
+
|
3 |
+
__all__ = ['MultiBoxLoss']
|
face_detect/layers/modules/multibox_loss.py
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import torch.nn as nn
|
3 |
+
import torch.nn.functional as F
|
4 |
+
from torch.autograd import Variable
|
5 |
+
from utils.box_utils import match, log_sum_exp
|
6 |
+
from data import cfg_mnet
|
7 |
+
GPU = cfg_mnet['gpu_train']
|
8 |
+
|
9 |
+
class MultiBoxLoss(nn.Module):
|
10 |
+
"""SSD Weighted Loss Function
|
11 |
+
Compute Targets:
|
12 |
+
1) Produce Confidence Target Indices by matching ground truth boxes
|
13 |
+
with (default) 'priorboxes' that have jaccard index > threshold parameter
|
14 |
+
(default threshold: 0.5).
|
15 |
+
2) Produce localization target by 'encoding' variance into offsets of ground
|
16 |
+
truth boxes and their matched 'priorboxes'.
|
17 |
+
3) Hard negative mining to filter the excessive number of negative examples
|
18 |
+
that comes with using a large number of default bounding boxes.
|
19 |
+
(default negative:positive ratio 3:1)
|
20 |
+
Objective Loss:
|
21 |
+
L(x,c,l,g) = (Lconf(x, c) + αLloc(x,l,g)) / N
|
22 |
+
Where, Lconf is the CrossEntropy Loss and Lloc is the SmoothL1 Loss
|
23 |
+
weighted by α which is set to 1 by cross val.
|
24 |
+
Args:
|
25 |
+
c: class confidences,
|
26 |
+
l: predicted boxes,
|
27 |
+
g: ground truth boxes
|
28 |
+
N: number of matched default boxes
|
29 |
+
See: https://arxiv.org/pdf/1512.02325.pdf for more details.
|
30 |
+
"""
|
31 |
+
|
32 |
+
def __init__(self, num_classes, overlap_thresh, prior_for_matching, bkg_label, neg_mining, neg_pos, neg_overlap, encode_target):
|
33 |
+
super(MultiBoxLoss, self).__init__()
|
34 |
+
self.num_classes = num_classes
|
35 |
+
self.threshold = overlap_thresh
|
36 |
+
self.background_label = bkg_label
|
37 |
+
self.encode_target = encode_target
|
38 |
+
self.use_prior_for_matching = prior_for_matching
|
39 |
+
self.do_neg_mining = neg_mining
|
40 |
+
self.negpos_ratio = neg_pos
|
41 |
+
self.neg_overlap = neg_overlap
|
42 |
+
self.variance = [0.1, 0.2]
|
43 |
+
|
44 |
+
def forward(self, predictions, priors, targets):
|
45 |
+
"""Multibox Loss
|
46 |
+
Args:
|
47 |
+
predictions (tuple): A tuple containing loc preds, conf preds,
|
48 |
+
and prior boxes from SSD net.
|
49 |
+
conf shape: torch.size(batch_size,num_priors,num_classes)
|
50 |
+
loc shape: torch.size(batch_size,num_priors,4)
|
51 |
+
priors shape: torch.size(num_priors,4)
|
52 |
+
|
53 |
+
ground_truth (tensor): Ground truth boxes and labels for a batch,
|
54 |
+
shape: [batch_size,num_objs,5] (last idx is the label).
|
55 |
+
"""
|
56 |
+
|
57 |
+
loc_data, conf_data, landm_data = predictions
|
58 |
+
priors = priors
|
59 |
+
num = loc_data.size(0)
|
60 |
+
num_priors = (priors.size(0))
|
61 |
+
|
62 |
+
# match priors (default boxes) and ground truth boxes
|
63 |
+
loc_t = torch.Tensor(num, num_priors, 4)
|
64 |
+
landm_t = torch.Tensor(num, num_priors, 10)
|
65 |
+
conf_t = torch.LongTensor(num, num_priors)
|
66 |
+
for idx in range(num):
|
67 |
+
truths = targets[idx][:, :4].data
|
68 |
+
labels = targets[idx][:, -1].data
|
69 |
+
landms = targets[idx][:, 4:14].data
|
70 |
+
defaults = priors.data
|
71 |
+
match(self.threshold, truths, defaults, self.variance, labels, landms, loc_t, conf_t, landm_t, idx)
|
72 |
+
if GPU:
|
73 |
+
loc_t = loc_t.cuda()
|
74 |
+
conf_t = conf_t.cuda()
|
75 |
+
landm_t = landm_t.cuda()
|
76 |
+
|
77 |
+
zeros = torch.tensor(0).cuda()
|
78 |
+
# landm Loss (Smooth L1)
|
79 |
+
# Shape: [batch,num_priors,10]
|
80 |
+
pos1 = conf_t > zeros
|
81 |
+
num_pos_landm = pos1.long().sum(1, keepdim=True)
|
82 |
+
N1 = max(num_pos_landm.data.sum().float(), 1)
|
83 |
+
pos_idx1 = pos1.unsqueeze(pos1.dim()).expand_as(landm_data)
|
84 |
+
landm_p = landm_data[pos_idx1].view(-1, 10)
|
85 |
+
landm_t = landm_t[pos_idx1].view(-1, 10)
|
86 |
+
loss_landm = F.smooth_l1_loss(landm_p, landm_t, reduction='sum')
|
87 |
+
|
88 |
+
|
89 |
+
pos = conf_t != zeros
|
90 |
+
conf_t[pos] = 1
|
91 |
+
|
92 |
+
# Localization Loss (Smooth L1)
|
93 |
+
# Shape: [batch,num_priors,4]
|
94 |
+
pos_idx = pos.unsqueeze(pos.dim()).expand_as(loc_data)
|
95 |
+
loc_p = loc_data[pos_idx].view(-1, 4)
|
96 |
+
loc_t = loc_t[pos_idx].view(-1, 4)
|
97 |
+
loss_l = F.smooth_l1_loss(loc_p, loc_t, reduction='sum')
|
98 |
+
|
99 |
+
# Compute max conf across batch for hard negative mining
|
100 |
+
batch_conf = conf_data.view(-1, self.num_classes)
|
101 |
+
loss_c = log_sum_exp(batch_conf) - batch_conf.gather(1, conf_t.view(-1, 1))
|
102 |
+
|
103 |
+
# Hard Negative Mining
|
104 |
+
loss_c[pos.view(-1, 1)] = 0 # filter out pos boxes for now
|
105 |
+
loss_c = loss_c.view(num, -1)
|
106 |
+
_, loss_idx = loss_c.sort(1, descending=True)
|
107 |
+
_, idx_rank = loss_idx.sort(1)
|
108 |
+
num_pos = pos.long().sum(1, keepdim=True)
|
109 |
+
num_neg = torch.clamp(self.negpos_ratio*num_pos, max=pos.size(1)-1)
|
110 |
+
neg = idx_rank < num_neg.expand_as(idx_rank)
|
111 |
+
|
112 |
+
# Confidence Loss Including Positive and Negative Examples
|
113 |
+
pos_idx = pos.unsqueeze(2).expand_as(conf_data)
|
114 |
+
neg_idx = neg.unsqueeze(2).expand_as(conf_data)
|
115 |
+
conf_p = conf_data[(pos_idx+neg_idx).gt(0)].view(-1,self.num_classes)
|
116 |
+
targets_weighted = conf_t[(pos+neg).gt(0)]
|
117 |
+
loss_c = F.cross_entropy(conf_p, targets_weighted, reduction='sum')
|
118 |
+
|
119 |
+
# Sum of losses: L(x,c,l,g) = (Lconf(x, c) + αLloc(x,l,g)) / N
|
120 |
+
N = max(num_pos.data.sum().float(), 1)
|
121 |
+
loss_l /= N
|
122 |
+
loss_c /= N
|
123 |
+
loss_landm /= N1
|
124 |
+
|
125 |
+
return loss_l, loss_c, loss_landm
|
face_detect/retinaface_detection.py
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@paper: GAN Prior Embedded Network for Blind Face Restoration in the Wild (CVPR2021)
|
3 |
+
@author: yangxy (yangtao9009@gmail.com)
|
4 |
+
'''
|
5 |
+
import os
|
6 |
+
import torch
|
7 |
+
import torch.backends.cudnn as cudnn
|
8 |
+
import numpy as np
|
9 |
+
from data import cfg_re50
|
10 |
+
from layers.functions.prior_box import PriorBox
|
11 |
+
from utils.nms.py_cpu_nms import py_cpu_nms
|
12 |
+
import cv2
|
13 |
+
from facemodels.retinaface import RetinaFace
|
14 |
+
from utils.box_utils import decode, decode_landm
|
15 |
+
import time
|
16 |
+
import torch.nn.functional as F
|
17 |
+
|
18 |
+
|
19 |
+
class RetinaFaceDetection(object):
|
20 |
+
def __init__(self, base_dir, device='cuda', network='RetinaFace-R50'):
|
21 |
+
torch.set_grad_enabled(False)
|
22 |
+
cudnn.benchmark = True
|
23 |
+
self.pretrained_path = os.path.join(base_dir, 'weights', network+'.pth')
|
24 |
+
self.device = device #torch.cuda.current_device()
|
25 |
+
self.cfg = cfg_re50
|
26 |
+
self.net = RetinaFace(cfg=self.cfg, phase='test')
|
27 |
+
self.load_model()
|
28 |
+
self.net = self.net.to(device)
|
29 |
+
|
30 |
+
self.mean = torch.tensor([[[[104]], [[117]], [[123]]]]).to(device)
|
31 |
+
|
32 |
+
def check_keys(self, pretrained_state_dict):
|
33 |
+
ckpt_keys = set(pretrained_state_dict.keys())
|
34 |
+
model_keys = set(self.net.state_dict().keys())
|
35 |
+
used_pretrained_keys = model_keys & ckpt_keys
|
36 |
+
unused_pretrained_keys = ckpt_keys - model_keys
|
37 |
+
missing_keys = model_keys - ckpt_keys
|
38 |
+
assert len(used_pretrained_keys) > 0, 'load NONE from pretrained checkpoint'
|
39 |
+
return True
|
40 |
+
|
41 |
+
def remove_prefix(self, state_dict, prefix):
|
42 |
+
''' Old style model is stored with all names of parameters sharing common prefix 'module.' '''
|
43 |
+
f = lambda x: x.split(prefix, 1)[-1] if x.startswith(prefix) else x
|
44 |
+
return {f(key): value for key, value in state_dict.items()}
|
45 |
+
|
46 |
+
def load_model(self, load_to_cpu=False):
|
47 |
+
#if load_to_cpu:
|
48 |
+
# pretrained_dict = torch.load(self.pretrained_path, map_location=lambda storage, loc: storage)
|
49 |
+
#else:
|
50 |
+
# pretrained_dict = torch.load(self.pretrained_path, map_location=lambda storage, loc: storage.cuda())
|
51 |
+
pretrained_dict = torch.load(self.pretrained_path, map_location=torch.device('cpu'))
|
52 |
+
if "state_dict" in pretrained_dict.keys():
|
53 |
+
pretrained_dict = self.remove_prefix(pretrained_dict['state_dict'], 'module.')
|
54 |
+
else:
|
55 |
+
pretrained_dict = self.remove_prefix(pretrained_dict, 'module.')
|
56 |
+
self.check_keys(pretrained_dict)
|
57 |
+
self.net.load_state_dict(pretrained_dict, strict=False)
|
58 |
+
self.net.eval()
|
59 |
+
|
60 |
+
def detect(self, img_raw, resize=1, confidence_threshold=0.9, nms_threshold=0.4, top_k=5000, keep_top_k=750, save_image=False):
|
61 |
+
img = np.float32(img_raw)
|
62 |
+
|
63 |
+
im_height, im_width = img.shape[:2]
|
64 |
+
ss = 1.0
|
65 |
+
# tricky
|
66 |
+
if max(im_height, im_width) > 1500:
|
67 |
+
ss = 1000.0/max(im_height, im_width)
|
68 |
+
img = cv2.resize(img, (0,0), fx=ss, fy=ss)
|
69 |
+
im_height, im_width = img.shape[:2]
|
70 |
+
|
71 |
+
scale = torch.Tensor([img.shape[1], img.shape[0], img.shape[1], img.shape[0]])
|
72 |
+
img -= (104, 117, 123)
|
73 |
+
img = img.transpose(2, 0, 1)
|
74 |
+
img = torch.from_numpy(img).unsqueeze(0)
|
75 |
+
img = img.to(self.device)
|
76 |
+
scale = scale.to(self.device)
|
77 |
+
|
78 |
+
loc, conf, landms = self.net(img) # forward pass
|
79 |
+
|
80 |
+
priorbox = PriorBox(self.cfg, image_size=(im_height, im_width))
|
81 |
+
priors = priorbox.forward()
|
82 |
+
priors = priors.to(self.device)
|
83 |
+
prior_data = priors.data
|
84 |
+
boxes = decode(loc.data.squeeze(0), prior_data, self.cfg['variance'])
|
85 |
+
boxes = boxes * scale / resize
|
86 |
+
boxes = boxes.cpu().numpy()
|
87 |
+
scores = conf.squeeze(0).data.cpu().numpy()[:, 1]
|
88 |
+
landms = decode_landm(landms.data.squeeze(0), prior_data, self.cfg['variance'])
|
89 |
+
scale1 = torch.Tensor([img.shape[3], img.shape[2], img.shape[3], img.shape[2],
|
90 |
+
img.shape[3], img.shape[2], img.shape[3], img.shape[2],
|
91 |
+
img.shape[3], img.shape[2]])
|
92 |
+
scale1 = scale1.to(self.device)
|
93 |
+
landms = landms * scale1 / resize
|
94 |
+
landms = landms.cpu().numpy()
|
95 |
+
|
96 |
+
# ignore low scores
|
97 |
+
inds = np.where(scores > confidence_threshold)[0]
|
98 |
+
boxes = boxes[inds]
|
99 |
+
landms = landms[inds]
|
100 |
+
scores = scores[inds]
|
101 |
+
|
102 |
+
# keep top-K before NMS
|
103 |
+
order = scores.argsort()[::-1][:top_k]
|
104 |
+
boxes = boxes[order]
|
105 |
+
landms = landms[order]
|
106 |
+
scores = scores[order]
|
107 |
+
|
108 |
+
# do NMS
|
109 |
+
dets = np.hstack((boxes, scores[:, np.newaxis])).astype(np.float32, copy=False)
|
110 |
+
keep = py_cpu_nms(dets, nms_threshold)
|
111 |
+
# keep = nms(dets, nms_threshold,force_cpu=args.cpu)
|
112 |
+
dets = dets[keep, :]
|
113 |
+
landms = landms[keep]
|
114 |
+
|
115 |
+
# keep top-K faster NMS
|
116 |
+
dets = dets[:keep_top_k, :]
|
117 |
+
landms = landms[:keep_top_k, :]
|
118 |
+
|
119 |
+
# sort faces(delete)
|
120 |
+
'''
|
121 |
+
fscores = [det[4] for det in dets]
|
122 |
+
sorted_idx = sorted(range(len(fscores)), key=lambda k:fscores[k], reverse=False) # sort index
|
123 |
+
tmp = [landms[idx] for idx in sorted_idx]
|
124 |
+
landms = np.asarray(tmp)
|
125 |
+
'''
|
126 |
+
|
127 |
+
landms = landms.reshape((-1, 5, 2))
|
128 |
+
landms = landms.transpose((0, 2, 1))
|
129 |
+
landms = landms.reshape(-1, 10, )
|
130 |
+
return dets/ss, landms/ss
|
131 |
+
|
132 |
+
def detect_tensor(self, img, resize=1, confidence_threshold=0.9, nms_threshold=0.4, top_k=5000, keep_top_k=750, save_image=False):
|
133 |
+
im_height, im_width = img.shape[-2:]
|
134 |
+
ss = 1000/max(im_height, im_width)
|
135 |
+
img = F.interpolate(img, scale_factor=ss)
|
136 |
+
im_height, im_width = img.shape[-2:]
|
137 |
+
scale = torch.Tensor([im_width, im_height, im_width, im_height]).to(self.device)
|
138 |
+
img -= self.mean
|
139 |
+
|
140 |
+
loc, conf, landms = self.net(img) # forward pass
|
141 |
+
|
142 |
+
priorbox = PriorBox(self.cfg, image_size=(im_height, im_width))
|
143 |
+
priors = priorbox.forward()
|
144 |
+
priors = priors.to(self.device)
|
145 |
+
prior_data = priors.data
|
146 |
+
boxes = decode(loc.data.squeeze(0), prior_data, self.cfg['variance'])
|
147 |
+
boxes = boxes * scale / resize
|
148 |
+
boxes = boxes.cpu().numpy()
|
149 |
+
scores = conf.squeeze(0).data.cpu().numpy()[:, 1]
|
150 |
+
landms = decode_landm(landms.data.squeeze(0), prior_data, self.cfg['variance'])
|
151 |
+
scale1 = torch.Tensor([img.shape[3], img.shape[2], img.shape[3], img.shape[2],
|
152 |
+
img.shape[3], img.shape[2], img.shape[3], img.shape[2],
|
153 |
+
img.shape[3], img.shape[2]])
|
154 |
+
scale1 = scale1.to(self.device)
|
155 |
+
landms = landms * scale1 / resize
|
156 |
+
landms = landms.cpu().numpy()
|
157 |
+
|
158 |
+
# ignore low scores
|
159 |
+
inds = np.where(scores > confidence_threshold)[0]
|
160 |
+
boxes = boxes[inds]
|
161 |
+
landms = landms[inds]
|
162 |
+
scores = scores[inds]
|
163 |
+
|
164 |
+
# keep top-K before NMS
|
165 |
+
order = scores.argsort()[::-1][:top_k]
|
166 |
+
boxes = boxes[order]
|
167 |
+
landms = landms[order]
|
168 |
+
scores = scores[order]
|
169 |
+
|
170 |
+
# do NMS
|
171 |
+
dets = np.hstack((boxes, scores[:, np.newaxis])).astype(np.float32, copy=False)
|
172 |
+
keep = py_cpu_nms(dets, nms_threshold)
|
173 |
+
# keep = nms(dets, nms_threshold,force_cpu=args.cpu)
|
174 |
+
dets = dets[keep, :]
|
175 |
+
landms = landms[keep]
|
176 |
+
|
177 |
+
# keep top-K faster NMS
|
178 |
+
dets = dets[:keep_top_k, :]
|
179 |
+
landms = landms[:keep_top_k, :]
|
180 |
+
|
181 |
+
# sort faces(delete)
|
182 |
+
'''
|
183 |
+
fscores = [det[4] for det in dets]
|
184 |
+
sorted_idx = sorted(range(len(fscores)), key=lambda k:fscores[k], reverse=False) # sort index
|
185 |
+
tmp = [landms[idx] for idx in sorted_idx]
|
186 |
+
landms = np.asarray(tmp)
|
187 |
+
'''
|
188 |
+
|
189 |
+
landms = landms.reshape((-1, 5, 2))
|
190 |
+
landms = landms.transpose((0, 2, 1))
|
191 |
+
landms = landms.reshape(-1, 10, )
|
192 |
+
return dets/ss, landms/ss
|
face_detect/utils/__init__.py
ADDED
File without changes
|
face_detect/utils/box_utils.py
ADDED
@@ -0,0 +1,330 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import numpy as np
|
3 |
+
|
4 |
+
|
5 |
+
def point_form(boxes):
|
6 |
+
""" Convert prior_boxes to (xmin, ymin, xmax, ymax)
|
7 |
+
representation for comparison to point form ground truth data.
|
8 |
+
Args:
|
9 |
+
boxes: (tensor) center-size default boxes from priorbox layers.
|
10 |
+
Return:
|
11 |
+
boxes: (tensor) Converted xmin, ymin, xmax, ymax form of boxes.
|
12 |
+
"""
|
13 |
+
return torch.cat((boxes[:, :2] - boxes[:, 2:]/2, # xmin, ymin
|
14 |
+
boxes[:, :2] + boxes[:, 2:]/2), 1) # xmax, ymax
|
15 |
+
|
16 |
+
|
17 |
+
def center_size(boxes):
|
18 |
+
""" Convert prior_boxes to (cx, cy, w, h)
|
19 |
+
representation for comparison to center-size form ground truth data.
|
20 |
+
Args:
|
21 |
+
boxes: (tensor) point_form boxes
|
22 |
+
Return:
|
23 |
+
boxes: (tensor) Converted xmin, ymin, xmax, ymax form of boxes.
|
24 |
+
"""
|
25 |
+
return torch.cat((boxes[:, 2:] + boxes[:, :2])/2, # cx, cy
|
26 |
+
boxes[:, 2:] - boxes[:, :2], 1) # w, h
|
27 |
+
|
28 |
+
|
29 |
+
def intersect(box_a, box_b):
|
30 |
+
""" We resize both tensors to [A,B,2] without new malloc:
|
31 |
+
[A,2] -> [A,1,2] -> [A,B,2]
|
32 |
+
[B,2] -> [1,B,2] -> [A,B,2]
|
33 |
+
Then we compute the area of intersect between box_a and box_b.
|
34 |
+
Args:
|
35 |
+
box_a: (tensor) bounding boxes, Shape: [A,4].
|
36 |
+
box_b: (tensor) bounding boxes, Shape: [B,4].
|
37 |
+
Return:
|
38 |
+
(tensor) intersection area, Shape: [A,B].
|
39 |
+
"""
|
40 |
+
A = box_a.size(0)
|
41 |
+
B = box_b.size(0)
|
42 |
+
max_xy = torch.min(box_a[:, 2:].unsqueeze(1).expand(A, B, 2),
|
43 |
+
box_b[:, 2:].unsqueeze(0).expand(A, B, 2))
|
44 |
+
min_xy = torch.max(box_a[:, :2].unsqueeze(1).expand(A, B, 2),
|
45 |
+
box_b[:, :2].unsqueeze(0).expand(A, B, 2))
|
46 |
+
inter = torch.clamp((max_xy - min_xy), min=0)
|
47 |
+
return inter[:, :, 0] * inter[:, :, 1]
|
48 |
+
|
49 |
+
|
50 |
+
def jaccard(box_a, box_b):
|
51 |
+
"""Compute the jaccard overlap of two sets of boxes. The jaccard overlap
|
52 |
+
is simply the intersection over union of two boxes. Here we operate on
|
53 |
+
ground truth boxes and default boxes.
|
54 |
+
E.g.:
|
55 |
+
A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B)
|
56 |
+
Args:
|
57 |
+
box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4]
|
58 |
+
box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4]
|
59 |
+
Return:
|
60 |
+
jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)]
|
61 |
+
"""
|
62 |
+
inter = intersect(box_a, box_b)
|
63 |
+
area_a = ((box_a[:, 2]-box_a[:, 0]) *
|
64 |
+
(box_a[:, 3]-box_a[:, 1])).unsqueeze(1).expand_as(inter) # [A,B]
|
65 |
+
area_b = ((box_b[:, 2]-box_b[:, 0]) *
|
66 |
+
(box_b[:, 3]-box_b[:, 1])).unsqueeze(0).expand_as(inter) # [A,B]
|
67 |
+
union = area_a + area_b - inter
|
68 |
+
return inter / union # [A,B]
|
69 |
+
|
70 |
+
|
71 |
+
def matrix_iou(a, b):
|
72 |
+
"""
|
73 |
+
return iou of a and b, numpy version for data augenmentation
|
74 |
+
"""
|
75 |
+
lt = np.maximum(a[:, np.newaxis, :2], b[:, :2])
|
76 |
+
rb = np.minimum(a[:, np.newaxis, 2:], b[:, 2:])
|
77 |
+
|
78 |
+
area_i = np.prod(rb - lt, axis=2) * (lt < rb).all(axis=2)
|
79 |
+
area_a = np.prod(a[:, 2:] - a[:, :2], axis=1)
|
80 |
+
area_b = np.prod(b[:, 2:] - b[:, :2], axis=1)
|
81 |
+
return area_i / (area_a[:, np.newaxis] + area_b - area_i)
|
82 |
+
|
83 |
+
|
84 |
+
def matrix_iof(a, b):
|
85 |
+
"""
|
86 |
+
return iof of a and b, numpy version for data augenmentation
|
87 |
+
"""
|
88 |
+
lt = np.maximum(a[:, np.newaxis, :2], b[:, :2])
|
89 |
+
rb = np.minimum(a[:, np.newaxis, 2:], b[:, 2:])
|
90 |
+
|
91 |
+
area_i = np.prod(rb - lt, axis=2) * (lt < rb).all(axis=2)
|
92 |
+
area_a = np.prod(a[:, 2:] - a[:, :2], axis=1)
|
93 |
+
return area_i / np.maximum(area_a[:, np.newaxis], 1)
|
94 |
+
|
95 |
+
|
96 |
+
def match(threshold, truths, priors, variances, labels, landms, loc_t, conf_t, landm_t, idx):
|
97 |
+
"""Match each prior box with the ground truth box of the highest jaccard
|
98 |
+
overlap, encode the bounding boxes, then return the matched indices
|
99 |
+
corresponding to both confidence and location preds.
|
100 |
+
Args:
|
101 |
+
threshold: (float) The overlap threshold used when mathing boxes.
|
102 |
+
truths: (tensor) Ground truth boxes, Shape: [num_obj, 4].
|
103 |
+
priors: (tensor) Prior boxes from priorbox layers, Shape: [n_priors,4].
|
104 |
+
variances: (tensor) Variances corresponding to each prior coord,
|
105 |
+
Shape: [num_priors, 4].
|
106 |
+
labels: (tensor) All the class labels for the image, Shape: [num_obj].
|
107 |
+
landms: (tensor) Ground truth landms, Shape [num_obj, 10].
|
108 |
+
loc_t: (tensor) Tensor to be filled w/ endcoded location targets.
|
109 |
+
conf_t: (tensor) Tensor to be filled w/ matched indices for conf preds.
|
110 |
+
landm_t: (tensor) Tensor to be filled w/ endcoded landm targets.
|
111 |
+
idx: (int) current batch index
|
112 |
+
Return:
|
113 |
+
The matched indices corresponding to 1)location 2)confidence 3)landm preds.
|
114 |
+
"""
|
115 |
+
# jaccard index
|
116 |
+
overlaps = jaccard(
|
117 |
+
truths,
|
118 |
+
point_form(priors)
|
119 |
+
)
|
120 |
+
# (Bipartite Matching)
|
121 |
+
# [1,num_objects] best prior for each ground truth
|
122 |
+
best_prior_overlap, best_prior_idx = overlaps.max(1, keepdim=True)
|
123 |
+
|
124 |
+
# ignore hard gt
|
125 |
+
valid_gt_idx = best_prior_overlap[:, 0] >= 0.2
|
126 |
+
best_prior_idx_filter = best_prior_idx[valid_gt_idx, :]
|
127 |
+
if best_prior_idx_filter.shape[0] <= 0:
|
128 |
+
loc_t[idx] = 0
|
129 |
+
conf_t[idx] = 0
|
130 |
+
return
|
131 |
+
|
132 |
+
# [1,num_priors] best ground truth for each prior
|
133 |
+
best_truth_overlap, best_truth_idx = overlaps.max(0, keepdim=True)
|
134 |
+
best_truth_idx.squeeze_(0)
|
135 |
+
best_truth_overlap.squeeze_(0)
|
136 |
+
best_prior_idx.squeeze_(1)
|
137 |
+
best_prior_idx_filter.squeeze_(1)
|
138 |
+
best_prior_overlap.squeeze_(1)
|
139 |
+
best_truth_overlap.index_fill_(0, best_prior_idx_filter, 2) # ensure best prior
|
140 |
+
# TODO refactor: index best_prior_idx with long tensor
|
141 |
+
# ensure every gt matches with its prior of max overlap
|
142 |
+
for j in range(best_prior_idx.size(0)): # 判别此anchor是预测哪一个boxes
|
143 |
+
best_truth_idx[best_prior_idx[j]] = j
|
144 |
+
matches = truths[best_truth_idx] # Shape: [num_priors,4] 此处为每一个anchor对应的bbox取出来
|
145 |
+
conf = labels[best_truth_idx] # Shape: [num_priors] 此处为每一个anchor对应的label取出来
|
146 |
+
conf[best_truth_overlap < threshold] = 0 # label as background overlap<0.35的全部作为负样本
|
147 |
+
loc = encode(matches, priors, variances)
|
148 |
+
|
149 |
+
matches_landm = landms[best_truth_idx]
|
150 |
+
landm = encode_landm(matches_landm, priors, variances)
|
151 |
+
loc_t[idx] = loc # [num_priors,4] encoded offsets to learn
|
152 |
+
conf_t[idx] = conf # [num_priors] top class label for each prior
|
153 |
+
landm_t[idx] = landm
|
154 |
+
|
155 |
+
|
156 |
+
def encode(matched, priors, variances):
|
157 |
+
"""Encode the variances from the priorbox layers into the ground truth boxes
|
158 |
+
we have matched (based on jaccard overlap) with the prior boxes.
|
159 |
+
Args:
|
160 |
+
matched: (tensor) Coords of ground truth for each prior in point-form
|
161 |
+
Shape: [num_priors, 4].
|
162 |
+
priors: (tensor) Prior boxes in center-offset form
|
163 |
+
Shape: [num_priors,4].
|
164 |
+
variances: (list[float]) Variances of priorboxes
|
165 |
+
Return:
|
166 |
+
encoded boxes (tensor), Shape: [num_priors, 4]
|
167 |
+
"""
|
168 |
+
|
169 |
+
# dist b/t match center and prior's center
|
170 |
+
g_cxcy = (matched[:, :2] + matched[:, 2:])/2 - priors[:, :2]
|
171 |
+
# encode variance
|
172 |
+
g_cxcy /= (variances[0] * priors[:, 2:])
|
173 |
+
# match wh / prior wh
|
174 |
+
g_wh = (matched[:, 2:] - matched[:, :2]) / priors[:, 2:]
|
175 |
+
g_wh = torch.log(g_wh) / variances[1]
|
176 |
+
# return target for smooth_l1_loss
|
177 |
+
return torch.cat([g_cxcy, g_wh], 1) # [num_priors,4]
|
178 |
+
|
179 |
+
def encode_landm(matched, priors, variances):
|
180 |
+
"""Encode the variances from the priorbox layers into the ground truth boxes
|
181 |
+
we have matched (based on jaccard overlap) with the prior boxes.
|
182 |
+
Args:
|
183 |
+
matched: (tensor) Coords of ground truth for each prior in point-form
|
184 |
+
Shape: [num_priors, 10].
|
185 |
+
priors: (tensor) Prior boxes in center-offset form
|
186 |
+
Shape: [num_priors,4].
|
187 |
+
variances: (list[float]) Variances of priorboxes
|
188 |
+
Return:
|
189 |
+
encoded landm (tensor), Shape: [num_priors, 10]
|
190 |
+
"""
|
191 |
+
|
192 |
+
# dist b/t match center and prior's center
|
193 |
+
matched = torch.reshape(matched, (matched.size(0), 5, 2))
|
194 |
+
priors_cx = priors[:, 0].unsqueeze(1).expand(matched.size(0), 5).unsqueeze(2)
|
195 |
+
priors_cy = priors[:, 1].unsqueeze(1).expand(matched.size(0), 5).unsqueeze(2)
|
196 |
+
priors_w = priors[:, 2].unsqueeze(1).expand(matched.size(0), 5).unsqueeze(2)
|
197 |
+
priors_h = priors[:, 3].unsqueeze(1).expand(matched.size(0), 5).unsqueeze(2)
|
198 |
+
priors = torch.cat([priors_cx, priors_cy, priors_w, priors_h], dim=2)
|
199 |
+
g_cxcy = matched[:, :, :2] - priors[:, :, :2]
|
200 |
+
# encode variance
|
201 |
+
g_cxcy /= (variances[0] * priors[:, :, 2:])
|
202 |
+
# g_cxcy /= priors[:, :, 2:]
|
203 |
+
g_cxcy = g_cxcy.reshape(g_cxcy.size(0), -1)
|
204 |
+
# return target for smooth_l1_loss
|
205 |
+
return g_cxcy
|
206 |
+
|
207 |
+
|
208 |
+
# Adapted from https://github.com/Hakuyume/chainer-ssd
|
209 |
+
def decode(loc, priors, variances):
|
210 |
+
"""Decode locations from predictions using priors to undo
|
211 |
+
the encoding we did for offset regression at train time.
|
212 |
+
Args:
|
213 |
+
loc (tensor): location predictions for loc layers,
|
214 |
+
Shape: [num_priors,4]
|
215 |
+
priors (tensor): Prior boxes in center-offset form.
|
216 |
+
Shape: [num_priors,4].
|
217 |
+
variances: (list[float]) Variances of priorboxes
|
218 |
+
Return:
|
219 |
+
decoded bounding box predictions
|
220 |
+
"""
|
221 |
+
|
222 |
+
boxes = torch.cat((
|
223 |
+
priors[:, :2] + loc[:, :2] * variances[0] * priors[:, 2:],
|
224 |
+
priors[:, 2:] * torch.exp(loc[:, 2:] * variances[1])), 1)
|
225 |
+
boxes[:, :2] -= boxes[:, 2:] / 2
|
226 |
+
boxes[:, 2:] += boxes[:, :2]
|
227 |
+
return boxes
|
228 |
+
|
229 |
+
def decode_landm(pre, priors, variances):
|
230 |
+
"""Decode landm from predictions using priors to undo
|
231 |
+
the encoding we did for offset regression at train time.
|
232 |
+
Args:
|
233 |
+
pre (tensor): landm predictions for loc layers,
|
234 |
+
Shape: [num_priors,10]
|
235 |
+
priors (tensor): Prior boxes in center-offset form.
|
236 |
+
Shape: [num_priors,4].
|
237 |
+
variances: (list[float]) Variances of priorboxes
|
238 |
+
Return:
|
239 |
+
decoded landm predictions
|
240 |
+
"""
|
241 |
+
landms = torch.cat((priors[:, :2] + pre[:, :2] * variances[0] * priors[:, 2:],
|
242 |
+
priors[:, :2] + pre[:, 2:4] * variances[0] * priors[:, 2:],
|
243 |
+
priors[:, :2] + pre[:, 4:6] * variances[0] * priors[:, 2:],
|
244 |
+
priors[:, :2] + pre[:, 6:8] * variances[0] * priors[:, 2:],
|
245 |
+
priors[:, :2] + pre[:, 8:10] * variances[0] * priors[:, 2:],
|
246 |
+
), dim=1)
|
247 |
+
return landms
|
248 |
+
|
249 |
+
|
250 |
+
def log_sum_exp(x):
|
251 |
+
"""Utility function for computing log_sum_exp while determining
|
252 |
+
This will be used to determine unaveraged confidence loss across
|
253 |
+
all examples in a batch.
|
254 |
+
Args:
|
255 |
+
x (Variable(tensor)): conf_preds from conf layers
|
256 |
+
"""
|
257 |
+
x_max = x.data.max()
|
258 |
+
return torch.log(torch.sum(torch.exp(x-x_max), 1, keepdim=True)) + x_max
|
259 |
+
|
260 |
+
|
261 |
+
# Original author: Francisco Massa:
|
262 |
+
# https://github.com/fmassa/object-detection.torch
|
263 |
+
# Ported to PyTorch by Max deGroot (02/01/2017)
|
264 |
+
def nms(boxes, scores, overlap=0.5, top_k=200):
|
265 |
+
"""Apply non-maximum suppression at test time to avoid detecting too many
|
266 |
+
overlapping bounding boxes for a given object.
|
267 |
+
Args:
|
268 |
+
boxes: (tensor) The location preds for the img, Shape: [num_priors,4].
|
269 |
+
scores: (tensor) The class predscores for the img, Shape:[num_priors].
|
270 |
+
overlap: (float) The overlap thresh for suppressing unnecessary boxes.
|
271 |
+
top_k: (int) The Maximum number of box preds to consider.
|
272 |
+
Return:
|
273 |
+
The indices of the kept boxes with respect to num_priors.
|
274 |
+
"""
|
275 |
+
|
276 |
+
keep = torch.Tensor(scores.size(0)).fill_(0).long()
|
277 |
+
if boxes.numel() == 0:
|
278 |
+
return keep
|
279 |
+
x1 = boxes[:, 0]
|
280 |
+
y1 = boxes[:, 1]
|
281 |
+
x2 = boxes[:, 2]
|
282 |
+
y2 = boxes[:, 3]
|
283 |
+
area = torch.mul(x2 - x1, y2 - y1)
|
284 |
+
v, idx = scores.sort(0) # sort in ascending order
|
285 |
+
# I = I[v >= 0.01]
|
286 |
+
idx = idx[-top_k:] # indices of the top-k largest vals
|
287 |
+
xx1 = boxes.new()
|
288 |
+
yy1 = boxes.new()
|
289 |
+
xx2 = boxes.new()
|
290 |
+
yy2 = boxes.new()
|
291 |
+
w = boxes.new()
|
292 |
+
h = boxes.new()
|
293 |
+
|
294 |
+
# keep = torch.Tensor()
|
295 |
+
count = 0
|
296 |
+
while idx.numel() > 0:
|
297 |
+
i = idx[-1] # index of current largest val
|
298 |
+
# keep.append(i)
|
299 |
+
keep[count] = i
|
300 |
+
count += 1
|
301 |
+
if idx.size(0) == 1:
|
302 |
+
break
|
303 |
+
idx = idx[:-1] # remove kept element from view
|
304 |
+
# load bboxes of next highest vals
|
305 |
+
torch.index_select(x1, 0, idx, out=xx1)
|
306 |
+
torch.index_select(y1, 0, idx, out=yy1)
|
307 |
+
torch.index_select(x2, 0, idx, out=xx2)
|
308 |
+
torch.index_select(y2, 0, idx, out=yy2)
|
309 |
+
# store element-wise max with next highest score
|
310 |
+
xx1 = torch.clamp(xx1, min=x1[i])
|
311 |
+
yy1 = torch.clamp(yy1, min=y1[i])
|
312 |
+
xx2 = torch.clamp(xx2, max=x2[i])
|
313 |
+
yy2 = torch.clamp(yy2, max=y2[i])
|
314 |
+
w.resize_as_(xx2)
|
315 |
+
h.resize_as_(yy2)
|
316 |
+
w = xx2 - xx1
|
317 |
+
h = yy2 - yy1
|
318 |
+
# check sizes of xx1 and xx2.. after each iteration
|
319 |
+
w = torch.clamp(w, min=0.0)
|
320 |
+
h = torch.clamp(h, min=0.0)
|
321 |
+
inter = w*h
|
322 |
+
# IoU = i / (area(a) + area(b) - i)
|
323 |
+
rem_areas = torch.index_select(area, 0, idx) # load remaining areas)
|
324 |
+
union = (rem_areas - inter) + area[i]
|
325 |
+
IoU = inter/union # store result in iou
|
326 |
+
# keep only elements with an IoU <= overlap
|
327 |
+
idx = idx[IoU.le(overlap)]
|
328 |
+
return keep, count
|
329 |
+
|
330 |
+
|
face_detect/utils/nms/__init__.py
ADDED
File without changes
|
face_detect/utils/nms/py_cpu_nms.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# --------------------------------------------------------
|
2 |
+
# Fast R-CNN
|
3 |
+
# Copyright (c) 2015 Microsoft
|
4 |
+
# Licensed under The MIT License [see LICENSE for details]
|
5 |
+
# Written by Ross Girshick
|
6 |
+
# --------------------------------------------------------
|
7 |
+
|
8 |
+
import numpy as np
|
9 |
+
|
10 |
+
def py_cpu_nms(dets, thresh):
|
11 |
+
"""Pure Python NMS baseline."""
|
12 |
+
x1 = dets[:, 0]
|
13 |
+
y1 = dets[:, 1]
|
14 |
+
x2 = dets[:, 2]
|
15 |
+
y2 = dets[:, 3]
|
16 |
+
scores = dets[:, 4]
|
17 |
+
|
18 |
+
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
|
19 |
+
order = scores.argsort()[::-1]
|
20 |
+
|
21 |
+
keep = []
|
22 |
+
while order.size > 0:
|
23 |
+
i = order[0]
|
24 |
+
keep.append(i)
|
25 |
+
xx1 = np.maximum(x1[i], x1[order[1:]])
|
26 |
+
yy1 = np.maximum(y1[i], y1[order[1:]])
|
27 |
+
xx2 = np.minimum(x2[i], x2[order[1:]])
|
28 |
+
yy2 = np.minimum(y2[i], y2[order[1:]])
|
29 |
+
|
30 |
+
w = np.maximum(0.0, xx2 - xx1 + 1)
|
31 |
+
h = np.maximum(0.0, yy2 - yy1 + 1)
|
32 |
+
inter = w * h
|
33 |
+
ovr = inter / (areas[i] + areas[order[1:]] - inter)
|
34 |
+
|
35 |
+
inds = np.where(ovr <= thresh)[0]
|
36 |
+
order = order[inds + 1]
|
37 |
+
|
38 |
+
return keep
|
face_detect/utils/timer.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# --------------------------------------------------------
|
2 |
+
# Fast R-CNN
|
3 |
+
# Copyright (c) 2015 Microsoft
|
4 |
+
# Licensed under The MIT License [see LICENSE for details]
|
5 |
+
# Written by Ross Girshick
|
6 |
+
# --------------------------------------------------------
|
7 |
+
|
8 |
+
import time
|
9 |
+
|
10 |
+
|
11 |
+
class Timer(object):
|
12 |
+
"""A simple timer."""
|
13 |
+
def __init__(self):
|
14 |
+
self.total_time = 0.
|
15 |
+
self.calls = 0
|
16 |
+
self.start_time = 0.
|
17 |
+
self.diff = 0.
|
18 |
+
self.average_time = 0.
|
19 |
+
|
20 |
+
def tic(self):
|
21 |
+
# using time.time instead of time.clock because time time.clock
|
22 |
+
# does not normalize for multithreading
|
23 |
+
self.start_time = time.time()
|
24 |
+
|
25 |
+
def toc(self, average=True):
|
26 |
+
self.diff = time.time() - self.start_time
|
27 |
+
self.total_time += self.diff
|
28 |
+
self.calls += 1
|
29 |
+
self.average_time = self.total_time / self.calls
|
30 |
+
if average:
|
31 |
+
return self.average_time
|
32 |
+
else:
|
33 |
+
return self.diff
|
34 |
+
|
35 |
+
def clear(self):
|
36 |
+
self.total_time = 0.
|
37 |
+
self.calls = 0
|
38 |
+
self.start_time = 0.
|
39 |
+
self.diff = 0.
|
40 |
+
self.average_time = 0.
|
face_enhancement.py
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@paper: GAN Prior Embedded Network for Blind Face Restoration in the Wild (CVPR2021)
|
3 |
+
@author: yangxy (yangtao9009@gmail.com)
|
4 |
+
'''
|
5 |
+
import os
|
6 |
+
import cv2
|
7 |
+
import glob
|
8 |
+
import time
|
9 |
+
import argparse
|
10 |
+
import numpy as np
|
11 |
+
from PIL import Image
|
12 |
+
import __init_paths
|
13 |
+
from face_detect.retinaface_detection import RetinaFaceDetection
|
14 |
+
from face_parse.face_parsing import FaceParse
|
15 |
+
from face_model.face_gan import FaceGAN
|
16 |
+
from sr_model.real_esrnet import RealESRNet
|
17 |
+
from align_faces import warp_and_crop_face, get_reference_facial_points
|
18 |
+
|
19 |
+
class FaceEnhancement(object):
|
20 |
+
def __init__(self, base_dir='./', size=512, model=None, use_sr=True, sr_model=None, channel_multiplier=2, narrow=1, key=None, device='cuda'):
|
21 |
+
self.facedetector = RetinaFaceDetection(base_dir, device)
|
22 |
+
self.facegan = FaceGAN(base_dir, size, model, channel_multiplier, narrow, key, device=device)
|
23 |
+
self.srmodel = RealESRNet(base_dir, sr_model, device=device)
|
24 |
+
self.faceparser = FaceParse(base_dir, device=device)
|
25 |
+
self.use_sr = use_sr
|
26 |
+
self.size = size
|
27 |
+
self.threshold = 0.9
|
28 |
+
|
29 |
+
# the mask for pasting restored faces back
|
30 |
+
self.mask = np.zeros((512, 512), np.float32)
|
31 |
+
cv2.rectangle(self.mask, (26, 26), (486, 486), (1, 1, 1), -1, cv2.LINE_AA)
|
32 |
+
self.mask = cv2.GaussianBlur(self.mask, (101, 101), 11)
|
33 |
+
self.mask = cv2.GaussianBlur(self.mask, (101, 101), 11)
|
34 |
+
|
35 |
+
self.kernel = np.array((
|
36 |
+
[0.0625, 0.125, 0.0625],
|
37 |
+
[0.125, 0.25, 0.125],
|
38 |
+
[0.0625, 0.125, 0.0625]), dtype="float32")
|
39 |
+
|
40 |
+
# get the reference 5 landmarks position in the crop settings
|
41 |
+
default_square = True
|
42 |
+
inner_padding_factor = 0.25
|
43 |
+
outer_padding = (0, 0)
|
44 |
+
self.reference_5pts = get_reference_facial_points(
|
45 |
+
(self.size, self.size), inner_padding_factor, outer_padding, default_square)
|
46 |
+
|
47 |
+
def mask_postprocess(self, mask, thres=20):
|
48 |
+
mask[:thres, :] = 0; mask[-thres:, :] = 0
|
49 |
+
mask[:, :thres] = 0; mask[:, -thres:] = 0
|
50 |
+
mask = cv2.GaussianBlur(mask, (101, 101), 11)
|
51 |
+
mask = cv2.GaussianBlur(mask, (101, 101), 11)
|
52 |
+
return mask.astype(np.float32)
|
53 |
+
|
54 |
+
def process(self, img):
|
55 |
+
if self.use_sr:
|
56 |
+
img_sr = self.srmodel.process(img)
|
57 |
+
if img_sr is not None:
|
58 |
+
img = cv2.resize(img, img_sr.shape[:2][::-1])
|
59 |
+
|
60 |
+
facebs, landms = self.facedetector.detect(img)
|
61 |
+
|
62 |
+
orig_faces, enhanced_faces = [], []
|
63 |
+
height, width = img.shape[:2]
|
64 |
+
full_mask = np.zeros((height, width), dtype=np.float32)
|
65 |
+
full_img = np.zeros(img.shape, dtype=np.uint8)
|
66 |
+
|
67 |
+
for i, (faceb, facial5points) in enumerate(zip(facebs, landms)):
|
68 |
+
if faceb[4]<self.threshold: continue
|
69 |
+
fh, fw = (faceb[3]-faceb[1]), (faceb[2]-faceb[0])
|
70 |
+
|
71 |
+
facial5points = np.reshape(facial5points, (2, 5))
|
72 |
+
|
73 |
+
of, tfm_inv = warp_and_crop_face(img, facial5points, reference_pts=self.reference_5pts, crop_size=(self.size, self.size))
|
74 |
+
|
75 |
+
# enhance the face
|
76 |
+
ef = self.facegan.process(of)
|
77 |
+
|
78 |
+
orig_faces.append(of)
|
79 |
+
enhanced_faces.append(ef)
|
80 |
+
|
81 |
+
#tmp_mask = self.mask
|
82 |
+
tmp_mask = self.mask_postprocess(self.faceparser.process(ef)[0]/255.)
|
83 |
+
tmp_mask = cv2.resize(tmp_mask, ef.shape[:2])
|
84 |
+
tmp_mask = cv2.warpAffine(tmp_mask, tfm_inv, (width, height), flags=3)
|
85 |
+
|
86 |
+
if min(fh, fw)<100: # gaussian filter for small faces
|
87 |
+
ef = cv2.filter2D(ef, -1, self.kernel)
|
88 |
+
|
89 |
+
tmp_img = cv2.warpAffine(ef, tfm_inv, (width, height), flags=3)
|
90 |
+
|
91 |
+
mask = tmp_mask - full_mask
|
92 |
+
full_mask[np.where(mask>0)] = tmp_mask[np.where(mask>0)]
|
93 |
+
full_img[np.where(mask>0)] = tmp_img[np.where(mask>0)]
|
94 |
+
|
95 |
+
full_mask = full_mask[:, :, np.newaxis]
|
96 |
+
if self.use_sr and img_sr is not None:
|
97 |
+
img = cv2.convertScaleAbs(img_sr*(1-full_mask) + full_img*full_mask)
|
98 |
+
else:
|
99 |
+
img = cv2.convertScaleAbs(img*(1-full_mask) + full_img*full_mask)
|
100 |
+
|
101 |
+
return img, orig_faces, enhanced_faces
|
102 |
+
|
103 |
+
|
104 |
+
if __name__=='__main__':
|
105 |
+
parser = argparse.ArgumentParser()
|
106 |
+
parser.add_argument('--model', type=str, default='GPEN-BFR-512', help='GPEN model')
|
107 |
+
parser.add_argument('--key', type=str, default=None, help='key of GPEN model')
|
108 |
+
parser.add_argument('--size', type=int, default=512, help='resolution of GPEN')
|
109 |
+
parser.add_argument('--channel_multiplier', type=int, default=2, help='channel multiplier of GPEN')
|
110 |
+
parser.add_argument('--narrow', type=float, default=1, help='channel narrow scale')
|
111 |
+
parser.add_argument('--use_sr', action='store_true', help='use sr or not')
|
112 |
+
parser.add_argument('--use_cuda', action='store_true', help='use cuda or not')
|
113 |
+
parser.add_argument('--sr_model', type=str, default='rrdb_realesrnet_psnr', help='SR model')
|
114 |
+
parser.add_argument('--sr_scale', type=int, default=2, help='SR scale')
|
115 |
+
parser.add_argument('--indir', type=str, default='examples/imgs', help='input folder')
|
116 |
+
parser.add_argument('--outdir', type=str, default='results/outs-BFR', help='output folder')
|
117 |
+
args = parser.parse_args()
|
118 |
+
|
119 |
+
#model = {'name':'GPEN-BFR-512', 'size':512, 'channel_multiplier':2, 'narrow':1}
|
120 |
+
#model = {'name':'GPEN-BFR-256', 'size':256, 'channel_multiplier':1, 'narrow':0.5}
|
121 |
+
|
122 |
+
os.makedirs(args.outdir, exist_ok=True)
|
123 |
+
|
124 |
+
faceenhancer = FaceEnhancement(size=args.size, model=args.model, use_sr=args.use_sr, sr_model=args.sr_model, channel_multiplier=args.channel_multiplier, narrow=args.narrow, key=args.key, device='cuda' if args.use_cuda else 'cpu')
|
125 |
+
|
126 |
+
files = sorted(glob.glob(os.path.join(args.indir, '*.*g')))
|
127 |
+
for n, file in enumerate(files[:]):
|
128 |
+
filename = os.path.basename(file)
|
129 |
+
|
130 |
+
im = cv2.imread(file, cv2.IMREAD_COLOR) # BGR
|
131 |
+
if not isinstance(im, np.ndarray): print(filename, 'error'); continue
|
132 |
+
#im = cv2.resize(im, (0,0), fx=2, fy=2) # optional
|
133 |
+
|
134 |
+
img, orig_faces, enhanced_faces = faceenhancer.process(im)
|
135 |
+
|
136 |
+
im = cv2.resize(im, img.shape[:2][::-1])
|
137 |
+
cv2.imwrite(os.path.join(args.outdir, '.'.join(filename.split('.')[:-1])+'_COMP.jpg'), np.hstack((im, img)))
|
138 |
+
cv2.imwrite(os.path.join(args.outdir, '.'.join(filename.split('.')[:-1])+'_GPEN.jpg'), img)
|
139 |
+
|
140 |
+
for m, (ef, of) in enumerate(zip(enhanced_faces, orig_faces)):
|
141 |
+
of = cv2.resize(of, ef.shape[:2])
|
142 |
+
cv2.imwrite(os.path.join(args.outdir, '.'.join(filename.split('.')[:-1])+'_face%02d'%m+'.jpg'), np.hstack((of, ef)))
|
143 |
+
|
144 |
+
if n%10==0: print(n, filename)
|
145 |
+
|
face_inpainting.py
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@paper: GAN Prior Embedded Network for Blind Face Restoration in the Wild (CVPR2021)
|
3 |
+
@author: yangxy (yangtao9009@gmail.com)
|
4 |
+
'''
|
5 |
+
import os
|
6 |
+
import cv2
|
7 |
+
import glob
|
8 |
+
import time
|
9 |
+
import math
|
10 |
+
import numpy as np
|
11 |
+
from PIL import Image, ImageDraw
|
12 |
+
import __init_paths
|
13 |
+
from face_model.face_gan import FaceGAN
|
14 |
+
|
15 |
+
# modified by yangxy
|
16 |
+
def brush_stroke_mask(img, color=(255,255,255)):
|
17 |
+
min_num_vertex = 8
|
18 |
+
max_num_vertex = 28
|
19 |
+
mean_angle = 2*math.pi / 5
|
20 |
+
angle_range = 2*math.pi / 15
|
21 |
+
min_width = 12
|
22 |
+
max_width = 80
|
23 |
+
def generate_mask(H, W, img=None):
|
24 |
+
average_radius = math.sqrt(H*H+W*W) / 8
|
25 |
+
mask = Image.new('RGB', (W, H), 0)
|
26 |
+
if img is not None: mask = img #Image.fromarray(img)
|
27 |
+
|
28 |
+
for _ in range(np.random.randint(1, 4)):
|
29 |
+
num_vertex = np.random.randint(min_num_vertex, max_num_vertex)
|
30 |
+
angle_min = mean_angle - np.random.uniform(0, angle_range)
|
31 |
+
angle_max = mean_angle + np.random.uniform(0, angle_range)
|
32 |
+
angles = []
|
33 |
+
vertex = []
|
34 |
+
for i in range(num_vertex):
|
35 |
+
if i % 2 == 0:
|
36 |
+
angles.append(2*math.pi - np.random.uniform(angle_min, angle_max))
|
37 |
+
else:
|
38 |
+
angles.append(np.random.uniform(angle_min, angle_max))
|
39 |
+
|
40 |
+
h, w = mask.size
|
41 |
+
vertex.append((int(np.random.randint(0, w)), int(np.random.randint(0, h))))
|
42 |
+
for i in range(num_vertex):
|
43 |
+
r = np.clip(
|
44 |
+
np.random.normal(loc=average_radius, scale=average_radius//2),
|
45 |
+
0, 2*average_radius)
|
46 |
+
new_x = np.clip(vertex[-1][0] + r * math.cos(angles[i]), 0, w)
|
47 |
+
new_y = np.clip(vertex[-1][1] + r * math.sin(angles[i]), 0, h)
|
48 |
+
vertex.append((int(new_x), int(new_y)))
|
49 |
+
|
50 |
+
draw = ImageDraw.Draw(mask)
|
51 |
+
width = int(np.random.uniform(min_width, max_width))
|
52 |
+
draw.line(vertex, fill=color, width=width)
|
53 |
+
for v in vertex:
|
54 |
+
draw.ellipse((v[0] - width//2,
|
55 |
+
v[1] - width//2,
|
56 |
+
v[0] + width//2,
|
57 |
+
v[1] + width//2),
|
58 |
+
fill=color)
|
59 |
+
|
60 |
+
return mask
|
61 |
+
|
62 |
+
width, height = img.size
|
63 |
+
mask = generate_mask(height, width, img)
|
64 |
+
return mask
|
65 |
+
|
66 |
+
class FaceInpainting(object):
|
67 |
+
def __init__(self, base_dir='./', size=1024, model=None, channel_multiplier=2):
|
68 |
+
self.facegan = FaceGAN(base_dir, size, model, channel_multiplier)
|
69 |
+
|
70 |
+
# make sure the face image is well aligned. Please refer to face_enhancement.py
|
71 |
+
def process(self, brokenf):
|
72 |
+
# complete the face
|
73 |
+
out = self.facegan.process(brokenf)
|
74 |
+
|
75 |
+
return out
|
76 |
+
|
77 |
+
if __name__=='__main__':
|
78 |
+
model = {'name':'GPEN-Inpainting-1024', 'size':1024}
|
79 |
+
|
80 |
+
indir = 'examples/ffhq-10'
|
81 |
+
outdir = 'examples/outs-inpainting'
|
82 |
+
os.makedirs(outdir, exist_ok=True)
|
83 |
+
|
84 |
+
faceinpainter = FaceInpainting(size=model['size'], model=model['name'], channel_multiplier=2)
|
85 |
+
|
86 |
+
files = sorted(glob.glob(os.path.join(indir, '*.*g')))
|
87 |
+
for n, file in enumerate(files[:]):
|
88 |
+
filename = os.path.basename(file)
|
89 |
+
|
90 |
+
originf = cv2.imread(file, cv2.IMREAD_COLOR)
|
91 |
+
|
92 |
+
brokenf = np.asarray(brush_stroke_mask(Image.fromarray(originf)))
|
93 |
+
|
94 |
+
completef = faceinpainter.process(brokenf)
|
95 |
+
|
96 |
+
originf = cv2.resize(originf, completef.shape[:2])
|
97 |
+
brokenf = cv2.resize(brokenf, completef.shape[:2])
|
98 |
+
cv2.imwrite(os.path.join(outdir, '.'.join(filename.split('.')[:-1])+'.jpg'), np.hstack((brokenf, completef, originf)))
|
99 |
+
|
100 |
+
if n%10==0: print(n, file)
|
101 |
+
|
face_model/face_gan.py
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@paper: GAN Prior Embedded Network for Blind Face Restoration in the Wild (CVPR2021)
|
3 |
+
@author: yangxy (yangtao9009@gmail.com)
|
4 |
+
'''
|
5 |
+
import torch
|
6 |
+
import os
|
7 |
+
import cv2
|
8 |
+
import glob
|
9 |
+
import numpy as np
|
10 |
+
from torch import nn
|
11 |
+
import torch.nn.functional as F
|
12 |
+
from torchvision import transforms, utils
|
13 |
+
from gpen_model import FullGenerator
|
14 |
+
|
15 |
+
class FaceGAN(object):
|
16 |
+
def __init__(self, base_dir='./', size=512, model=None, channel_multiplier=2, narrow=1, key=None, is_norm=True, device='cuda'):
|
17 |
+
self.mfile = os.path.join(base_dir, 'weights', model+'.pth')
|
18 |
+
self.n_mlp = 8
|
19 |
+
self.device = device
|
20 |
+
self.is_norm = is_norm
|
21 |
+
self.resolution = size
|
22 |
+
self.key = key
|
23 |
+
self.load_model(channel_multiplier, narrow)
|
24 |
+
|
25 |
+
def load_model(self, channel_multiplier=2, narrow=1):
|
26 |
+
self.model = FullGenerator(self.resolution, 512, self.n_mlp, channel_multiplier, narrow=narrow, device=self.device)
|
27 |
+
pretrained_dict = torch.load(self.mfile, map_location=torch.device('cpu'))
|
28 |
+
if self.key is not None: pretrained_dict = pretrained_dict[self.key]
|
29 |
+
self.model.load_state_dict(pretrained_dict)
|
30 |
+
self.model.to(self.device)
|
31 |
+
self.model.eval()
|
32 |
+
|
33 |
+
def process(self, img):
|
34 |
+
img = cv2.resize(img, (self.resolution, self.resolution))
|
35 |
+
img_t = self.img2tensor(img)
|
36 |
+
|
37 |
+
with torch.no_grad():
|
38 |
+
out, __ = self.model(img_t)
|
39 |
+
|
40 |
+
out = self.tensor2img(out)
|
41 |
+
|
42 |
+
return out
|
43 |
+
|
44 |
+
def img2tensor(self, img):
|
45 |
+
img_t = torch.from_numpy(img).to(self.device)/255.
|
46 |
+
if self.is_norm:
|
47 |
+
img_t = (img_t - 0.5) / 0.5
|
48 |
+
img_t = img_t.permute(2, 0, 1).unsqueeze(0).flip(1) # BGR->RGB
|
49 |
+
return img_t
|
50 |
+
|
51 |
+
def tensor2img(self, img_t, pmax=255.0, imtype=np.uint8):
|
52 |
+
if self.is_norm:
|
53 |
+
img_t = img_t * 0.5 + 0.5
|
54 |
+
img_t = img_t.squeeze(0).permute(1, 2, 0).flip(2) # RGB->BGR
|
55 |
+
img_np = np.clip(img_t.float().cpu().numpy(), 0, 1) * pmax
|
56 |
+
|
57 |
+
return img_np.astype(imtype)
|
face_model/gpen_model.py
ADDED
@@ -0,0 +1,747 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@paper: GAN Prior Embedded Network for Blind Face Restoration in the Wild (CVPR2021)
|
3 |
+
@author: yangxy (yangtao9009@gmail.com)
|
4 |
+
'''
|
5 |
+
import math
|
6 |
+
import random
|
7 |
+
import functools
|
8 |
+
import operator
|
9 |
+
import itertools
|
10 |
+
|
11 |
+
import torch
|
12 |
+
from torch import nn
|
13 |
+
from torch.nn import functional as F
|
14 |
+
from torch.autograd import Function
|
15 |
+
|
16 |
+
from op import FusedLeakyReLU, fused_leaky_relu, upfirdn2d
|
17 |
+
|
18 |
+
class PixelNorm(nn.Module):
|
19 |
+
def __init__(self):
|
20 |
+
super().__init__()
|
21 |
+
|
22 |
+
def forward(self, input):
|
23 |
+
return input * torch.rsqrt(torch.mean(input ** 2, dim=1, keepdim=True) + 1e-8)
|
24 |
+
|
25 |
+
|
26 |
+
def make_kernel(k):
|
27 |
+
k = torch.tensor(k, dtype=torch.float32)
|
28 |
+
|
29 |
+
if k.ndim == 1:
|
30 |
+
k = k[None, :] * k[:, None]
|
31 |
+
|
32 |
+
k /= k.sum()
|
33 |
+
|
34 |
+
return k
|
35 |
+
|
36 |
+
|
37 |
+
class Upsample(nn.Module):
|
38 |
+
def __init__(self, kernel, factor=2, device='cpu'):
|
39 |
+
super().__init__()
|
40 |
+
|
41 |
+
self.factor = factor
|
42 |
+
kernel = make_kernel(kernel) * (factor ** 2)
|
43 |
+
self.register_buffer('kernel', kernel)
|
44 |
+
|
45 |
+
p = kernel.shape[0] - factor
|
46 |
+
|
47 |
+
pad0 = (p + 1) // 2 + factor - 1
|
48 |
+
pad1 = p // 2
|
49 |
+
|
50 |
+
self.pad = (pad0, pad1)
|
51 |
+
self.device = device
|
52 |
+
|
53 |
+
def forward(self, input):
|
54 |
+
out = upfirdn2d(input, self.kernel, up=self.factor, down=1, pad=self.pad, device=self.device)
|
55 |
+
|
56 |
+
return out
|
57 |
+
|
58 |
+
|
59 |
+
class Downsample(nn.Module):
|
60 |
+
def __init__(self, kernel, factor=2, device='cpu'):
|
61 |
+
super().__init__()
|
62 |
+
|
63 |
+
self.factor = factor
|
64 |
+
kernel = make_kernel(kernel)
|
65 |
+
self.register_buffer('kernel', kernel)
|
66 |
+
|
67 |
+
p = kernel.shape[0] - factor
|
68 |
+
|
69 |
+
pad0 = (p + 1) // 2
|
70 |
+
pad1 = p // 2
|
71 |
+
|
72 |
+
self.pad = (pad0, pad1)
|
73 |
+
self.device = device
|
74 |
+
|
75 |
+
def forward(self, input):
|
76 |
+
out = upfirdn2d(input, self.kernel, up=1, down=self.factor, pad=self.pad, device=self.device)
|
77 |
+
|
78 |
+
return out
|
79 |
+
|
80 |
+
|
81 |
+
class Blur(nn.Module):
|
82 |
+
def __init__(self, kernel, pad, upsample_factor=1, device='cpu'):
|
83 |
+
super().__init__()
|
84 |
+
|
85 |
+
kernel = make_kernel(kernel)
|
86 |
+
|
87 |
+
if upsample_factor > 1:
|
88 |
+
kernel = kernel * (upsample_factor ** 2)
|
89 |
+
|
90 |
+
self.register_buffer('kernel', kernel)
|
91 |
+
|
92 |
+
self.pad = pad
|
93 |
+
self.device = device
|
94 |
+
|
95 |
+
def forward(self, input):
|
96 |
+
out = upfirdn2d(input, self.kernel, pad=self.pad, device=self.device)
|
97 |
+
|
98 |
+
return out
|
99 |
+
|
100 |
+
|
101 |
+
class EqualConv2d(nn.Module):
|
102 |
+
def __init__(
|
103 |
+
self, in_channel, out_channel, kernel_size, stride=1, padding=0, bias=True
|
104 |
+
):
|
105 |
+
super().__init__()
|
106 |
+
|
107 |
+
self.weight = nn.Parameter(
|
108 |
+
torch.randn(out_channel, in_channel, kernel_size, kernel_size)
|
109 |
+
)
|
110 |
+
self.scale = 1 / math.sqrt(in_channel * kernel_size ** 2)
|
111 |
+
|
112 |
+
self.stride = stride
|
113 |
+
self.padding = padding
|
114 |
+
|
115 |
+
if bias:
|
116 |
+
self.bias = nn.Parameter(torch.zeros(out_channel))
|
117 |
+
|
118 |
+
else:
|
119 |
+
self.bias = None
|
120 |
+
|
121 |
+
def forward(self, input):
|
122 |
+
out = F.conv2d(
|
123 |
+
input,
|
124 |
+
self.weight * self.scale,
|
125 |
+
bias=self.bias,
|
126 |
+
stride=self.stride,
|
127 |
+
padding=self.padding,
|
128 |
+
)
|
129 |
+
|
130 |
+
return out
|
131 |
+
|
132 |
+
def __repr__(self):
|
133 |
+
return (
|
134 |
+
f'{self.__class__.__name__}({self.weight.shape[1]}, {self.weight.shape[0]},'
|
135 |
+
f' {self.weight.shape[2]}, stride={self.stride}, padding={self.padding})'
|
136 |
+
)
|
137 |
+
|
138 |
+
|
139 |
+
class EqualLinear(nn.Module):
|
140 |
+
def __init__(
|
141 |
+
self, in_dim, out_dim, bias=True, bias_init=0, lr_mul=1, activation=None, device='cpu'
|
142 |
+
):
|
143 |
+
super().__init__()
|
144 |
+
|
145 |
+
self.weight = nn.Parameter(torch.randn(out_dim, in_dim).div_(lr_mul))
|
146 |
+
|
147 |
+
if bias:
|
148 |
+
self.bias = nn.Parameter(torch.zeros(out_dim).fill_(bias_init))
|
149 |
+
|
150 |
+
else:
|
151 |
+
self.bias = None
|
152 |
+
|
153 |
+
self.activation = activation
|
154 |
+
self.device = device
|
155 |
+
|
156 |
+
self.scale = (1 / math.sqrt(in_dim)) * lr_mul
|
157 |
+
self.lr_mul = lr_mul
|
158 |
+
|
159 |
+
def forward(self, input):
|
160 |
+
if self.activation:
|
161 |
+
out = F.linear(input, self.weight * self.scale)
|
162 |
+
out = fused_leaky_relu(out, self.bias * self.lr_mul, device=self.device)
|
163 |
+
|
164 |
+
else:
|
165 |
+
out = F.linear(input, self.weight * self.scale, bias=self.bias * self.lr_mul)
|
166 |
+
|
167 |
+
return out
|
168 |
+
|
169 |
+
def __repr__(self):
|
170 |
+
return (
|
171 |
+
f'{self.__class__.__name__}({self.weight.shape[1]}, {self.weight.shape[0]})'
|
172 |
+
)
|
173 |
+
|
174 |
+
|
175 |
+
class ScaledLeakyReLU(nn.Module):
|
176 |
+
def __init__(self, negative_slope=0.2):
|
177 |
+
super().__init__()
|
178 |
+
|
179 |
+
self.negative_slope = negative_slope
|
180 |
+
|
181 |
+
def forward(self, input):
|
182 |
+
out = F.leaky_relu(input, negative_slope=self.negative_slope)
|
183 |
+
|
184 |
+
return out * math.sqrt(2)
|
185 |
+
|
186 |
+
|
187 |
+
class ModulatedConv2d(nn.Module):
|
188 |
+
def __init__(
|
189 |
+
self,
|
190 |
+
in_channel,
|
191 |
+
out_channel,
|
192 |
+
kernel_size,
|
193 |
+
style_dim,
|
194 |
+
demodulate=True,
|
195 |
+
upsample=False,
|
196 |
+
downsample=False,
|
197 |
+
blur_kernel=[1, 3, 3, 1],
|
198 |
+
device='cpu'
|
199 |
+
):
|
200 |
+
super().__init__()
|
201 |
+
|
202 |
+
self.eps = 1e-8
|
203 |
+
self.kernel_size = kernel_size
|
204 |
+
self.in_channel = in_channel
|
205 |
+
self.out_channel = out_channel
|
206 |
+
self.upsample = upsample
|
207 |
+
self.downsample = downsample
|
208 |
+
|
209 |
+
if upsample:
|
210 |
+
factor = 2
|
211 |
+
p = (len(blur_kernel) - factor) - (kernel_size - 1)
|
212 |
+
pad0 = (p + 1) // 2 + factor - 1
|
213 |
+
pad1 = p // 2 + 1
|
214 |
+
|
215 |
+
self.blur = Blur(blur_kernel, pad=(pad0, pad1), upsample_factor=factor, device=device)
|
216 |
+
|
217 |
+
if downsample:
|
218 |
+
factor = 2
|
219 |
+
p = (len(blur_kernel) - factor) + (kernel_size - 1)
|
220 |
+
pad0 = (p + 1) // 2
|
221 |
+
pad1 = p // 2
|
222 |
+
|
223 |
+
self.blur = Blur(blur_kernel, pad=(pad0, pad1), device=device)
|
224 |
+
|
225 |
+
fan_in = in_channel * kernel_size ** 2
|
226 |
+
self.scale = 1 / math.sqrt(fan_in)
|
227 |
+
self.padding = kernel_size // 2
|
228 |
+
|
229 |
+
self.weight = nn.Parameter(
|
230 |
+
torch.randn(1, out_channel, in_channel, kernel_size, kernel_size)
|
231 |
+
)
|
232 |
+
|
233 |
+
self.modulation = EqualLinear(style_dim, in_channel, bias_init=1)
|
234 |
+
|
235 |
+
self.demodulate = demodulate
|
236 |
+
|
237 |
+
def __repr__(self):
|
238 |
+
return (
|
239 |
+
f'{self.__class__.__name__}({self.in_channel}, {self.out_channel}, {self.kernel_size}, '
|
240 |
+
f'upsample={self.upsample}, downsample={self.downsample})'
|
241 |
+
)
|
242 |
+
|
243 |
+
def forward(self, input, style):
|
244 |
+
batch, in_channel, height, width = input.shape
|
245 |
+
|
246 |
+
style = self.modulation(style).view(batch, 1, in_channel, 1, 1)
|
247 |
+
weight = self.scale * self.weight * style
|
248 |
+
|
249 |
+
if self.demodulate:
|
250 |
+
demod = torch.rsqrt(weight.pow(2).sum([2, 3, 4]) + 1e-8)
|
251 |
+
weight = weight * demod.view(batch, self.out_channel, 1, 1, 1)
|
252 |
+
|
253 |
+
weight = weight.view(
|
254 |
+
batch * self.out_channel, in_channel, self.kernel_size, self.kernel_size
|
255 |
+
)
|
256 |
+
|
257 |
+
if self.upsample:
|
258 |
+
input = input.view(1, batch * in_channel, height, width)
|
259 |
+
weight = weight.view(
|
260 |
+
batch, self.out_channel, in_channel, self.kernel_size, self.kernel_size
|
261 |
+
)
|
262 |
+
weight = weight.transpose(1, 2).reshape(
|
263 |
+
batch * in_channel, self.out_channel, self.kernel_size, self.kernel_size
|
264 |
+
)
|
265 |
+
out = F.conv_transpose2d(input, weight, padding=0, stride=2, groups=batch)
|
266 |
+
_, _, height, width = out.shape
|
267 |
+
out = out.view(batch, self.out_channel, height, width)
|
268 |
+
out = self.blur(out)
|
269 |
+
|
270 |
+
elif self.downsample:
|
271 |
+
input = self.blur(input)
|
272 |
+
_, _, height, width = input.shape
|
273 |
+
input = input.view(1, batch * in_channel, height, width)
|
274 |
+
out = F.conv2d(input, weight, padding=0, stride=2, groups=batch)
|
275 |
+
_, _, height, width = out.shape
|
276 |
+
out = out.view(batch, self.out_channel, height, width)
|
277 |
+
|
278 |
+
else:
|
279 |
+
input = input.view(1, batch * in_channel, height, width)
|
280 |
+
out = F.conv2d(input, weight, padding=self.padding, groups=batch)
|
281 |
+
_, _, height, width = out.shape
|
282 |
+
out = out.view(batch, self.out_channel, height, width)
|
283 |
+
|
284 |
+
return out
|
285 |
+
|
286 |
+
|
287 |
+
class NoiseInjection(nn.Module):
|
288 |
+
def __init__(self, isconcat=True):
|
289 |
+
super().__init__()
|
290 |
+
|
291 |
+
self.isconcat = isconcat
|
292 |
+
self.weight = nn.Parameter(torch.zeros(1))
|
293 |
+
|
294 |
+
def forward(self, image, noise=None):
|
295 |
+
if noise is None:
|
296 |
+
batch, _, height, width = image.shape
|
297 |
+
noise = image.new_empty(batch, 1, height, width).normal_()
|
298 |
+
|
299 |
+
if self.isconcat:
|
300 |
+
return torch.cat((image, self.weight * noise), dim=1)
|
301 |
+
else:
|
302 |
+
return image + self.weight * noise
|
303 |
+
|
304 |
+
|
305 |
+
class ConstantInput(nn.Module):
|
306 |
+
def __init__(self, channel, size=4):
|
307 |
+
super().__init__()
|
308 |
+
|
309 |
+
self.input = nn.Parameter(torch.randn(1, channel, size, size))
|
310 |
+
|
311 |
+
def forward(self, input):
|
312 |
+
batch = input.shape[0]
|
313 |
+
out = self.input.repeat(batch, 1, 1, 1)
|
314 |
+
|
315 |
+
return out
|
316 |
+
|
317 |
+
|
318 |
+
class StyledConv(nn.Module):
|
319 |
+
def __init__(
|
320 |
+
self,
|
321 |
+
in_channel,
|
322 |
+
out_channel,
|
323 |
+
kernel_size,
|
324 |
+
style_dim,
|
325 |
+
upsample=False,
|
326 |
+
blur_kernel=[1, 3, 3, 1],
|
327 |
+
demodulate=True,
|
328 |
+
isconcat=True,
|
329 |
+
device='cpu'
|
330 |
+
):
|
331 |
+
super().__init__()
|
332 |
+
|
333 |
+
self.conv = ModulatedConv2d(
|
334 |
+
in_channel,
|
335 |
+
out_channel,
|
336 |
+
kernel_size,
|
337 |
+
style_dim,
|
338 |
+
upsample=upsample,
|
339 |
+
blur_kernel=blur_kernel,
|
340 |
+
demodulate=demodulate,
|
341 |
+
device=device
|
342 |
+
)
|
343 |
+
|
344 |
+
self.noise = NoiseInjection(isconcat)
|
345 |
+
#self.bias = nn.Parameter(torch.zeros(1, out_channel, 1, 1))
|
346 |
+
#self.activate = ScaledLeakyReLU(0.2)
|
347 |
+
feat_multiplier = 2 if isconcat else 1
|
348 |
+
self.activate = FusedLeakyReLU(out_channel*feat_multiplier, device=device)
|
349 |
+
|
350 |
+
def forward(self, input, style, noise=None):
|
351 |
+
out = self.conv(input, style)
|
352 |
+
out = self.noise(out, noise=noise)
|
353 |
+
# out = out + self.bias
|
354 |
+
out = self.activate(out)
|
355 |
+
|
356 |
+
return out
|
357 |
+
|
358 |
+
|
359 |
+
class ToRGB(nn.Module):
|
360 |
+
def __init__(self, in_channel, style_dim, upsample=True, blur_kernel=[1, 3, 3, 1], device='cpu'):
|
361 |
+
super().__init__()
|
362 |
+
|
363 |
+
if upsample:
|
364 |
+
self.upsample = Upsample(blur_kernel, device=device)
|
365 |
+
|
366 |
+
self.conv = ModulatedConv2d(in_channel, 3, 1, style_dim, demodulate=False, device=device)
|
367 |
+
self.bias = nn.Parameter(torch.zeros(1, 3, 1, 1))
|
368 |
+
|
369 |
+
def forward(self, input, style, skip=None):
|
370 |
+
out = self.conv(input, style)
|
371 |
+
out = out + self.bias
|
372 |
+
|
373 |
+
if skip is not None:
|
374 |
+
skip = self.upsample(skip)
|
375 |
+
|
376 |
+
out = out + skip
|
377 |
+
|
378 |
+
return out
|
379 |
+
|
380 |
+
class Generator(nn.Module):
|
381 |
+
def __init__(
|
382 |
+
self,
|
383 |
+
size,
|
384 |
+
style_dim,
|
385 |
+
n_mlp,
|
386 |
+
channel_multiplier=2,
|
387 |
+
blur_kernel=[1, 3, 3, 1],
|
388 |
+
lr_mlp=0.01,
|
389 |
+
isconcat=True,
|
390 |
+
narrow=1,
|
391 |
+
device='cpu'
|
392 |
+
):
|
393 |
+
super().__init__()
|
394 |
+
|
395 |
+
self.size = size
|
396 |
+
self.n_mlp = n_mlp
|
397 |
+
self.style_dim = style_dim
|
398 |
+
self.feat_multiplier = 2 if isconcat else 1
|
399 |
+
|
400 |
+
layers = [PixelNorm()]
|
401 |
+
|
402 |
+
for i in range(n_mlp):
|
403 |
+
layers.append(
|
404 |
+
EqualLinear(
|
405 |
+
style_dim, style_dim, lr_mul=lr_mlp, activation='fused_lrelu', device=device
|
406 |
+
)
|
407 |
+
)
|
408 |
+
|
409 |
+
self.style = nn.Sequential(*layers)
|
410 |
+
|
411 |
+
self.channels = {
|
412 |
+
4: int(512 * narrow),
|
413 |
+
8: int(512 * narrow),
|
414 |
+
16: int(512 * narrow),
|
415 |
+
32: int(512 * narrow),
|
416 |
+
64: int(256 * channel_multiplier * narrow),
|
417 |
+
128: int(128 * channel_multiplier * narrow),
|
418 |
+
256: int(64 * channel_multiplier * narrow),
|
419 |
+
512: int(32 * channel_multiplier * narrow),
|
420 |
+
1024: int(16 * channel_multiplier * narrow)
|
421 |
+
}
|
422 |
+
|
423 |
+
self.input = ConstantInput(self.channels[4])
|
424 |
+
self.conv1 = StyledConv(
|
425 |
+
self.channels[4], self.channels[4], 3, style_dim, blur_kernel=blur_kernel, isconcat=isconcat, device=device
|
426 |
+
)
|
427 |
+
self.to_rgb1 = ToRGB(self.channels[4]*self.feat_multiplier, style_dim, upsample=False, device=device)
|
428 |
+
|
429 |
+
self.log_size = int(math.log(size, 2))
|
430 |
+
|
431 |
+
self.convs = nn.ModuleList()
|
432 |
+
self.upsamples = nn.ModuleList()
|
433 |
+
self.to_rgbs = nn.ModuleList()
|
434 |
+
|
435 |
+
in_channel = self.channels[4]
|
436 |
+
|
437 |
+
for i in range(3, self.log_size + 1):
|
438 |
+
out_channel = self.channels[2 ** i]
|
439 |
+
|
440 |
+
self.convs.append(
|
441 |
+
StyledConv(
|
442 |
+
in_channel*self.feat_multiplier,
|
443 |
+
out_channel,
|
444 |
+
3,
|
445 |
+
style_dim,
|
446 |
+
upsample=True,
|
447 |
+
blur_kernel=blur_kernel,
|
448 |
+
isconcat=isconcat,
|
449 |
+
device=device
|
450 |
+
)
|
451 |
+
)
|
452 |
+
|
453 |
+
self.convs.append(
|
454 |
+
StyledConv(
|
455 |
+
out_channel*self.feat_multiplier, out_channel, 3, style_dim, blur_kernel=blur_kernel, isconcat=isconcat, device=device
|
456 |
+
)
|
457 |
+
)
|
458 |
+
|
459 |
+
self.to_rgbs.append(ToRGB(out_channel*self.feat_multiplier, style_dim, device=device))
|
460 |
+
|
461 |
+
in_channel = out_channel
|
462 |
+
|
463 |
+
self.n_latent = self.log_size * 2 - 2
|
464 |
+
|
465 |
+
def make_noise(self):
|
466 |
+
device = self.input.input.device
|
467 |
+
|
468 |
+
noises = [torch.randn(1, 1, 2 ** 2, 2 ** 2, device=device)]
|
469 |
+
|
470 |
+
for i in range(3, self.log_size + 1):
|
471 |
+
for _ in range(2):
|
472 |
+
noises.append(torch.randn(1, 1, 2 ** i, 2 ** i, device=device))
|
473 |
+
|
474 |
+
return noises
|
475 |
+
|
476 |
+
def mean_latent(self, n_latent):
|
477 |
+
latent_in = torch.randn(
|
478 |
+
n_latent, self.style_dim, device=self.input.input.device
|
479 |
+
)
|
480 |
+
latent = self.style(latent_in).mean(0, keepdim=True)
|
481 |
+
|
482 |
+
return latent
|
483 |
+
|
484 |
+
def get_latent(self, input):
|
485 |
+
return self.style(input)
|
486 |
+
|
487 |
+
def forward(
|
488 |
+
self,
|
489 |
+
styles,
|
490 |
+
return_latents=False,
|
491 |
+
inject_index=None,
|
492 |
+
truncation=1,
|
493 |
+
truncation_latent=None,
|
494 |
+
input_is_latent=False,
|
495 |
+
noise=None,
|
496 |
+
):
|
497 |
+
if not input_is_latent:
|
498 |
+
styles = [self.style(s) for s in styles]
|
499 |
+
|
500 |
+
if noise is None:
|
501 |
+
'''
|
502 |
+
noise = [None] * (2 * (self.log_size - 2) + 1)
|
503 |
+
'''
|
504 |
+
noise = []
|
505 |
+
batch = styles[0].shape[0]
|
506 |
+
for i in range(self.n_mlp + 1):
|
507 |
+
size = 2 ** (i+2)
|
508 |
+
noise.append(torch.randn(batch, self.channels[size], size, size, device=styles[0].device))
|
509 |
+
|
510 |
+
if truncation < 1:
|
511 |
+
style_t = []
|
512 |
+
|
513 |
+
for style in styles:
|
514 |
+
style_t.append(
|
515 |
+
truncation_latent + truncation * (style - truncation_latent)
|
516 |
+
)
|
517 |
+
|
518 |
+
styles = style_t
|
519 |
+
|
520 |
+
if len(styles) < 2:
|
521 |
+
inject_index = self.n_latent
|
522 |
+
|
523 |
+
latent = styles[0].unsqueeze(1).repeat(1, inject_index, 1)
|
524 |
+
|
525 |
+
else:
|
526 |
+
if inject_index is None:
|
527 |
+
inject_index = random.randint(1, self.n_latent - 1)
|
528 |
+
|
529 |
+
latent = styles[0].unsqueeze(1).repeat(1, inject_index, 1)
|
530 |
+
latent2 = styles[1].unsqueeze(1).repeat(1, self.n_latent - inject_index, 1)
|
531 |
+
|
532 |
+
latent = torch.cat([latent, latent2], 1)
|
533 |
+
|
534 |
+
out = self.input(latent)
|
535 |
+
out = self.conv1(out, latent[:, 0], noise=noise[0])
|
536 |
+
|
537 |
+
skip = self.to_rgb1(out, latent[:, 1])
|
538 |
+
|
539 |
+
i = 1
|
540 |
+
for conv1, conv2, noise1, noise2, to_rgb in zip(
|
541 |
+
self.convs[::2], self.convs[1::2], noise[1::2], noise[2::2], self.to_rgbs
|
542 |
+
):
|
543 |
+
out = conv1(out, latent[:, i], noise=noise1)
|
544 |
+
out = conv2(out, latent[:, i + 1], noise=noise2)
|
545 |
+
skip = to_rgb(out, latent[:, i + 2], skip)
|
546 |
+
|
547 |
+
i += 2
|
548 |
+
|
549 |
+
image = skip
|
550 |
+
|
551 |
+
if return_latents:
|
552 |
+
return image, latent
|
553 |
+
|
554 |
+
else:
|
555 |
+
return image, None
|
556 |
+
|
557 |
+
class ConvLayer(nn.Sequential):
|
558 |
+
def __init__(
|
559 |
+
self,
|
560 |
+
in_channel,
|
561 |
+
out_channel,
|
562 |
+
kernel_size,
|
563 |
+
downsample=False,
|
564 |
+
blur_kernel=[1, 3, 3, 1],
|
565 |
+
bias=True,
|
566 |
+
activate=True,
|
567 |
+
device='cpu'
|
568 |
+
):
|
569 |
+
layers = []
|
570 |
+
|
571 |
+
if downsample:
|
572 |
+
factor = 2
|
573 |
+
p = (len(blur_kernel) - factor) + (kernel_size - 1)
|
574 |
+
pad0 = (p + 1) // 2
|
575 |
+
pad1 = p // 2
|
576 |
+
|
577 |
+
layers.append(Blur(blur_kernel, pad=(pad0, pad1), device=device))
|
578 |
+
|
579 |
+
stride = 2
|
580 |
+
self.padding = 0
|
581 |
+
|
582 |
+
else:
|
583 |
+
stride = 1
|
584 |
+
self.padding = kernel_size // 2
|
585 |
+
|
586 |
+
layers.append(
|
587 |
+
EqualConv2d(
|
588 |
+
in_channel,
|
589 |
+
out_channel,
|
590 |
+
kernel_size,
|
591 |
+
padding=self.padding,
|
592 |
+
stride=stride,
|
593 |
+
bias=bias and not activate,
|
594 |
+
)
|
595 |
+
)
|
596 |
+
|
597 |
+
if activate:
|
598 |
+
if bias:
|
599 |
+
layers.append(FusedLeakyReLU(out_channel, device=device))
|
600 |
+
|
601 |
+
else:
|
602 |
+
layers.append(ScaledLeakyReLU(0.2))
|
603 |
+
|
604 |
+
super().__init__(*layers)
|
605 |
+
|
606 |
+
|
607 |
+
class ResBlock(nn.Module):
|
608 |
+
def __init__(self, in_channel, out_channel, blur_kernel=[1, 3, 3, 1], device='cpu'):
|
609 |
+
super().__init__()
|
610 |
+
|
611 |
+
self.conv1 = ConvLayer(in_channel, in_channel, 3, device=device)
|
612 |
+
self.conv2 = ConvLayer(in_channel, out_channel, 3, downsample=True, device=device)
|
613 |
+
|
614 |
+
self.skip = ConvLayer(
|
615 |
+
in_channel, out_channel, 1, downsample=True, activate=False, bias=False
|
616 |
+
)
|
617 |
+
|
618 |
+
def forward(self, input):
|
619 |
+
out = self.conv1(input)
|
620 |
+
out = self.conv2(out)
|
621 |
+
|
622 |
+
skip = self.skip(input)
|
623 |
+
out = (out + skip) / math.sqrt(2)
|
624 |
+
|
625 |
+
return out
|
626 |
+
|
627 |
+
class FullGenerator(nn.Module):
|
628 |
+
def __init__(
|
629 |
+
self,
|
630 |
+
size,
|
631 |
+
style_dim,
|
632 |
+
n_mlp,
|
633 |
+
channel_multiplier=2,
|
634 |
+
blur_kernel=[1, 3, 3, 1],
|
635 |
+
lr_mlp=0.01,
|
636 |
+
isconcat=True,
|
637 |
+
narrow=1,
|
638 |
+
device='cpu'
|
639 |
+
):
|
640 |
+
super().__init__()
|
641 |
+
channels = {
|
642 |
+
4: int(512 * narrow),
|
643 |
+
8: int(512 * narrow),
|
644 |
+
16: int(512 * narrow),
|
645 |
+
32: int(512 * narrow),
|
646 |
+
64: int(256 * channel_multiplier * narrow),
|
647 |
+
128: int(128 * channel_multiplier * narrow),
|
648 |
+
256: int(64 * channel_multiplier * narrow),
|
649 |
+
512: int(32 * channel_multiplier * narrow),
|
650 |
+
1024: int(16 * channel_multiplier * narrow)
|
651 |
+
}
|
652 |
+
|
653 |
+
self.log_size = int(math.log(size, 2))
|
654 |
+
self.generator = Generator(size, style_dim, n_mlp, channel_multiplier=channel_multiplier, blur_kernel=blur_kernel, lr_mlp=lr_mlp, isconcat=isconcat, narrow=narrow, device=device)
|
655 |
+
|
656 |
+
conv = [ConvLayer(3, channels[size], 1, device=device)]
|
657 |
+
self.ecd0 = nn.Sequential(*conv)
|
658 |
+
in_channel = channels[size]
|
659 |
+
|
660 |
+
self.names = ['ecd%d'%i for i in range(self.log_size-1)]
|
661 |
+
for i in range(self.log_size, 2, -1):
|
662 |
+
out_channel = channels[2 ** (i - 1)]
|
663 |
+
#conv = [ResBlock(in_channel, out_channel, blur_kernel)]
|
664 |
+
conv = [ConvLayer(in_channel, out_channel, 3, downsample=True, device=device)]
|
665 |
+
setattr(self, self.names[self.log_size-i+1], nn.Sequential(*conv))
|
666 |
+
in_channel = out_channel
|
667 |
+
self.final_linear = nn.Sequential(EqualLinear(channels[4] * 4 * 4, style_dim, activation='fused_lrelu', device=device))
|
668 |
+
|
669 |
+
def forward(self,
|
670 |
+
inputs,
|
671 |
+
return_latents=False,
|
672 |
+
inject_index=None,
|
673 |
+
truncation=1,
|
674 |
+
truncation_latent=None,
|
675 |
+
input_is_latent=False,
|
676 |
+
):
|
677 |
+
noise = []
|
678 |
+
for i in range(self.log_size-1):
|
679 |
+
ecd = getattr(self, self.names[i])
|
680 |
+
inputs = ecd(inputs)
|
681 |
+
noise.append(inputs)
|
682 |
+
#print(inputs.shape)
|
683 |
+
inputs = inputs.view(inputs.shape[0], -1)
|
684 |
+
outs = self.final_linear(inputs)
|
685 |
+
#print(outs.shape)
|
686 |
+
noise = list(itertools.chain.from_iterable(itertools.repeat(x, 2) for x in noise))[::-1]
|
687 |
+
outs = self.generator([outs], return_latents, inject_index, truncation, truncation_latent, input_is_latent, noise=noise[1:])
|
688 |
+
return outs
|
689 |
+
|
690 |
+
class Discriminator(nn.Module):
|
691 |
+
def __init__(self, size, channel_multiplier=2, blur_kernel=[1, 3, 3, 1], narrow=1, device='cpu'):
|
692 |
+
super().__init__()
|
693 |
+
|
694 |
+
channels = {
|
695 |
+
4: int(512 * narrow),
|
696 |
+
8: int(512 * narrow),
|
697 |
+
16: int(512 * narrow),
|
698 |
+
32: int(512 * narrow),
|
699 |
+
64: int(256 * channel_multiplier * narrow),
|
700 |
+
128: int(128 * channel_multiplier * narrow),
|
701 |
+
256: int(64 * channel_multiplier * narrow),
|
702 |
+
512: int(32 * channel_multiplier * narrow),
|
703 |
+
1024: int(16 * channel_multiplier * narrow)
|
704 |
+
}
|
705 |
+
|
706 |
+
convs = [ConvLayer(3, channels[size], 1, device=device)]
|
707 |
+
|
708 |
+
log_size = int(math.log(size, 2))
|
709 |
+
|
710 |
+
in_channel = channels[size]
|
711 |
+
|
712 |
+
for i in range(log_size, 2, -1):
|
713 |
+
out_channel = channels[2 ** (i - 1)]
|
714 |
+
|
715 |
+
convs.append(ResBlock(in_channel, out_channel, blur_kernel, device=device))
|
716 |
+
|
717 |
+
in_channel = out_channel
|
718 |
+
|
719 |
+
self.convs = nn.Sequential(*convs)
|
720 |
+
|
721 |
+
self.stddev_group = 4
|
722 |
+
self.stddev_feat = 1
|
723 |
+
|
724 |
+
self.final_conv = ConvLayer(in_channel + 1, channels[4], 3, device=device)
|
725 |
+
self.final_linear = nn.Sequential(
|
726 |
+
EqualLinear(channels[4] * 4 * 4, channels[4], activation='fused_lrelu', device=device),
|
727 |
+
EqualLinear(channels[4], 1),
|
728 |
+
)
|
729 |
+
|
730 |
+
def forward(self, input):
|
731 |
+
out = self.convs(input)
|
732 |
+
|
733 |
+
batch, channel, height, width = out.shape
|
734 |
+
group = min(batch, self.stddev_group)
|
735 |
+
stddev = out.view(
|
736 |
+
group, -1, self.stddev_feat, channel // self.stddev_feat, height, width
|
737 |
+
)
|
738 |
+
stddev = torch.sqrt(stddev.var(0, unbiased=False) + 1e-8)
|
739 |
+
stddev = stddev.mean([2, 3, 4], keepdims=True).squeeze(2)
|
740 |
+
stddev = stddev.repeat(group, 1, height, width)
|
741 |
+
out = torch.cat([out, stddev], 1)
|
742 |
+
|
743 |
+
out = self.final_conv(out)
|
744 |
+
|
745 |
+
out = out.view(batch, -1)
|
746 |
+
out = self.final_linear(out)
|
747 |
+
return out
|
face_model/op/__init__.py
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
from .fused_act import FusedLeakyReLU, fused_leaky_relu
|
2 |
+
from .upfirdn2d import upfirdn2d
|
face_model/op/fused_act.py
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import platform
|
3 |
+
|
4 |
+
import torch
|
5 |
+
from torch import nn
|
6 |
+
import torch.nn.functional as F
|
7 |
+
from torch.autograd import Function
|
8 |
+
from torch.utils.cpp_extension import load, _import_module_from_library
|
9 |
+
|
10 |
+
# if running GPEN without cuda, please comment line 11-19
|
11 |
+
if platform.system() == 'Linux' and torch.cuda.is_available():
|
12 |
+
module_path = os.path.dirname(__file__)
|
13 |
+
fused = load(
|
14 |
+
'fused',
|
15 |
+
sources=[
|
16 |
+
os.path.join(module_path, 'fused_bias_act.cpp'),
|
17 |
+
os.path.join(module_path, 'fused_bias_act_kernel.cu'),
|
18 |
+
],
|
19 |
+
)
|
20 |
+
|
21 |
+
|
22 |
+
#fused = _import_module_from_library('fused', '/tmp/torch_extensions/fused', True)
|
23 |
+
|
24 |
+
|
25 |
+
class FusedLeakyReLUFunctionBackward(Function):
|
26 |
+
@staticmethod
|
27 |
+
def forward(ctx, grad_output, out, negative_slope, scale):
|
28 |
+
ctx.save_for_backward(out)
|
29 |
+
ctx.negative_slope = negative_slope
|
30 |
+
ctx.scale = scale
|
31 |
+
|
32 |
+
empty = grad_output.new_empty(0)
|
33 |
+
|
34 |
+
grad_input = fused.fused_bias_act(
|
35 |
+
grad_output, empty, out, 3, 1, negative_slope, scale
|
36 |
+
)
|
37 |
+
|
38 |
+
dim = [0]
|
39 |
+
|
40 |
+
if grad_input.ndim > 2:
|
41 |
+
dim += list(range(2, grad_input.ndim))
|
42 |
+
|
43 |
+
grad_bias = grad_input.sum(dim).detach()
|
44 |
+
|
45 |
+
return grad_input, grad_bias
|
46 |
+
|
47 |
+
@staticmethod
|
48 |
+
def backward(ctx, gradgrad_input, gradgrad_bias):
|
49 |
+
out, = ctx.saved_tensors
|
50 |
+
gradgrad_out = fused.fused_bias_act(
|
51 |
+
gradgrad_input, gradgrad_bias, out, 3, 1, ctx.negative_slope, ctx.scale
|
52 |
+
)
|
53 |
+
|
54 |
+
return gradgrad_out, None, None, None
|
55 |
+
|
56 |
+
|
57 |
+
class FusedLeakyReLUFunction(Function):
|
58 |
+
@staticmethod
|
59 |
+
def forward(ctx, input, bias, negative_slope, scale):
|
60 |
+
empty = input.new_empty(0)
|
61 |
+
out = fused.fused_bias_act(input, bias, empty, 3, 0, negative_slope, scale)
|
62 |
+
ctx.save_for_backward(out)
|
63 |
+
ctx.negative_slope = negative_slope
|
64 |
+
ctx.scale = scale
|
65 |
+
|
66 |
+
return out
|
67 |
+
|
68 |
+
@staticmethod
|
69 |
+
def backward(ctx, grad_output):
|
70 |
+
out, = ctx.saved_tensors
|
71 |
+
|
72 |
+
grad_input, grad_bias = FusedLeakyReLUFunctionBackward.apply(
|
73 |
+
grad_output, out, ctx.negative_slope, ctx.scale
|
74 |
+
)
|
75 |
+
|
76 |
+
return grad_input, grad_bias, None, None
|
77 |
+
|
78 |
+
|
79 |
+
class FusedLeakyReLU(nn.Module):
|
80 |
+
def __init__(self, channel, negative_slope=0.2, scale=2 ** 0.5, device='cpu'):
|
81 |
+
super().__init__()
|
82 |
+
|
83 |
+
self.bias = nn.Parameter(torch.zeros(channel))
|
84 |
+
self.negative_slope = negative_slope
|
85 |
+
self.scale = scale
|
86 |
+
self.device = device
|
87 |
+
|
88 |
+
def forward(self, input):
|
89 |
+
return fused_leaky_relu(input, self.bias, self.negative_slope, self.scale, self.device)
|
90 |
+
|
91 |
+
|
92 |
+
def fused_leaky_relu(input, bias, negative_slope=0.2, scale=2 ** 0.5, device='cpu'):
|
93 |
+
if platform.system() == 'Linux' and torch.cuda.is_available() and device != 'cpu':
|
94 |
+
return FusedLeakyReLUFunction.apply(input, bias, negative_slope, scale)
|
95 |
+
else:
|
96 |
+
return scale * F.leaky_relu(input + bias.view((1, -1)+(1,)*(len(input.shape)-2)), negative_slope=negative_slope)
|
face_model/op/fused_bias_act.cpp
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#include <torch/extension.h>
|
2 |
+
|
3 |
+
|
4 |
+
torch::Tensor fused_bias_act_op(const torch::Tensor& input, const torch::Tensor& bias, const torch::Tensor& refer,
|
5 |
+
int act, int grad, float alpha, float scale);
|
6 |
+
|
7 |
+
#define CHECK_CUDA(x) TORCH_CHECK(x.type().is_cuda(), #x " must be a CUDA tensor")
|
8 |
+
#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous")
|
9 |
+
#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x)
|
10 |
+
|
11 |
+
torch::Tensor fused_bias_act(const torch::Tensor& input, const torch::Tensor& bias, const torch::Tensor& refer,
|
12 |
+
int act, int grad, float alpha, float scale) {
|
13 |
+
CHECK_CUDA(input);
|
14 |
+
CHECK_CUDA(bias);
|
15 |
+
|
16 |
+
return fused_bias_act_op(input, bias, refer, act, grad, alpha, scale);
|
17 |
+
}
|
18 |
+
|
19 |
+
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
|
20 |
+
m.def("fused_bias_act", &fused_bias_act, "fused bias act (CUDA)");
|
21 |
+
}
|
face_model/op/fused_bias_act_kernel.cu
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
|
2 |
+
//
|
3 |
+
// This work is made available under the Nvidia Source Code License-NC.
|
4 |
+
// To view a copy of this license, visit
|
5 |
+
// https://nvlabs.github.io/stylegan2/license.html
|
6 |
+
|
7 |
+
#include <torch/types.h>
|
8 |
+
|
9 |
+
#include <ATen/ATen.h>
|
10 |
+
#include <ATen/AccumulateType.h>
|
11 |
+
#include <ATen/cuda/CUDAContext.h>
|
12 |
+
#include <ATen/cuda/CUDAApplyUtils.cuh>
|
13 |
+
|
14 |
+
#include <cuda.h>
|
15 |
+
#include <cuda_runtime.h>
|
16 |
+
|
17 |
+
|
18 |
+
template <typename scalar_t>
|
19 |
+
static __global__ void fused_bias_act_kernel(scalar_t* out, const scalar_t* p_x, const scalar_t* p_b, const scalar_t* p_ref,
|
20 |
+
int act, int grad, scalar_t alpha, scalar_t scale, int loop_x, int size_x, int step_b, int size_b, int use_bias, int use_ref) {
|
21 |
+
int xi = blockIdx.x * loop_x * blockDim.x + threadIdx.x;
|
22 |
+
|
23 |
+
scalar_t zero = 0.0;
|
24 |
+
|
25 |
+
for (int loop_idx = 0; loop_idx < loop_x && xi < size_x; loop_idx++, xi += blockDim.x) {
|
26 |
+
scalar_t x = p_x[xi];
|
27 |
+
|
28 |
+
if (use_bias) {
|
29 |
+
x += p_b[(xi / step_b) % size_b];
|
30 |
+
}
|
31 |
+
|
32 |
+
scalar_t ref = use_ref ? p_ref[xi] : zero;
|
33 |
+
|
34 |
+
scalar_t y;
|
35 |
+
|
36 |
+
switch (act * 10 + grad) {
|
37 |
+
default:
|
38 |
+
case 10: y = x; break;
|
39 |
+
case 11: y = x; break;
|
40 |
+
case 12: y = 0.0; break;
|
41 |
+
|
42 |
+
case 30: y = (x > 0.0) ? x : x * alpha; break;
|
43 |
+
case 31: y = (ref > 0.0) ? x : x * alpha; break;
|
44 |
+
case 32: y = 0.0; break;
|
45 |
+
}
|
46 |
+
|
47 |
+
out[xi] = y * scale;
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
|
52 |
+
torch::Tensor fused_bias_act_op(const torch::Tensor& input, const torch::Tensor& bias, const torch::Tensor& refer,
|
53 |
+
int act, int grad, float alpha, float scale) {
|
54 |
+
int curDevice = -1;
|
55 |
+
cudaGetDevice(&curDevice);
|
56 |
+
cudaStream_t stream = at::cuda::getCurrentCUDAStream(curDevice);
|
57 |
+
|
58 |
+
auto x = input.contiguous();
|
59 |
+
auto b = bias.contiguous();
|
60 |
+
auto ref = refer.contiguous();
|
61 |
+
|
62 |
+
int use_bias = b.numel() ? 1 : 0;
|
63 |
+
int use_ref = ref.numel() ? 1 : 0;
|
64 |
+
|
65 |
+
int size_x = x.numel();
|
66 |
+
int size_b = b.numel();
|
67 |
+
int step_b = 1;
|
68 |
+
|
69 |
+
for (int i = 1 + 1; i < x.dim(); i++) {
|
70 |
+
step_b *= x.size(i);
|
71 |
+
}
|
72 |
+
|
73 |
+
int loop_x = 4;
|
74 |
+
int block_size = 4 * 32;
|
75 |
+
int grid_size = (size_x - 1) / (loop_x * block_size) + 1;
|
76 |
+
|
77 |
+
auto y = torch::empty_like(x);
|
78 |
+
|
79 |
+
AT_DISPATCH_FLOATING_TYPES_AND_HALF(x.scalar_type(), "fused_bias_act_kernel", [&] {
|
80 |
+
fused_bias_act_kernel<scalar_t><<<grid_size, block_size, 0, stream>>>(
|
81 |
+
y.data_ptr<scalar_t>(),
|
82 |
+
x.data_ptr<scalar_t>(),
|
83 |
+
b.data_ptr<scalar_t>(),
|
84 |
+
ref.data_ptr<scalar_t>(),
|
85 |
+
act,
|
86 |
+
grad,
|
87 |
+
alpha,
|
88 |
+
scale,
|
89 |
+
loop_x,
|
90 |
+
size_x,
|
91 |
+
step_b,
|
92 |
+
size_b,
|
93 |
+
use_bias,
|
94 |
+
use_ref
|
95 |
+
);
|
96 |
+
});
|
97 |
+
|
98 |
+
return y;
|
99 |
+
}
|
face_model/op/upfirdn2d.cpp
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#include <torch/extension.h>
|
2 |
+
|
3 |
+
|
4 |
+
torch::Tensor upfirdn2d_op(const torch::Tensor& input, const torch::Tensor& kernel,
|
5 |
+
int up_x, int up_y, int down_x, int down_y,
|
6 |
+
int pad_x0, int pad_x1, int pad_y0, int pad_y1);
|
7 |
+
|
8 |
+
#define CHECK_CUDA(x) TORCH_CHECK(x.type().is_cuda(), #x " must be a CUDA tensor")
|
9 |
+
#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous")
|
10 |
+
#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x)
|
11 |
+
|
12 |
+
torch::Tensor upfirdn2d(const torch::Tensor& input, const torch::Tensor& kernel,
|
13 |
+
int up_x, int up_y, int down_x, int down_y,
|
14 |
+
int pad_x0, int pad_x1, int pad_y0, int pad_y1) {
|
15 |
+
CHECK_CUDA(input);
|
16 |
+
CHECK_CUDA(kernel);
|
17 |
+
|
18 |
+
return upfirdn2d_op(input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1, pad_y0, pad_y1);
|
19 |
+
}
|
20 |
+
|
21 |
+
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
|
22 |
+
m.def("upfirdn2d", &upfirdn2d, "upfirdn2d (CUDA)");
|
23 |
+
}
|
face_model/op/upfirdn2d.py
ADDED
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import platform
|
3 |
+
|
4 |
+
import torch
|
5 |
+
import torch.nn.functional as F
|
6 |
+
from torch.autograd import Function
|
7 |
+
from torch.utils.cpp_extension import load, _import_module_from_library
|
8 |
+
|
9 |
+
# if running GPEN without cuda, please comment line 10-18
|
10 |
+
if platform.system() == 'Linux' and torch.cuda.is_available():
|
11 |
+
module_path = os.path.dirname(__file__)
|
12 |
+
upfirdn2d_op = load(
|
13 |
+
'upfirdn2d',
|
14 |
+
sources=[
|
15 |
+
os.path.join(module_path, 'upfirdn2d.cpp'),
|
16 |
+
os.path.join(module_path, 'upfirdn2d_kernel.cu'),
|
17 |
+
],
|
18 |
+
)
|
19 |
+
|
20 |
+
|
21 |
+
#upfirdn2d_op = _import_module_from_library('upfirdn2d', '/tmp/torch_extensions/upfirdn2d', True)
|
22 |
+
|
23 |
+
class UpFirDn2dBackward(Function):
|
24 |
+
@staticmethod
|
25 |
+
def forward(
|
26 |
+
ctx, grad_output, kernel, grad_kernel, up, down, pad, g_pad, in_size, out_size
|
27 |
+
):
|
28 |
+
|
29 |
+
up_x, up_y = up
|
30 |
+
down_x, down_y = down
|
31 |
+
g_pad_x0, g_pad_x1, g_pad_y0, g_pad_y1 = g_pad
|
32 |
+
|
33 |
+
grad_output = grad_output.reshape(-1, out_size[0], out_size[1], 1)
|
34 |
+
|
35 |
+
grad_input = upfirdn2d_op.upfirdn2d(
|
36 |
+
grad_output,
|
37 |
+
grad_kernel,
|
38 |
+
down_x,
|
39 |
+
down_y,
|
40 |
+
up_x,
|
41 |
+
up_y,
|
42 |
+
g_pad_x0,
|
43 |
+
g_pad_x1,
|
44 |
+
g_pad_y0,
|
45 |
+
g_pad_y1,
|
46 |
+
)
|
47 |
+
grad_input = grad_input.view(in_size[0], in_size[1], in_size[2], in_size[3])
|
48 |
+
|
49 |
+
ctx.save_for_backward(kernel)
|
50 |
+
|
51 |
+
pad_x0, pad_x1, pad_y0, pad_y1 = pad
|
52 |
+
|
53 |
+
ctx.up_x = up_x
|
54 |
+
ctx.up_y = up_y
|
55 |
+
ctx.down_x = down_x
|
56 |
+
ctx.down_y = down_y
|
57 |
+
ctx.pad_x0 = pad_x0
|
58 |
+
ctx.pad_x1 = pad_x1
|
59 |
+
ctx.pad_y0 = pad_y0
|
60 |
+
ctx.pad_y1 = pad_y1
|
61 |
+
ctx.in_size = in_size
|
62 |
+
ctx.out_size = out_size
|
63 |
+
|
64 |
+
return grad_input
|
65 |
+
|
66 |
+
@staticmethod
|
67 |
+
def backward(ctx, gradgrad_input):
|
68 |
+
kernel, = ctx.saved_tensors
|
69 |
+
|
70 |
+
gradgrad_input = gradgrad_input.reshape(-1, ctx.in_size[2], ctx.in_size[3], 1)
|
71 |
+
|
72 |
+
gradgrad_out = upfirdn2d_op.upfirdn2d(
|
73 |
+
gradgrad_input,
|
74 |
+
kernel,
|
75 |
+
ctx.up_x,
|
76 |
+
ctx.up_y,
|
77 |
+
ctx.down_x,
|
78 |
+
ctx.down_y,
|
79 |
+
ctx.pad_x0,
|
80 |
+
ctx.pad_x1,
|
81 |
+
ctx.pad_y0,
|
82 |
+
ctx.pad_y1,
|
83 |
+
)
|
84 |
+
# gradgrad_out = gradgrad_out.view(ctx.in_size[0], ctx.out_size[0], ctx.out_size[1], ctx.in_size[3])
|
85 |
+
gradgrad_out = gradgrad_out.view(
|
86 |
+
ctx.in_size[0], ctx.in_size[1], ctx.out_size[0], ctx.out_size[1]
|
87 |
+
)
|
88 |
+
|
89 |
+
return gradgrad_out, None, None, None, None, None, None, None, None
|
90 |
+
|
91 |
+
|
92 |
+
class UpFirDn2d(Function):
|
93 |
+
@staticmethod
|
94 |
+
def forward(ctx, input, kernel, up, down, pad):
|
95 |
+
up_x, up_y = up
|
96 |
+
down_x, down_y = down
|
97 |
+
pad_x0, pad_x1, pad_y0, pad_y1 = pad
|
98 |
+
|
99 |
+
kernel_h, kernel_w = kernel.shape
|
100 |
+
batch, channel, in_h, in_w = input.shape
|
101 |
+
ctx.in_size = input.shape
|
102 |
+
|
103 |
+
input = input.reshape(-1, in_h, in_w, 1)
|
104 |
+
|
105 |
+
ctx.save_for_backward(kernel, torch.flip(kernel, [0, 1]))
|
106 |
+
|
107 |
+
out_h = (in_h * up_y + pad_y0 + pad_y1 - kernel_h) // down_y + 1
|
108 |
+
out_w = (in_w * up_x + pad_x0 + pad_x1 - kernel_w) // down_x + 1
|
109 |
+
ctx.out_size = (out_h, out_w)
|
110 |
+
|
111 |
+
ctx.up = (up_x, up_y)
|
112 |
+
ctx.down = (down_x, down_y)
|
113 |
+
ctx.pad = (pad_x0, pad_x1, pad_y0, pad_y1)
|
114 |
+
|
115 |
+
g_pad_x0 = kernel_w - pad_x0 - 1
|
116 |
+
g_pad_y0 = kernel_h - pad_y0 - 1
|
117 |
+
g_pad_x1 = in_w * up_x - out_w * down_x + pad_x0 - up_x + 1
|
118 |
+
g_pad_y1 = in_h * up_y - out_h * down_y + pad_y0 - up_y + 1
|
119 |
+
|
120 |
+
ctx.g_pad = (g_pad_x0, g_pad_x1, g_pad_y0, g_pad_y1)
|
121 |
+
|
122 |
+
out = upfirdn2d_op.upfirdn2d(
|
123 |
+
input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1, pad_y0, pad_y1
|
124 |
+
)
|
125 |
+
# out = out.view(major, out_h, out_w, minor)
|
126 |
+
out = out.view(-1, channel, out_h, out_w)
|
127 |
+
|
128 |
+
return out
|
129 |
+
|
130 |
+
@staticmethod
|
131 |
+
def backward(ctx, grad_output):
|
132 |
+
kernel, grad_kernel = ctx.saved_tensors
|
133 |
+
|
134 |
+
grad_input = UpFirDn2dBackward.apply(
|
135 |
+
grad_output,
|
136 |
+
kernel,
|
137 |
+
grad_kernel,
|
138 |
+
ctx.up,
|
139 |
+
ctx.down,
|
140 |
+
ctx.pad,
|
141 |
+
ctx.g_pad,
|
142 |
+
ctx.in_size,
|
143 |
+
ctx.out_size,
|
144 |
+
)
|
145 |
+
|
146 |
+
return grad_input, None, None, None, None
|
147 |
+
|
148 |
+
|
149 |
+
def upfirdn2d(input, kernel, up=1, down=1, pad=(0, 0), device='cpu'):
|
150 |
+
if platform.system() == 'Linux' and torch.cuda.is_available() and device != 'cpu':
|
151 |
+
out = UpFirDn2d.apply(
|
152 |
+
input, kernel, (up, up), (down, down), (pad[0], pad[1], pad[0], pad[1])
|
153 |
+
)
|
154 |
+
else:
|
155 |
+
out = upfirdn2d_native(input, kernel, up, up, down, down, pad[0], pad[1], pad[0], pad[1])
|
156 |
+
|
157 |
+
return out
|
158 |
+
|
159 |
+
|
160 |
+
def upfirdn2d_native(
|
161 |
+
input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1, pad_y0, pad_y1
|
162 |
+
):
|
163 |
+
input = input.permute(0, 2, 3, 1)
|
164 |
+
_, in_h, in_w, minor = input.shape
|
165 |
+
kernel_h, kernel_w = kernel.shape
|
166 |
+
out = input.view(-1, in_h, 1, in_w, 1, minor)
|
167 |
+
out = F.pad(out, [0, 0, 0, up_x - 1, 0, 0, 0, up_y - 1])
|
168 |
+
out = out.view(-1, in_h * up_y, in_w * up_x, minor)
|
169 |
+
|
170 |
+
out = F.pad(
|
171 |
+
out, [0, 0, max(pad_x0, 0), max(pad_x1, 0), max(pad_y0, 0), max(pad_y1, 0)]
|
172 |
+
)
|
173 |
+
out = out[
|
174 |
+
:,
|
175 |
+
max(-pad_y0, 0) : out.shape[1] - max(-pad_y1, 0),
|
176 |
+
max(-pad_x0, 0) : out.shape[2] - max(-pad_x1, 0),
|
177 |
+
:,
|
178 |
+
]
|
179 |
+
|
180 |
+
out = out.permute(0, 3, 1, 2)
|
181 |
+
out = out.reshape(
|
182 |
+
[-1, 1, in_h * up_y + pad_y0 + pad_y1, in_w * up_x + pad_x0 + pad_x1]
|
183 |
+
)
|
184 |
+
w = torch.flip(kernel, [0, 1]).view(1, 1, kernel_h, kernel_w)
|
185 |
+
out = F.conv2d(out, w)
|
186 |
+
out = out.reshape(
|
187 |
+
-1,
|
188 |
+
minor,
|
189 |
+
in_h * up_y + pad_y0 + pad_y1 - kernel_h + 1,
|
190 |
+
in_w * up_x + pad_x0 + pad_x1 - kernel_w + 1,
|
191 |
+
)
|
192 |
+
# out = out.permute(0, 2, 3, 1)
|
193 |
+
return out[:, :, ::down_y, ::down_x]
|
194 |
+
|
face_model/op/upfirdn2d_kernel.cu
ADDED
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
|
2 |
+
//
|
3 |
+
// This work is made available under the Nvidia Source Code License-NC.
|
4 |
+
// To view a copy of this license, visit
|
5 |
+
// https://nvlabs.github.io/stylegan2/license.html
|
6 |
+
|
7 |
+
#include <torch/types.h>
|
8 |
+
|
9 |
+
#include <ATen/ATen.h>
|
10 |
+
#include <ATen/AccumulateType.h>
|
11 |
+
#include <ATen/cuda/CUDAContext.h>
|
12 |
+
#include <ATen/cuda/CUDAApplyUtils.cuh>
|
13 |
+
|
14 |
+
#include <cuda.h>
|
15 |
+
#include <cuda_runtime.h>
|
16 |
+
|
17 |
+
|
18 |
+
static __host__ __device__ __forceinline__ int floor_div(int a, int b) {
|
19 |
+
int c = a / b;
|
20 |
+
|
21 |
+
if (c * b > a) {
|
22 |
+
c--;
|
23 |
+
}
|
24 |
+
|
25 |
+
return c;
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
struct UpFirDn2DKernelParams {
|
30 |
+
int up_x;
|
31 |
+
int up_y;
|
32 |
+
int down_x;
|
33 |
+
int down_y;
|
34 |
+
int pad_x0;
|
35 |
+
int pad_x1;
|
36 |
+
int pad_y0;
|
37 |
+
int pad_y1;
|
38 |
+
|
39 |
+
int major_dim;
|
40 |
+
int in_h;
|
41 |
+
int in_w;
|
42 |
+
int minor_dim;
|
43 |
+
int kernel_h;
|
44 |
+
int kernel_w;
|
45 |
+
int out_h;
|
46 |
+
int out_w;
|
47 |
+
int loop_major;
|
48 |
+
int loop_x;
|
49 |
+
};
|
50 |
+
|
51 |
+
|
52 |
+
template <typename scalar_t, int up_x, int up_y, int down_x, int down_y, int kernel_h, int kernel_w, int tile_out_h, int tile_out_w>
|
53 |
+
__global__ void upfirdn2d_kernel(scalar_t* out, const scalar_t* input, const scalar_t* kernel, const UpFirDn2DKernelParams p) {
|
54 |
+
const int tile_in_h = ((tile_out_h - 1) * down_y + kernel_h - 1) / up_y + 1;
|
55 |
+
const int tile_in_w = ((tile_out_w - 1) * down_x + kernel_w - 1) / up_x + 1;
|
56 |
+
|
57 |
+
__shared__ volatile float sk[kernel_h][kernel_w];
|
58 |
+
__shared__ volatile float sx[tile_in_h][tile_in_w];
|
59 |
+
|
60 |
+
int minor_idx = blockIdx.x;
|
61 |
+
int tile_out_y = minor_idx / p.minor_dim;
|
62 |
+
minor_idx -= tile_out_y * p.minor_dim;
|
63 |
+
tile_out_y *= tile_out_h;
|
64 |
+
int tile_out_x_base = blockIdx.y * p.loop_x * tile_out_w;
|
65 |
+
int major_idx_base = blockIdx.z * p.loop_major;
|
66 |
+
|
67 |
+
if (tile_out_x_base >= p.out_w | tile_out_y >= p.out_h | major_idx_base >= p.major_dim) {
|
68 |
+
return;
|
69 |
+
}
|
70 |
+
|
71 |
+
for (int tap_idx = threadIdx.x; tap_idx < kernel_h * kernel_w; tap_idx += blockDim.x) {
|
72 |
+
int ky = tap_idx / kernel_w;
|
73 |
+
int kx = tap_idx - ky * kernel_w;
|
74 |
+
scalar_t v = 0.0;
|
75 |
+
|
76 |
+
if (kx < p.kernel_w & ky < p.kernel_h) {
|
77 |
+
v = kernel[(p.kernel_h - 1 - ky) * p.kernel_w + (p.kernel_w - 1 - kx)];
|
78 |
+
}
|
79 |
+
|
80 |
+
sk[ky][kx] = v;
|
81 |
+
}
|
82 |
+
|
83 |
+
for (int loop_major = 0, major_idx = major_idx_base; loop_major < p.loop_major & major_idx < p.major_dim; loop_major++, major_idx++) {
|
84 |
+
for (int loop_x = 0, tile_out_x = tile_out_x_base; loop_x < p.loop_x & tile_out_x < p.out_w; loop_x++, tile_out_x += tile_out_w) {
|
85 |
+
int tile_mid_x = tile_out_x * down_x + up_x - 1 - p.pad_x0;
|
86 |
+
int tile_mid_y = tile_out_y * down_y + up_y - 1 - p.pad_y0;
|
87 |
+
int tile_in_x = floor_div(tile_mid_x, up_x);
|
88 |
+
int tile_in_y = floor_div(tile_mid_y, up_y);
|
89 |
+
|
90 |
+
__syncthreads();
|
91 |
+
|
92 |
+
for (int in_idx = threadIdx.x; in_idx < tile_in_h * tile_in_w; in_idx += blockDim.x) {
|
93 |
+
int rel_in_y = in_idx / tile_in_w;
|
94 |
+
int rel_in_x = in_idx - rel_in_y * tile_in_w;
|
95 |
+
int in_x = rel_in_x + tile_in_x;
|
96 |
+
int in_y = rel_in_y + tile_in_y;
|
97 |
+
|
98 |
+
scalar_t v = 0.0;
|
99 |
+
|
100 |
+
if (in_x >= 0 & in_y >= 0 & in_x < p.in_w & in_y < p.in_h) {
|
101 |
+
v = input[((major_idx * p.in_h + in_y) * p.in_w + in_x) * p.minor_dim + minor_idx];
|
102 |
+
}
|
103 |
+
|
104 |
+
sx[rel_in_y][rel_in_x] = v;
|
105 |
+
}
|
106 |
+
|
107 |
+
__syncthreads();
|
108 |
+
for (int out_idx = threadIdx.x; out_idx < tile_out_h * tile_out_w; out_idx += blockDim.x) {
|
109 |
+
int rel_out_y = out_idx / tile_out_w;
|
110 |
+
int rel_out_x = out_idx - rel_out_y * tile_out_w;
|
111 |
+
int out_x = rel_out_x + tile_out_x;
|
112 |
+
int out_y = rel_out_y + tile_out_y;
|
113 |
+
|
114 |
+
int mid_x = tile_mid_x + rel_out_x * down_x;
|
115 |
+
int mid_y = tile_mid_y + rel_out_y * down_y;
|
116 |
+
int in_x = floor_div(mid_x, up_x);
|
117 |
+
int in_y = floor_div(mid_y, up_y);
|
118 |
+
int rel_in_x = in_x - tile_in_x;
|
119 |
+
int rel_in_y = in_y - tile_in_y;
|
120 |
+
int kernel_x = (in_x + 1) * up_x - mid_x - 1;
|
121 |
+
int kernel_y = (in_y + 1) * up_y - mid_y - 1;
|
122 |
+
|
123 |
+
scalar_t v = 0.0;
|
124 |
+
|
125 |
+
#pragma unroll
|
126 |
+
for (int y = 0; y < kernel_h / up_y; y++)
|
127 |
+
#pragma unroll
|
128 |
+
for (int x = 0; x < kernel_w / up_x; x++)
|
129 |
+
v += sx[rel_in_y + y][rel_in_x + x] * sk[kernel_y + y * up_y][kernel_x + x * up_x];
|
130 |
+
|
131 |
+
if (out_x < p.out_w & out_y < p.out_h) {
|
132 |
+
out[((major_idx * p.out_h + out_y) * p.out_w + out_x) * p.minor_dim + minor_idx] = v;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
|
140 |
+
torch::Tensor upfirdn2d_op(const torch::Tensor& input, const torch::Tensor& kernel,
|
141 |
+
int up_x, int up_y, int down_x, int down_y,
|
142 |
+
int pad_x0, int pad_x1, int pad_y0, int pad_y1) {
|
143 |
+
int curDevice = -1;
|
144 |
+
cudaGetDevice(&curDevice);
|
145 |
+
cudaStream_t stream = at::cuda::getCurrentCUDAStream(curDevice);
|
146 |
+
|
147 |
+
UpFirDn2DKernelParams p;
|
148 |
+
|
149 |
+
auto x = input.contiguous();
|
150 |
+
auto k = kernel.contiguous();
|
151 |
+
|
152 |
+
p.major_dim = x.size(0);
|
153 |
+
p.in_h = x.size(1);
|
154 |
+
p.in_w = x.size(2);
|
155 |
+
p.minor_dim = x.size(3);
|
156 |
+
p.kernel_h = k.size(0);
|
157 |
+
p.kernel_w = k.size(1);
|
158 |
+
p.up_x = up_x;
|
159 |
+
p.up_y = up_y;
|
160 |
+
p.down_x = down_x;
|
161 |
+
p.down_y = down_y;
|
162 |
+
p.pad_x0 = pad_x0;
|
163 |
+
p.pad_x1 = pad_x1;
|
164 |
+
p.pad_y0 = pad_y0;
|
165 |
+
p.pad_y1 = pad_y1;
|
166 |
+
|
167 |
+
p.out_h = (p.in_h * p.up_y + p.pad_y0 + p.pad_y1 - p.kernel_h + p.down_y) / p.down_y;
|
168 |
+
p.out_w = (p.in_w * p.up_x + p.pad_x0 + p.pad_x1 - p.kernel_w + p.down_x) / p.down_x;
|
169 |
+
|
170 |
+
auto out = at::empty({p.major_dim, p.out_h, p.out_w, p.minor_dim}, x.options());
|
171 |
+
|
172 |
+
int mode = -1;
|
173 |
+
|
174 |
+
int tile_out_h;
|
175 |
+
int tile_out_w;
|
176 |
+
|
177 |
+
if (p.up_x == 1 && p.up_y == 1 && p.down_x == 1 && p.down_y == 1 && p.kernel_h <= 4 && p.kernel_w <= 4) {
|
178 |
+
mode = 1;
|
179 |
+
tile_out_h = 16;
|
180 |
+
tile_out_w = 64;
|
181 |
+
}
|
182 |
+
|
183 |
+
if (p.up_x == 1 && p.up_y == 1 && p.down_x == 1 && p.down_y == 1 && p.kernel_h <= 3 && p.kernel_w <= 3) {
|
184 |
+
mode = 2;
|
185 |
+
tile_out_h = 16;
|
186 |
+
tile_out_w = 64;
|
187 |
+
}
|
188 |
+
|
189 |
+
if (p.up_x == 2 && p.up_y == 2 && p.down_x == 1 && p.down_y == 1 && p.kernel_h <= 4 && p.kernel_w <= 4) {
|
190 |
+
mode = 3;
|
191 |
+
tile_out_h = 16;
|
192 |
+
tile_out_w = 64;
|
193 |
+
}
|
194 |
+
|
195 |
+
if (p.up_x == 2 && p.up_y == 2 && p.down_x == 1 && p.down_y == 1 && p.kernel_h <= 2 && p.kernel_w <= 2) {
|
196 |
+
mode = 4;
|
197 |
+
tile_out_h = 16;
|
198 |
+
tile_out_w = 64;
|
199 |
+
}
|
200 |
+
|
201 |
+
if (p.up_x == 1 && p.up_y == 1 && p.down_x == 2 && p.down_y == 2 && p.kernel_h <= 4 && p.kernel_w <= 4) {
|
202 |
+
mode = 5;
|
203 |
+
tile_out_h = 8;
|
204 |
+
tile_out_w = 32;
|
205 |
+
}
|
206 |
+
|
207 |
+
if (p.up_x == 1 && p.up_y == 1 && p.down_x == 2 && p.down_y == 2 && p.kernel_h <= 2 && p.kernel_w <= 2) {
|
208 |
+
mode = 6;
|
209 |
+
tile_out_h = 8;
|
210 |
+
tile_out_w = 32;
|
211 |
+
}
|
212 |
+
|
213 |
+
dim3 block_size;
|
214 |
+
dim3 grid_size;
|
215 |
+
|
216 |
+
if (tile_out_h > 0 && tile_out_w) {
|
217 |
+
p.loop_major = (p.major_dim - 1) / 16384 + 1;
|
218 |
+
p.loop_x = 1;
|
219 |
+
block_size = dim3(32 * 8, 1, 1);
|
220 |
+
grid_size = dim3(((p.out_h - 1) / tile_out_h + 1) * p.minor_dim,
|
221 |
+
(p.out_w - 1) / (p.loop_x * tile_out_w) + 1,
|
222 |
+
(p.major_dim - 1) / p.loop_major + 1);
|
223 |
+
}
|
224 |
+
|
225 |
+
AT_DISPATCH_FLOATING_TYPES_AND_HALF(x.scalar_type(), "upfirdn2d_cuda", [&] {
|
226 |
+
switch (mode) {
|
227 |
+
case 1:
|
228 |
+
upfirdn2d_kernel<scalar_t, 1, 1, 1, 1, 4, 4, 16, 64><<<grid_size, block_size, 0, stream>>>(
|
229 |
+
out.data_ptr<scalar_t>(), x.data_ptr<scalar_t>(), k.data_ptr<scalar_t>(), p
|
230 |
+
);
|
231 |
+
|
232 |
+
break;
|
233 |
+
|
234 |
+
case 2:
|
235 |
+
upfirdn2d_kernel<scalar_t, 1, 1, 1, 1, 3, 3, 16, 64><<<grid_size, block_size, 0, stream>>>(
|
236 |
+
out.data_ptr<scalar_t>(), x.data_ptr<scalar_t>(), k.data_ptr<scalar_t>(), p
|
237 |
+
);
|
238 |
+
|
239 |
+
break;
|
240 |
+
|
241 |
+
case 3:
|
242 |
+
upfirdn2d_kernel<scalar_t, 2, 2, 1, 1, 4, 4, 16, 64><<<grid_size, block_size, 0, stream>>>(
|
243 |
+
out.data_ptr<scalar_t>(), x.data_ptr<scalar_t>(), k.data_ptr<scalar_t>(), p
|
244 |
+
);
|
245 |
+
|
246 |
+
break;
|
247 |
+
|
248 |
+
case 4:
|
249 |
+
upfirdn2d_kernel<scalar_t, 2, 2, 1, 1, 2, 2, 16, 64><<<grid_size, block_size, 0, stream>>>(
|
250 |
+
out.data_ptr<scalar_t>(), x.data_ptr<scalar_t>(), k.data_ptr<scalar_t>(), p
|
251 |
+
);
|
252 |
+
|
253 |
+
break;
|
254 |
+
|
255 |
+
case 5:
|
256 |
+
upfirdn2d_kernel<scalar_t, 1, 1, 2, 2, 4, 4, 8, 32><<<grid_size, block_size, 0, stream>>>(
|
257 |
+
out.data_ptr<scalar_t>(), x.data_ptr<scalar_t>(), k.data_ptr<scalar_t>(), p
|
258 |
+
);
|
259 |
+
|
260 |
+
break;
|
261 |
+
|
262 |
+
case 6:
|
263 |
+
upfirdn2d_kernel<scalar_t, 1, 1, 2, 2, 4, 4, 8, 32><<<grid_size, block_size, 0, stream>>>(
|
264 |
+
out.data_ptr<scalar_t>(), x.data_ptr<scalar_t>(), k.data_ptr<scalar_t>(), p
|
265 |
+
);
|
266 |
+
|
267 |
+
break;
|
268 |
+
}
|
269 |
+
});
|
270 |
+
|
271 |
+
return out;
|
272 |
+
}
|
face_parse/blocks.py
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
import torch
|
3 |
+
import torch.nn as nn
|
4 |
+
from torch.nn.parameter import Parameter
|
5 |
+
from torch.nn import functional as F
|
6 |
+
import numpy as np
|
7 |
+
|
8 |
+
class NormLayer(nn.Module):
|
9 |
+
"""Normalization Layers.
|
10 |
+
------------
|
11 |
+
# Arguments
|
12 |
+
- channels: input channels, for batch norm and instance norm.
|
13 |
+
- input_size: input shape without batch size, for layer norm.
|
14 |
+
"""
|
15 |
+
def __init__(self, channels, normalize_shape=None, norm_type='bn', ref_channels=None):
|
16 |
+
super(NormLayer, self).__init__()
|
17 |
+
norm_type = norm_type.lower()
|
18 |
+
self.norm_type = norm_type
|
19 |
+
if norm_type == 'bn':
|
20 |
+
self.norm = nn.BatchNorm2d(channels, affine=True)
|
21 |
+
elif norm_type == 'in':
|
22 |
+
self.norm = nn.InstanceNorm2d(channels, affine=False)
|
23 |
+
elif norm_type == 'gn':
|
24 |
+
self.norm = nn.GroupNorm(32, channels, affine=True)
|
25 |
+
elif norm_type == 'pixel':
|
26 |
+
self.norm = lambda x: F.normalize(x, p=2, dim=1)
|
27 |
+
elif norm_type == 'layer':
|
28 |
+
self.norm = nn.LayerNorm(normalize_shape)
|
29 |
+
elif norm_type == 'none':
|
30 |
+
self.norm = lambda x: x*1.0
|
31 |
+
else:
|
32 |
+
assert 1==0, 'Norm type {} not support.'.format(norm_type)
|
33 |
+
|
34 |
+
def forward(self, x, ref=None):
|
35 |
+
if self.norm_type == 'spade':
|
36 |
+
return self.norm(x, ref)
|
37 |
+
else:
|
38 |
+
return self.norm(x)
|
39 |
+
|
40 |
+
|
41 |
+
class ReluLayer(nn.Module):
|
42 |
+
"""Relu Layer.
|
43 |
+
------------
|
44 |
+
# Arguments
|
45 |
+
- relu type: type of relu layer, candidates are
|
46 |
+
- ReLU
|
47 |
+
- LeakyReLU: default relu slope 0.2
|
48 |
+
- PRelu
|
49 |
+
- SELU
|
50 |
+
- none: direct pass
|
51 |
+
"""
|
52 |
+
def __init__(self, channels, relu_type='relu'):
|
53 |
+
super(ReluLayer, self).__init__()
|
54 |
+
relu_type = relu_type.lower()
|
55 |
+
if relu_type == 'relu':
|
56 |
+
self.func = nn.ReLU(True)
|
57 |
+
elif relu_type == 'leakyrelu':
|
58 |
+
self.func = nn.LeakyReLU(0.2, inplace=True)
|
59 |
+
elif relu_type == 'prelu':
|
60 |
+
self.func = nn.PReLU(channels)
|
61 |
+
elif relu_type == 'selu':
|
62 |
+
self.func = nn.SELU(True)
|
63 |
+
elif relu_type == 'none':
|
64 |
+
self.func = lambda x: x*1.0
|
65 |
+
else:
|
66 |
+
assert 1==0, 'Relu type {} not support.'.format(relu_type)
|
67 |
+
|
68 |
+
def forward(self, x):
|
69 |
+
return self.func(x)
|
70 |
+
|
71 |
+
|
72 |
+
class ConvLayer(nn.Module):
|
73 |
+
def __init__(self, in_channels, out_channels, kernel_size=3, scale='none', norm_type='none', relu_type='none', use_pad=True, bias=True):
|
74 |
+
super(ConvLayer, self).__init__()
|
75 |
+
self.use_pad = use_pad
|
76 |
+
self.norm_type = norm_type
|
77 |
+
if norm_type in ['bn']:
|
78 |
+
bias = False
|
79 |
+
|
80 |
+
stride = 2 if scale == 'down' else 1
|
81 |
+
|
82 |
+
self.scale_func = lambda x: x
|
83 |
+
if scale == 'up':
|
84 |
+
self.scale_func = lambda x: nn.functional.interpolate(x, scale_factor=2, mode='nearest')
|
85 |
+
|
86 |
+
self.reflection_pad = nn.ReflectionPad2d(int(np.ceil((kernel_size - 1.)/2)))
|
87 |
+
self.conv2d = nn.Conv2d(in_channels, out_channels, kernel_size, stride, bias=bias)
|
88 |
+
|
89 |
+
self.relu = ReluLayer(out_channels, relu_type)
|
90 |
+
self.norm = NormLayer(out_channels, norm_type=norm_type)
|
91 |
+
|
92 |
+
def forward(self, x):
|
93 |
+
out = self.scale_func(x)
|
94 |
+
if self.use_pad:
|
95 |
+
out = self.reflection_pad(out)
|
96 |
+
out = self.conv2d(out)
|
97 |
+
out = self.norm(out)
|
98 |
+
out = self.relu(out)
|
99 |
+
return out
|
100 |
+
|
101 |
+
|
102 |
+
class ResidualBlock(nn.Module):
|
103 |
+
"""
|
104 |
+
Residual block recommended in: http://torch.ch/blog/2016/02/04/resnets.html
|
105 |
+
"""
|
106 |
+
def __init__(self, c_in, c_out, relu_type='prelu', norm_type='bn', scale='none'):
|
107 |
+
super(ResidualBlock, self).__init__()
|
108 |
+
|
109 |
+
if scale == 'none' and c_in == c_out:
|
110 |
+
self.shortcut_func = lambda x: x
|
111 |
+
else:
|
112 |
+
self.shortcut_func = ConvLayer(c_in, c_out, 3, scale)
|
113 |
+
|
114 |
+
scale_config_dict = {'down': ['none', 'down'], 'up': ['up', 'none'], 'none': ['none', 'none']}
|
115 |
+
scale_conf = scale_config_dict[scale]
|
116 |
+
|
117 |
+
self.conv1 = ConvLayer(c_in, c_out, 3, scale_conf[0], norm_type=norm_type, relu_type=relu_type)
|
118 |
+
self.conv2 = ConvLayer(c_out, c_out, 3, scale_conf[1], norm_type=norm_type, relu_type='none')
|
119 |
+
|
120 |
+
def forward(self, x):
|
121 |
+
identity = self.shortcut_func(x)
|
122 |
+
|
123 |
+
res = self.conv1(x)
|
124 |
+
res = self.conv2(res)
|
125 |
+
return identity + res
|
126 |
+
|
127 |
+
|
face_parse/face_parsing.py
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@paper: GAN Prior Embedded Network for Blind Face Restoration in the Wild (CVPR2021)
|
3 |
+
@author: yangxy (yangtao9009@gmail.com)
|
4 |
+
'''
|
5 |
+
import os
|
6 |
+
import cv2
|
7 |
+
import torch
|
8 |
+
import numpy as np
|
9 |
+
from parse_model import ParseNet
|
10 |
+
import torch.nn.functional as F
|
11 |
+
|
12 |
+
class FaceParse(object):
|
13 |
+
def __init__(self, base_dir='./', model='ParseNet-latest', device='cuda'):
|
14 |
+
self.mfile = os.path.join(base_dir, 'weights', model+'.pth')
|
15 |
+
self.size = 512
|
16 |
+
self.device = device
|
17 |
+
|
18 |
+
'''
|
19 |
+
0: 'background' 1: 'skin' 2: 'nose'
|
20 |
+
3: 'eye_g' 4: 'l_eye' 5: 'r_eye'
|
21 |
+
6: 'l_brow' 7: 'r_brow' 8: 'l_ear'
|
22 |
+
9: 'r_ear' 10: 'mouth' 11: 'u_lip'
|
23 |
+
12: 'l_lip' 13: 'hair' 14: 'hat'
|
24 |
+
15: 'ear_r' 16: 'neck_l' 17: 'neck'
|
25 |
+
18: 'cloth'
|
26 |
+
'''
|
27 |
+
#self.MASK_COLORMAP = [[0, 0, 0], [204, 0, 0], [76, 153, 0], [204, 204, 0], [51, 51, 255], [204, 0, 204], [0, 255, 255], [255, 204, 204], [102, 51, 0], [255, 0, 0], [102, 204, 0], [255, 255, 0], [0, 0, 153], [0, 0, 204], [255, 51, 153], [0, 204, 204], [0, 51, 0], [255, 153, 51], [0, 204, 0]]
|
28 |
+
#self.#MASK_COLORMAP = [[0, 0, 0], [204, 0, 0], [76, 153, 0], [204, 204, 0], [51, 51, 255], [204, 0, 204], [0, 255, 255], [255, 204, 204], [102, 51, 0], [255, 0, 0], [102, 204, 0], [255, 255, 0], [0, 0, 153], [0, 0, 204], [255, 51, 153], [0, 204, 204], [0, 51, 0], [255, 153, 51], [0, 204, 0]] = [[0, 0, 0], [204, 0, 0], [76, 153, 0], [204, 204, 0], [51, 51, 255], [204, 0, 204], [0, 255, 255], [255, 204, 204], [102, 51, 0], [255, 0, 0], [102, 204, 0], [255, 255, 0], [0, 0, 153], [0, 0, 204], [255, 51, 153], [0, 204, 204], [0, 51, 0], [0, 0, 0], [0, 0, 0]]
|
29 |
+
self.MASK_COLORMAP = [0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 0, 0, 0]
|
30 |
+
self.load_model()
|
31 |
+
|
32 |
+
def load_model(self):
|
33 |
+
self.faceparse = ParseNet(self.size, self.size, 32, 64, 19, norm_type='bn', relu_type='LeakyReLU', ch_range=[32, 256])
|
34 |
+
self.faceparse.load_state_dict(torch.load(self.mfile, map_location=torch.device('cpu')))
|
35 |
+
self.faceparse.to(self.device)
|
36 |
+
self.faceparse.eval()
|
37 |
+
|
38 |
+
def process(self, im):
|
39 |
+
im = cv2.resize(im, (self.size, self.size))
|
40 |
+
imt = self.img2tensor(im)
|
41 |
+
pred_mask, sr_img_tensor = self.faceparse(imt)
|
42 |
+
mask = self.tenor2mask(pred_mask)
|
43 |
+
|
44 |
+
return mask
|
45 |
+
|
46 |
+
def process_tensor(self, imt):
|
47 |
+
imt = F.interpolate(imt.flip(1)*2-1, (self.size, self.size))
|
48 |
+
pred_mask, sr_img_tensor = self.faceparse(imt)
|
49 |
+
|
50 |
+
mask = pred_mask.argmax(dim=1)
|
51 |
+
for idx, color in enumerate(self.MASK_COLORMAP):
|
52 |
+
mask = torch.where(mask==idx, color, mask)
|
53 |
+
#mask = mask.repeat(3, 1, 1).unsqueeze(0) #.cpu().float().numpy()
|
54 |
+
mask = mask.unsqueeze(0)
|
55 |
+
|
56 |
+
return mask
|
57 |
+
|
58 |
+
def img2tensor(self, img):
|
59 |
+
img = img[..., ::-1]
|
60 |
+
img = img / 255. * 2 - 1
|
61 |
+
img_tensor = torch.from_numpy(img.transpose(2, 0, 1)).unsqueeze(0).to(self.device)
|
62 |
+
return img_tensor.float()
|
63 |
+
|
64 |
+
def tenor2mask(self, tensor):
|
65 |
+
if len(tensor.shape) < 4:
|
66 |
+
tensor = tensor.unsqueeze(0)
|
67 |
+
if tensor.shape[1] > 1:
|
68 |
+
tensor = tensor.argmax(dim=1)
|
69 |
+
|
70 |
+
tensor = tensor.squeeze(1).data.cpu().numpy()
|
71 |
+
color_maps = []
|
72 |
+
for t in tensor:
|
73 |
+
#tmp_img = np.zeros(tensor.shape[1:] + (3,))
|
74 |
+
tmp_img = np.zeros(tensor.shape[1:])
|
75 |
+
for idx, color in enumerate(self.MASK_COLORMAP):
|
76 |
+
tmp_img[t == idx] = color
|
77 |
+
color_maps.append(tmp_img.astype(np.uint8))
|
78 |
+
return color_maps
|
face_parse/mask.png
ADDED
face_parse/parse_model.py
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'''
|
2 |
+
@Created by chaofengc (chaofenghust@gmail.com)
|
3 |
+
|
4 |
+
@Modified by yangxy (yangtao9009@gmail.com)
|
5 |
+
'''
|
6 |
+
|
7 |
+
from blocks import *
|
8 |
+
import torch
|
9 |
+
from torch import nn
|
10 |
+
import numpy as np
|
11 |
+
|
12 |
+
def define_P(in_size=512, out_size=512, min_feat_size=32, relu_type='LeakyReLU', isTrain=False, weight_path=None):
|
13 |
+
net = ParseNet(in_size, out_size, min_feat_size, 64, 19, norm_type='bn', relu_type=relu_type, ch_range=[32, 256])
|
14 |
+
if not isTrain:
|
15 |
+
net.eval()
|
16 |
+
if weight_path is not None:
|
17 |
+
net.load_state_dict(torch.load(weight_path))
|
18 |
+
return net
|
19 |
+
|
20 |
+
|
21 |
+
class ParseNet(nn.Module):
|
22 |
+
def __init__(self,
|
23 |
+
in_size=128,
|
24 |
+
out_size=128,
|
25 |
+
min_feat_size=32,
|
26 |
+
base_ch=64,
|
27 |
+
parsing_ch=19,
|
28 |
+
res_depth=10,
|
29 |
+
relu_type='prelu',
|
30 |
+
norm_type='bn',
|
31 |
+
ch_range=[32, 512],
|
32 |
+
):
|
33 |
+
super().__init__()
|
34 |
+
self.res_depth = res_depth
|
35 |
+
act_args = {'norm_type': norm_type, 'relu_type': relu_type}
|
36 |
+
min_ch, max_ch = ch_range
|
37 |
+
|
38 |
+
ch_clip = lambda x: max(min_ch, min(x, max_ch))
|
39 |
+
min_feat_size = min(in_size, min_feat_size)
|
40 |
+
|
41 |
+
down_steps = int(np.log2(in_size//min_feat_size))
|
42 |
+
up_steps = int(np.log2(out_size//min_feat_size))
|
43 |
+
|
44 |
+
# =============== define encoder-body-decoder ====================
|
45 |
+
self.encoder = []
|
46 |
+
self.encoder.append(ConvLayer(3, base_ch, 3, 1))
|
47 |
+
head_ch = base_ch
|
48 |
+
for i in range(down_steps):
|
49 |
+
cin, cout = ch_clip(head_ch), ch_clip(head_ch * 2)
|
50 |
+
self.encoder.append(ResidualBlock(cin, cout, scale='down', **act_args))
|
51 |
+
head_ch = head_ch * 2
|
52 |
+
|
53 |
+
self.body = []
|
54 |
+
for i in range(res_depth):
|
55 |
+
self.body.append(ResidualBlock(ch_clip(head_ch), ch_clip(head_ch), **act_args))
|
56 |
+
|
57 |
+
self.decoder = []
|
58 |
+
for i in range(up_steps):
|
59 |
+
cin, cout = ch_clip(head_ch), ch_clip(head_ch // 2)
|
60 |
+
self.decoder.append(ResidualBlock(cin, cout, scale='up', **act_args))
|
61 |
+
head_ch = head_ch // 2
|
62 |
+
|
63 |
+
self.encoder = nn.Sequential(*self.encoder)
|
64 |
+
self.body = nn.Sequential(*self.body)
|
65 |
+
self.decoder = nn.Sequential(*self.decoder)
|
66 |
+
self.out_img_conv = ConvLayer(ch_clip(head_ch), 3)
|
67 |
+
self.out_mask_conv = ConvLayer(ch_clip(head_ch), parsing_ch)
|
68 |
+
|
69 |
+
def forward(self, x):
|
70 |
+
feat = self.encoder(x)
|
71 |
+
x = feat + self.body(feat)
|
72 |
+
x = self.decoder(x)
|
73 |
+
out_img = self.out_img_conv(x)
|
74 |
+
out_mask = self.out_mask_conv(x)
|
75 |
+
return out_mask, out_img
|
76 |
+
|
77 |
+
|
face_parse/test.png
ADDED
loss/helpers.py
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from collections import namedtuple
|
2 |
+
import torch
|
3 |
+
from torch.nn import Conv2d, BatchNorm2d, PReLU, ReLU, Sigmoid, MaxPool2d, AdaptiveAvgPool2d, Sequential, Module
|
4 |
+
|
5 |
+
"""
|
6 |
+
ArcFace implementation from [TreB1eN](https://github.com/TreB1eN/InsightFace_Pytorch)
|
7 |
+
"""
|
8 |
+
|
9 |
+
|
10 |
+
class Flatten(Module):
|
11 |
+
def forward(self, input):
|
12 |
+
return input.view(input.size(0), -1)
|
13 |
+
|
14 |
+
|
15 |
+
def l2_norm(input, axis=1):
|
16 |
+
norm = torch.norm(input, 2, axis, True)
|
17 |
+
output = torch.div(input, norm)
|
18 |
+
return output
|
19 |
+
|
20 |
+
|
21 |
+
class Bottleneck(namedtuple('Block', ['in_channel', 'depth', 'stride'])):
|
22 |
+
""" A named tuple describing a ResNet block. """
|
23 |
+
|
24 |
+
|
25 |
+
def get_block(in_channel, depth, num_units, stride=2):
|
26 |
+
return [Bottleneck(in_channel, depth, stride)] + [Bottleneck(depth, depth, 1) for i in range(num_units - 1)]
|
27 |
+
|
28 |
+
|
29 |
+
def get_blocks(num_layers):
|
30 |
+
if num_layers == 50:
|
31 |
+
blocks = [
|
32 |
+
get_block(in_channel=64, depth=64, num_units=3),
|
33 |
+
get_block(in_channel=64, depth=128, num_units=4),
|
34 |
+
get_block(in_channel=128, depth=256, num_units=14),
|
35 |
+
get_block(in_channel=256, depth=512, num_units=3)
|
36 |
+
]
|
37 |
+
elif num_layers == 100:
|
38 |
+
blocks = [
|
39 |
+
get_block(in_channel=64, depth=64, num_units=3),
|
40 |
+
get_block(in_channel=64, depth=128, num_units=13),
|
41 |
+
get_block(in_channel=128, depth=256, num_units=30),
|
42 |
+
get_block(in_channel=256, depth=512, num_units=3)
|
43 |
+
]
|
44 |
+
elif num_layers == 152:
|
45 |
+
blocks = [
|
46 |
+
get_block(in_channel=64, depth=64, num_units=3),
|
47 |
+
get_block(in_channel=64, depth=128, num_units=8),
|
48 |
+
get_block(in_channel=128, depth=256, num_units=36),
|
49 |
+
get_block(in_channel=256, depth=512, num_units=3)
|
50 |
+
]
|
51 |
+
else:
|
52 |
+
raise ValueError("Invalid number of layers: {}. Must be one of [50, 100, 152]".format(num_layers))
|
53 |
+
return blocks
|
54 |
+
|
55 |
+
|
56 |
+
class SEModule(Module):
|
57 |
+
def __init__(self, channels, reduction):
|
58 |
+
super(SEModule, self).__init__()
|
59 |
+
self.avg_pool = AdaptiveAvgPool2d(1)
|
60 |
+
self.fc1 = Conv2d(channels, channels // reduction, kernel_size=1, padding=0, bias=False)
|
61 |
+
self.relu = ReLU(inplace=True)
|
62 |
+
self.fc2 = Conv2d(channels // reduction, channels, kernel_size=1, padding=0, bias=False)
|
63 |
+
self.sigmoid = Sigmoid()
|
64 |
+
|
65 |
+
def forward(self, x):
|
66 |
+
module_input = x
|
67 |
+
x = self.avg_pool(x)
|
68 |
+
x = self.fc1(x)
|
69 |
+
x = self.relu(x)
|
70 |
+
x = self.fc2(x)
|
71 |
+
x = self.sigmoid(x)
|
72 |
+
return module_input * x
|
73 |
+
|
74 |
+
|
75 |
+
class bottleneck_IR(Module):
|
76 |
+
def __init__(self, in_channel, depth, stride):
|
77 |
+
super(bottleneck_IR, self).__init__()
|
78 |
+
if in_channel == depth:
|
79 |
+
self.shortcut_layer = MaxPool2d(1, stride)
|
80 |
+
else:
|
81 |
+
self.shortcut_layer = Sequential(
|
82 |
+
Conv2d(in_channel, depth, (1, 1), stride, bias=False),
|
83 |
+
BatchNorm2d(depth)
|
84 |
+
)
|
85 |
+
self.res_layer = Sequential(
|
86 |
+
BatchNorm2d(in_channel),
|
87 |
+
Conv2d(in_channel, depth, (3, 3), (1, 1), 1, bias=False), PReLU(depth),
|
88 |
+
Conv2d(depth, depth, (3, 3), stride, 1, bias=False), BatchNorm2d(depth)
|
89 |
+
)
|
90 |
+
|
91 |
+
def forward(self, x):
|
92 |
+
shortcut = self.shortcut_layer(x)
|
93 |
+
res = self.res_layer(x)
|
94 |
+
return res + shortcut
|
95 |
+
|
96 |
+
|
97 |
+
class bottleneck_IR_SE(Module):
|
98 |
+
def __init__(self, in_channel, depth, stride):
|
99 |
+
super(bottleneck_IR_SE, self).__init__()
|
100 |
+
if in_channel == depth:
|
101 |
+
self.shortcut_layer = MaxPool2d(1, stride)
|
102 |
+
else:
|
103 |
+
self.shortcut_layer = Sequential(
|
104 |
+
Conv2d(in_channel, depth, (1, 1), stride, bias=False),
|
105 |
+
BatchNorm2d(depth)
|
106 |
+
)
|
107 |
+
self.res_layer = Sequential(
|
108 |
+
BatchNorm2d(in_channel),
|
109 |
+
Conv2d(in_channel, depth, (3, 3), (1, 1), 1, bias=False),
|
110 |
+
PReLU(depth),
|
111 |
+
Conv2d(depth, depth, (3, 3), stride, 1, bias=False),
|
112 |
+
BatchNorm2d(depth),
|
113 |
+
SEModule(depth, 16)
|
114 |
+
)
|
115 |
+
|
116 |
+
def forward(self, x):
|
117 |
+
shortcut = self.shortcut_layer(x)
|
118 |
+
res = self.res_layer(x)
|
119 |
+
return res + shortcut
|
loss/id_loss.py
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import torch
|
3 |
+
from torch import nn
|
4 |
+
from model_irse import Backbone
|
5 |
+
|
6 |
+
class IDLoss(nn.Module):
|
7 |
+
def __init__(self, base_dir='./', device='cuda', ckpt_dict=None):
|
8 |
+
super(IDLoss, self).__init__()
|
9 |
+
print('Loading ResNet ArcFace')
|
10 |
+
self.facenet = Backbone(input_size=112, num_layers=50, drop_ratio=0.6, mode='ir_se').to(device)
|
11 |
+
if ckpt_dict is None:
|
12 |
+
self.facenet.load_state_dict(torch.load(os.path.join(base_dir, 'weights', 'model_ir_se50.pth'), map_location=torch.device('cpu')))
|
13 |
+
else:
|
14 |
+
self.facenet.load_state_dict(ckpt_dict)
|
15 |
+
self.face_pool = torch.nn.AdaptiveAvgPool2d((112, 112))
|
16 |
+
self.facenet.eval()
|
17 |
+
|
18 |
+
def extract_feats(self, x):
|
19 |
+
_, _, h, w = x.shape
|
20 |
+
assert h==w
|
21 |
+
ss = h//256
|
22 |
+
x = x[:, :, 35*ss:-33*ss, 32*ss:-36*ss] # Crop interesting region
|
23 |
+
x = self.face_pool(x)
|
24 |
+
x_feats = self.facenet(x)
|
25 |
+
return x_feats
|
26 |
+
|
27 |
+
def forward(self, y_hat, y, x):
|
28 |
+
n_samples = x.shape[0]
|
29 |
+
x_feats = self.extract_feats(x)
|
30 |
+
y_feats = self.extract_feats(y) # Otherwise use the feature from there
|
31 |
+
y_hat_feats = self.extract_feats(y_hat)
|
32 |
+
y_feats = y_feats.detach()
|
33 |
+
loss = 0
|
34 |
+
sim_improvement = 0
|
35 |
+
id_logs = []
|
36 |
+
count = 0
|
37 |
+
for i in range(n_samples):
|
38 |
+
diff_target = y_hat_feats[i].dot(y_feats[i])
|
39 |
+
diff_input = y_hat_feats[i].dot(x_feats[i])
|
40 |
+
diff_views = y_feats[i].dot(x_feats[i])
|
41 |
+
id_logs.append({'diff_target': float(diff_target),
|
42 |
+
'diff_input': float(diff_input),
|
43 |
+
'diff_views': float(diff_views)})
|
44 |
+
loss += 1 - diff_target
|
45 |
+
id_diff = float(diff_target) - float(diff_views)
|
46 |
+
sim_improvement += id_diff
|
47 |
+
count += 1
|
48 |
+
|
49 |
+
return loss / count, sim_improvement / count, id_logs
|
50 |
+
|
loss/model_irse.py
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from torch.nn import Linear, Conv2d, BatchNorm1d, BatchNorm2d, PReLU, Dropout, Sequential, Module
|
2 |
+
#from models.encoders.helpers import get_blocks, Flatten, bottleneck_IR, bottleneck_IR_SE, l2_norm
|
3 |
+
from helpers import get_blocks, Flatten, bottleneck_IR, bottleneck_IR_SE, l2_norm
|
4 |
+
|
5 |
+
"""
|
6 |
+
Modified Backbone implementation from [TreB1eN](https://github.com/TreB1eN/InsightFace_Pytorch)
|
7 |
+
"""
|
8 |
+
|
9 |
+
|
10 |
+
class Backbone(Module):
|
11 |
+
def __init__(self, input_size, num_layers, mode='ir', drop_ratio=0.4, affine=True):
|
12 |
+
super(Backbone, self).__init__()
|
13 |
+
assert input_size in [112, 224], "input_size should be 112 or 224"
|
14 |
+
assert num_layers in [50, 100, 152], "num_layers should be 50, 100 or 152"
|
15 |
+
assert mode in ['ir', 'ir_se'], "mode should be ir or ir_se"
|
16 |
+
blocks = get_blocks(num_layers)
|
17 |
+
if mode == 'ir':
|
18 |
+
unit_module = bottleneck_IR
|
19 |
+
elif mode == 'ir_se':
|
20 |
+
unit_module = bottleneck_IR_SE
|
21 |
+
self.input_layer = Sequential(Conv2d(3, 64, (3, 3), 1, 1, bias=False),
|
22 |
+
BatchNorm2d(64),
|
23 |
+
PReLU(64))
|
24 |
+
if input_size == 112:
|
25 |
+
self.output_layer = Sequential(BatchNorm2d(512),
|
26 |
+
Dropout(drop_ratio),
|
27 |
+
Flatten(),
|
28 |
+
Linear(512 * 7 * 7, 512),
|
29 |
+
BatchNorm1d(512, affine=affine))
|
30 |
+
else:
|
31 |
+
self.output_layer = Sequential(BatchNorm2d(512),
|
32 |
+
Dropout(drop_ratio),
|
33 |
+
Flatten(),
|
34 |
+
Linear(512 * 14 * 14, 512),
|
35 |
+
BatchNorm1d(512, affine=affine))
|
36 |
+
|
37 |
+
modules = []
|
38 |
+
for block in blocks:
|
39 |
+
for bottleneck in block:
|
40 |
+
modules.append(unit_module(bottleneck.in_channel,
|
41 |
+
bottleneck.depth,
|
42 |
+
bottleneck.stride))
|
43 |
+
self.body = Sequential(*modules)
|
44 |
+
|
45 |
+
def forward(self, x):
|
46 |
+
x = self.input_layer(x)
|
47 |
+
x = self.body(x)
|
48 |
+
x = self.output_layer(x)
|
49 |
+
return l2_norm(x)
|
50 |
+
|
51 |
+
|
52 |
+
def IR_50(input_size):
|
53 |
+
"""Constructs a ir-50 model."""
|
54 |
+
model = Backbone(input_size, num_layers=50, mode='ir', drop_ratio=0.4, affine=False)
|
55 |
+
return model
|
56 |
+
|
57 |
+
|
58 |
+
def IR_101(input_size):
|
59 |
+
"""Constructs a ir-101 model."""
|
60 |
+
model = Backbone(input_size, num_layers=100, mode='ir', drop_ratio=0.4, affine=False)
|
61 |
+
return model
|
62 |
+
|
63 |
+
|
64 |
+
def IR_152(input_size):
|
65 |
+
"""Constructs a ir-152 model."""
|
66 |
+
model = Backbone(input_size, num_layers=152, mode='ir', drop_ratio=0.4, affine=False)
|
67 |
+
return model
|
68 |
+
|
69 |
+
|
70 |
+
def IR_SE_50(input_size):
|
71 |
+
"""Constructs a ir_se-50 model."""
|
72 |
+
model = Backbone(input_size, num_layers=50, mode='ir_se', drop_ratio=0.4, affine=False)
|
73 |
+
return model
|
74 |
+
|
75 |
+
|
76 |
+
def IR_SE_101(input_size):
|
77 |
+
"""Constructs a ir_se-101 model."""
|
78 |
+
model = Backbone(input_size, num_layers=100, mode='ir_se', drop_ratio=0.4, affine=False)
|
79 |
+
return model
|
80 |
+
|
81 |
+
|
82 |
+
def IR_SE_152(input_size):
|
83 |
+
"""Constructs a ir_se-152 model."""
|
84 |
+
model = Backbone(input_size, num_layers=152, mode='ir_se', drop_ratio=0.4, affine=False)
|
85 |
+
return model
|
lpips/__init__.py
ADDED
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from __future__ import absolute_import
|
3 |
+
from __future__ import division
|
4 |
+
from __future__ import print_function
|
5 |
+
|
6 |
+
import numpy as np
|
7 |
+
import torch
|
8 |
+
# from torch.autograd import Variable
|
9 |
+
|
10 |
+
from lpips.trainer import *
|
11 |
+
from lpips.lpips import *
|
12 |
+
|
13 |
+
# class PerceptualLoss(torch.nn.Module):
|
14 |
+
# def __init__(self, model='lpips', net='alex', spatial=False, use_gpu=False, gpu_ids=[0], version='0.1'): # VGG using our perceptually-learned weights (LPIPS metric)
|
15 |
+
# # def __init__(self, model='net', net='vgg', use_gpu=True): # "default" way of using VGG as a perceptual loss
|
16 |
+
# super(PerceptualLoss, self).__init__()
|
17 |
+
# print('Setting up Perceptual loss...')
|
18 |
+
# self.use_gpu = use_gpu
|
19 |
+
# self.spatial = spatial
|
20 |
+
# self.gpu_ids = gpu_ids
|
21 |
+
# self.model = dist_model.DistModel()
|
22 |
+
# self.model.initialize(model=model, net=net, use_gpu=use_gpu, spatial=self.spatial, gpu_ids=gpu_ids, version=version)
|
23 |
+
# print('...[%s] initialized'%self.model.name())
|
24 |
+
# print('...Done')
|
25 |
+
|
26 |
+
# def forward(self, pred, target, normalize=False):
|
27 |
+
# """
|
28 |
+
# Pred and target are Variables.
|
29 |
+
# If normalize is True, assumes the images are between [0,1] and then scales them between [-1,+1]
|
30 |
+
# If normalize is False, assumes the images are already between [-1,+1]
|
31 |
+
|
32 |
+
# Inputs pred and target are Nx3xHxW
|
33 |
+
# Output pytorch Variable N long
|
34 |
+
# """
|
35 |
+
|
36 |
+
# if normalize:
|
37 |
+
# target = 2 * target - 1
|
38 |
+
# pred = 2 * pred - 1
|
39 |
+
|
40 |
+
# return self.model.forward(target, pred)
|
41 |
+
|
42 |
+
def normalize_tensor(in_feat,eps=1e-10):
|
43 |
+
norm_factor = torch.sqrt(torch.sum(in_feat**2,dim=1,keepdim=True))
|
44 |
+
return in_feat/(norm_factor+eps)
|
45 |
+
|
46 |
+
def l2(p0, p1, range=255.):
|
47 |
+
return .5*np.mean((p0 / range - p1 / range)**2)
|
48 |
+
|
49 |
+
def psnr(p0, p1, peak=255.):
|
50 |
+
return 10*np.log10(peak**2/np.mean((1.*p0-1.*p1)**2))
|
51 |
+
|
52 |
+
def dssim(p0, p1, range=255.):
|
53 |
+
from skimage.measure import compare_ssim
|
54 |
+
return (1 - compare_ssim(p0, p1, data_range=range, multichannel=True)) / 2.
|
55 |
+
|
56 |
+
def rgb2lab(in_img,mean_cent=False):
|
57 |
+
from skimage import color
|
58 |
+
img_lab = color.rgb2lab(in_img)
|
59 |
+
if(mean_cent):
|
60 |
+
img_lab[:,:,0] = img_lab[:,:,0]-50
|
61 |
+
return img_lab
|
62 |
+
|
63 |
+
def tensor2np(tensor_obj):
|
64 |
+
# change dimension of a tensor object into a numpy array
|
65 |
+
return tensor_obj[0].cpu().float().numpy().transpose((1,2,0))
|
66 |
+
|
67 |
+
def np2tensor(np_obj):
|
68 |
+
# change dimenion of np array into tensor array
|
69 |
+
return torch.Tensor(np_obj[:, :, :, np.newaxis].transpose((3, 2, 0, 1)))
|
70 |
+
|
71 |
+
def tensor2tensorlab(image_tensor,to_norm=True,mc_only=False):
|
72 |
+
# image tensor to lab tensor
|
73 |
+
from skimage import color
|
74 |
+
|
75 |
+
img = tensor2im(image_tensor)
|
76 |
+
img_lab = color.rgb2lab(img)
|
77 |
+
if(mc_only):
|
78 |
+
img_lab[:,:,0] = img_lab[:,:,0]-50
|
79 |
+
if(to_norm and not mc_only):
|
80 |
+
img_lab[:,:,0] = img_lab[:,:,0]-50
|
81 |
+
img_lab = img_lab/100.
|
82 |
+
|
83 |
+
return np2tensor(img_lab)
|
84 |
+
|
85 |
+
def tensorlab2tensor(lab_tensor,return_inbnd=False):
|
86 |
+
from skimage import color
|
87 |
+
import warnings
|
88 |
+
warnings.filterwarnings("ignore")
|
89 |
+
|
90 |
+
lab = tensor2np(lab_tensor)*100.
|
91 |
+
lab[:,:,0] = lab[:,:,0]+50
|
92 |
+
|
93 |
+
rgb_back = 255.*np.clip(color.lab2rgb(lab.astype('float')),0,1)
|
94 |
+
if(return_inbnd):
|
95 |
+
# convert back to lab, see if we match
|
96 |
+
lab_back = color.rgb2lab(rgb_back.astype('uint8'))
|
97 |
+
mask = 1.*np.isclose(lab_back,lab,atol=2.)
|
98 |
+
mask = np2tensor(np.prod(mask,axis=2)[:,:,np.newaxis])
|
99 |
+
return (im2tensor(rgb_back),mask)
|
100 |
+
else:
|
101 |
+
return im2tensor(rgb_back)
|
102 |
+
|
103 |
+
def load_image(path):
|
104 |
+
if(path[-3:] == 'dng'):
|
105 |
+
import rawpy
|
106 |
+
with rawpy.imread(path) as raw:
|
107 |
+
img = raw.postprocess()
|
108 |
+
elif(path[-3:]=='bmp' or path[-3:]=='jpg' or path[-3:]=='png'):
|
109 |
+
import cv2
|
110 |
+
return cv2.imread(path)[:,:,::-1]
|
111 |
+
else:
|
112 |
+
img = (255*plt.imread(path)[:,:,:3]).astype('uint8')
|
113 |
+
|
114 |
+
return img
|
115 |
+
|
116 |
+
def rgb2lab(input):
|
117 |
+
from skimage import color
|
118 |
+
return color.rgb2lab(input / 255.)
|
119 |
+
|
120 |
+
def tensor2im(image_tensor, imtype=np.uint8, cent=1., factor=255./2.):
|
121 |
+
image_numpy = image_tensor[0].cpu().float().numpy()
|
122 |
+
image_numpy = (np.transpose(image_numpy, (1, 2, 0)) + cent) * factor
|
123 |
+
return image_numpy.astype(imtype)
|
124 |
+
|
125 |
+
def im2tensor(image, imtype=np.uint8, cent=1., factor=255./2.):
|
126 |
+
return torch.Tensor((image / factor - cent)
|
127 |
+
[:, :, :, np.newaxis].transpose((3, 2, 0, 1)))
|
128 |
+
|
129 |
+
def tensor2vec(vector_tensor):
|
130 |
+
return vector_tensor.data.cpu().numpy()[:, :, 0, 0]
|
131 |
+
|
132 |
+
|
133 |
+
def tensor2im(image_tensor, imtype=np.uint8, cent=1., factor=255./2.):
|
134 |
+
# def tensor2im(image_tensor, imtype=np.uint8, cent=1., factor=1.):
|
135 |
+
image_numpy = image_tensor[0].cpu().float().numpy()
|
136 |
+
image_numpy = (np.transpose(image_numpy, (1, 2, 0)) + cent) * factor
|
137 |
+
return image_numpy.astype(imtype)
|
138 |
+
|
139 |
+
def im2tensor(image, imtype=np.uint8, cent=1., factor=255./2.):
|
140 |
+
# def im2tensor(image, imtype=np.uint8, cent=1., factor=1.):
|
141 |
+
return torch.Tensor((image / factor - cent)
|
142 |
+
[:, :, :, np.newaxis].transpose((3, 2, 0, 1)))
|
143 |
+
|
144 |
+
|
145 |
+
|
146 |
+
def voc_ap(rec, prec, use_07_metric=False):
|
147 |
+
""" ap = voc_ap(rec, prec, [use_07_metric])
|
148 |
+
Compute VOC AP given precision and recall.
|
149 |
+
If use_07_metric is true, uses the
|
150 |
+
VOC 07 11 point method (default:False).
|
151 |
+
"""
|
152 |
+
if use_07_metric:
|
153 |
+
# 11 point metric
|
154 |
+
ap = 0.
|
155 |
+
for t in np.arange(0., 1.1, 0.1):
|
156 |
+
if np.sum(rec >= t) == 0:
|
157 |
+
p = 0
|
158 |
+
else:
|
159 |
+
p = np.max(prec[rec >= t])
|
160 |
+
ap = ap + p / 11.
|
161 |
+
else:
|
162 |
+
# correct AP calculation
|
163 |
+
# first append sentinel values at the end
|
164 |
+
mrec = np.concatenate(([0.], rec, [1.]))
|
165 |
+
mpre = np.concatenate(([0.], prec, [0.]))
|
166 |
+
|
167 |
+
# compute the precision envelope
|
168 |
+
for i in range(mpre.size - 1, 0, -1):
|
169 |
+
mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
|
170 |
+
|
171 |
+
# to calculate area under PR curve, look for points
|
172 |
+
# where X axis (recall) changes value
|
173 |
+
i = np.where(mrec[1:] != mrec[:-1])[0]
|
174 |
+
|
175 |
+
# and sum (\Delta recall) * prec
|
176 |
+
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
|
177 |
+
return ap
|
178 |
+
|
lpips/lpips.py
ADDED
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from __future__ import absolute_import
|
3 |
+
|
4 |
+
import torch
|
5 |
+
import torch.nn as nn
|
6 |
+
import torch.nn.init as init
|
7 |
+
from torch.autograd import Variable
|
8 |
+
import numpy as np
|
9 |
+
from . import pretrained_networks as pn
|
10 |
+
import torch.nn
|
11 |
+
|
12 |
+
import lpips
|
13 |
+
|
14 |
+
def spatial_average(in_tens, keepdim=True):
|
15 |
+
return in_tens.mean([2,3],keepdim=keepdim)
|
16 |
+
|
17 |
+
def upsample(in_tens, out_HW=(64,64)): # assumes scale factor is same for H and W
|
18 |
+
in_H, in_W = in_tens.shape[2], in_tens.shape[3]
|
19 |
+
return nn.Upsample(size=out_HW, mode='bilinear', align_corners=False)(in_tens)
|
20 |
+
|
21 |
+
# Learned perceptual metric
|
22 |
+
class LPIPS(nn.Module):
|
23 |
+
def __init__(self, pretrained=True, net='alex', version='0.1', lpips=True, spatial=False,
|
24 |
+
pnet_rand=False, pnet_tune=False, use_dropout=True, model_path=None, eval_mode=True, verbose=True):
|
25 |
+
# lpips - [True] means with linear calibration on top of base network
|
26 |
+
# pretrained - [True] means load linear weights
|
27 |
+
|
28 |
+
super(LPIPS, self).__init__()
|
29 |
+
if(verbose):
|
30 |
+
print('Setting up [%s] perceptual loss: trunk [%s], v[%s], spatial [%s]'%
|
31 |
+
('LPIPS' if lpips else 'baseline', net, version, 'on' if spatial else 'off'))
|
32 |
+
|
33 |
+
self.pnet_type = net
|
34 |
+
self.pnet_tune = pnet_tune
|
35 |
+
self.pnet_rand = pnet_rand
|
36 |
+
self.spatial = spatial
|
37 |
+
self.lpips = lpips # false means baseline of just averaging all layers
|
38 |
+
self.version = version
|
39 |
+
self.scaling_layer = ScalingLayer()
|
40 |
+
|
41 |
+
if(self.pnet_type in ['vgg','vgg16']):
|
42 |
+
net_type = pn.vgg16
|
43 |
+
self.chns = [64,128,256,512,512]
|
44 |
+
elif(self.pnet_type=='alex'):
|
45 |
+
net_type = pn.alexnet
|
46 |
+
self.chns = [64,192,384,256,256]
|
47 |
+
elif(self.pnet_type=='squeeze'):
|
48 |
+
net_type = pn.squeezenet
|
49 |
+
self.chns = [64,128,256,384,384,512,512]
|
50 |
+
self.L = len(self.chns)
|
51 |
+
|
52 |
+
self.net = net_type(pretrained=not self.pnet_rand, requires_grad=self.pnet_tune)
|
53 |
+
|
54 |
+
if(lpips):
|
55 |
+
self.lin0 = NetLinLayer(self.chns[0], use_dropout=use_dropout)
|
56 |
+
self.lin1 = NetLinLayer(self.chns[1], use_dropout=use_dropout)
|
57 |
+
self.lin2 = NetLinLayer(self.chns[2], use_dropout=use_dropout)
|
58 |
+
self.lin3 = NetLinLayer(self.chns[3], use_dropout=use_dropout)
|
59 |
+
self.lin4 = NetLinLayer(self.chns[4], use_dropout=use_dropout)
|
60 |
+
self.lins = [self.lin0,self.lin1,self.lin2,self.lin3,self.lin4]
|
61 |
+
if(self.pnet_type=='squeeze'): # 7 layers for squeezenet
|
62 |
+
self.lin5 = NetLinLayer(self.chns[5], use_dropout=use_dropout)
|
63 |
+
self.lin6 = NetLinLayer(self.chns[6], use_dropout=use_dropout)
|
64 |
+
self.lins+=[self.lin5,self.lin6]
|
65 |
+
self.lins = nn.ModuleList(self.lins)
|
66 |
+
|
67 |
+
if(pretrained):
|
68 |
+
if(model_path is None):
|
69 |
+
import inspect
|
70 |
+
import os
|
71 |
+
model_path = os.path.abspath(os.path.join(inspect.getfile(self.__init__), '..', 'weights/v%s/%s.pth'%(version,net)))
|
72 |
+
|
73 |
+
if(verbose):
|
74 |
+
print('Loading model from: %s'%model_path)
|
75 |
+
self.load_state_dict(torch.load(model_path, map_location='cpu'), strict=False)
|
76 |
+
|
77 |
+
if(eval_mode):
|
78 |
+
self.eval()
|
79 |
+
|
80 |
+
def forward(self, in0, in1, retPerLayer=False, normalize=False):
|
81 |
+
if normalize: # turn on this flag if input is [0,1] so it can be adjusted to [-1, +1]
|
82 |
+
in0 = 2 * in0 - 1
|
83 |
+
in1 = 2 * in1 - 1
|
84 |
+
|
85 |
+
# v0.0 - original release had a bug, where input was not scaled
|
86 |
+
in0_input, in1_input = (self.scaling_layer(in0), self.scaling_layer(in1)) if self.version=='0.1' else (in0, in1)
|
87 |
+
outs0, outs1 = self.net.forward(in0_input), self.net.forward(in1_input)
|
88 |
+
feats0, feats1, diffs = {}, {}, {}
|
89 |
+
|
90 |
+
for kk in range(self.L):
|
91 |
+
feats0[kk], feats1[kk] = lpips.normalize_tensor(outs0[kk]), lpips.normalize_tensor(outs1[kk])
|
92 |
+
diffs[kk] = (feats0[kk]-feats1[kk])**2
|
93 |
+
|
94 |
+
if(self.lpips):
|
95 |
+
if(self.spatial):
|
96 |
+
res = [upsample(self.lins[kk](diffs[kk]), out_HW=in0.shape[2:]) for kk in range(self.L)]
|
97 |
+
else:
|
98 |
+
res = [spatial_average(self.lins[kk](diffs[kk]), keepdim=True) for kk in range(self.L)]
|
99 |
+
else:
|
100 |
+
if(self.spatial):
|
101 |
+
res = [upsample(diffs[kk].sum(dim=1,keepdim=True), out_HW=in0.shape[2:]) for kk in range(self.L)]
|
102 |
+
else:
|
103 |
+
res = [spatial_average(diffs[kk].sum(dim=1,keepdim=True), keepdim=True) for kk in range(self.L)]
|
104 |
+
|
105 |
+
val = res[0]
|
106 |
+
for l in range(1,self.L):
|
107 |
+
val += res[l]
|
108 |
+
|
109 |
+
# a = spatial_average(self.lins[kk](diffs[kk]), keepdim=True)
|
110 |
+
# b = torch.max(self.lins[kk](feats0[kk]**2))
|
111 |
+
# for kk in range(self.L):
|
112 |
+
# a += spatial_average(self.lins[kk](diffs[kk]), keepdim=True)
|
113 |
+
# b = torch.max(b,torch.max(self.lins[kk](feats0[kk]**2)))
|
114 |
+
# a = a/self.L
|
115 |
+
# from IPython import embed
|
116 |
+
# embed()
|
117 |
+
# return 10*torch.log10(b/a)
|
118 |
+
|
119 |
+
if(retPerLayer):
|
120 |
+
return (val, res)
|
121 |
+
else:
|
122 |
+
return val
|
123 |
+
|
124 |
+
|
125 |
+
class ScalingLayer(nn.Module):
|
126 |
+
def __init__(self):
|
127 |
+
super(ScalingLayer, self).__init__()
|
128 |
+
self.register_buffer('shift', torch.Tensor([-.030,-.088,-.188])[None,:,None,None])
|
129 |
+
self.register_buffer('scale', torch.Tensor([.458,.448,.450])[None,:,None,None])
|
130 |
+
|
131 |
+
def forward(self, inp):
|
132 |
+
return (inp - self.shift) / self.scale
|
133 |
+
|
134 |
+
|
135 |
+
class NetLinLayer(nn.Module):
|
136 |
+
''' A single linear layer which does a 1x1 conv '''
|
137 |
+
def __init__(self, chn_in, chn_out=1, use_dropout=False):
|
138 |
+
super(NetLinLayer, self).__init__()
|
139 |
+
|
140 |
+
layers = [nn.Dropout(),] if(use_dropout) else []
|
141 |
+
layers += [nn.Conv2d(chn_in, chn_out, 1, stride=1, padding=0, bias=False),]
|
142 |
+
self.model = nn.Sequential(*layers)
|
143 |
+
|
144 |
+
def forward(self, x):
|
145 |
+
return self.model(x)
|
146 |
+
|
147 |
+
class Dist2LogitLayer(nn.Module):
|
148 |
+
''' takes 2 distances, puts through fc layers, spits out value between [0,1] (if use_sigmoid is True) '''
|
149 |
+
def __init__(self, chn_mid=32, use_sigmoid=True):
|
150 |
+
super(Dist2LogitLayer, self).__init__()
|
151 |
+
|
152 |
+
layers = [nn.Conv2d(5, chn_mid, 1, stride=1, padding=0, bias=True),]
|
153 |
+
layers += [nn.LeakyReLU(0.2,True),]
|
154 |
+
layers += [nn.Conv2d(chn_mid, chn_mid, 1, stride=1, padding=0, bias=True),]
|
155 |
+
layers += [nn.LeakyReLU(0.2,True),]
|
156 |
+
layers += [nn.Conv2d(chn_mid, 1, 1, stride=1, padding=0, bias=True),]
|
157 |
+
if(use_sigmoid):
|
158 |
+
layers += [nn.Sigmoid(),]
|
159 |
+
self.model = nn.Sequential(*layers)
|
160 |
+
|
161 |
+
def forward(self,d0,d1,eps=0.1):
|
162 |
+
return self.model.forward(torch.cat((d0,d1,d0-d1,d0/(d1+eps),d1/(d0+eps)),dim=1))
|
163 |
+
|
164 |
+
class BCERankingLoss(nn.Module):
|
165 |
+
def __init__(self, chn_mid=32):
|
166 |
+
super(BCERankingLoss, self).__init__()
|
167 |
+
self.net = Dist2LogitLayer(chn_mid=chn_mid)
|
168 |
+
# self.parameters = list(self.net.parameters())
|
169 |
+
self.loss = torch.nn.BCELoss()
|
170 |
+
|
171 |
+
def forward(self, d0, d1, judge):
|
172 |
+
per = (judge+1.)/2.
|
173 |
+
self.logit = self.net.forward(d0,d1)
|
174 |
+
return self.loss(self.logit, per)
|
175 |
+
|
176 |
+
# L2, DSSIM metrics
|
177 |
+
class FakeNet(nn.Module):
|
178 |
+
def __init__(self, use_gpu=True, colorspace='Lab'):
|
179 |
+
super(FakeNet, self).__init__()
|
180 |
+
self.use_gpu = use_gpu
|
181 |
+
self.colorspace = colorspace
|
182 |
+
|
183 |
+
class L2(FakeNet):
|
184 |
+
def forward(self, in0, in1, retPerLayer=None):
|
185 |
+
assert(in0.size()[0]==1) # currently only supports batchSize 1
|
186 |
+
|
187 |
+
if(self.colorspace=='RGB'):
|
188 |
+
(N,C,X,Y) = in0.size()
|
189 |
+
value = torch.mean(torch.mean(torch.mean((in0-in1)**2,dim=1).view(N,1,X,Y),dim=2).view(N,1,1,Y),dim=3).view(N)
|
190 |
+
return value
|
191 |
+
elif(self.colorspace=='Lab'):
|
192 |
+
value = lpips.l2(lpips.tensor2np(lpips.tensor2tensorlab(in0.data,to_norm=False)),
|
193 |
+
lpips.tensor2np(lpips.tensor2tensorlab(in1.data,to_norm=False)), range=100.).astype('float')
|
194 |
+
ret_var = Variable( torch.Tensor((value,) ) )
|
195 |
+
if(self.use_gpu):
|
196 |
+
ret_var = ret_var.cuda()
|
197 |
+
return ret_var
|
198 |
+
|
199 |
+
class DSSIM(FakeNet):
|
200 |
+
|
201 |
+
def forward(self, in0, in1, retPerLayer=None):
|
202 |
+
assert(in0.size()[0]==1) # currently only supports batchSize 1
|
203 |
+
|
204 |
+
if(self.colorspace=='RGB'):
|
205 |
+
value = lpips.dssim(1.*lpips.tensor2im(in0.data), 1.*lpips.tensor2im(in1.data), range=255.).astype('float')
|
206 |
+
elif(self.colorspace=='Lab'):
|
207 |
+
value = lpips.dssim(lpips.tensor2np(lpips.tensor2tensorlab(in0.data,to_norm=False)),
|
208 |
+
lpips.tensor2np(lpips.tensor2tensorlab(in1.data,to_norm=False)), range=100.).astype('float')
|
209 |
+
ret_var = Variable( torch.Tensor((value,) ) )
|
210 |
+
if(self.use_gpu):
|
211 |
+
ret_var = ret_var.cuda()
|
212 |
+
return ret_var
|
213 |
+
|
214 |
+
def print_network(net):
|
215 |
+
num_params = 0
|
216 |
+
for param in net.parameters():
|
217 |
+
num_params += param.numel()
|
218 |
+
print('Network',net)
|
219 |
+
print('Total number of parameters: %d' % num_params)
|
lpips/pretrained_networks.py
ADDED
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from collections import namedtuple
|
2 |
+
import torch
|
3 |
+
from torchvision import models as tv
|
4 |
+
|
5 |
+
class squeezenet(torch.nn.Module):
|
6 |
+
def __init__(self, requires_grad=False, pretrained=True):
|
7 |
+
super(squeezenet, self).__init__()
|
8 |
+
pretrained_features = tv.squeezenet1_1(pretrained=pretrained).features
|
9 |
+
self.slice1 = torch.nn.Sequential()
|
10 |
+
self.slice2 = torch.nn.Sequential()
|
11 |
+
self.slice3 = torch.nn.Sequential()
|
12 |
+
self.slice4 = torch.nn.Sequential()
|
13 |
+
self.slice5 = torch.nn.Sequential()
|
14 |
+
self.slice6 = torch.nn.Sequential()
|
15 |
+
self.slice7 = torch.nn.Sequential()
|
16 |
+
self.N_slices = 7
|
17 |
+
for x in range(2):
|
18 |
+
self.slice1.add_module(str(x), pretrained_features[x])
|
19 |
+
for x in range(2,5):
|
20 |
+
self.slice2.add_module(str(x), pretrained_features[x])
|
21 |
+
for x in range(5, 8):
|
22 |
+
self.slice3.add_module(str(x), pretrained_features[x])
|
23 |
+
for x in range(8, 10):
|
24 |
+
self.slice4.add_module(str(x), pretrained_features[x])
|
25 |
+
for x in range(10, 11):
|
26 |
+
self.slice5.add_module(str(x), pretrained_features[x])
|
27 |
+
for x in range(11, 12):
|
28 |
+
self.slice6.add_module(str(x), pretrained_features[x])
|
29 |
+
for x in range(12, 13):
|
30 |
+
self.slice7.add_module(str(x), pretrained_features[x])
|
31 |
+
if not requires_grad:
|
32 |
+
for param in self.parameters():
|
33 |
+
param.requires_grad = False
|
34 |
+
|
35 |
+
def forward(self, X):
|
36 |
+
h = self.slice1(X)
|
37 |
+
h_relu1 = h
|
38 |
+
h = self.slice2(h)
|
39 |
+
h_relu2 = h
|
40 |
+
h = self.slice3(h)
|
41 |
+
h_relu3 = h
|
42 |
+
h = self.slice4(h)
|
43 |
+
h_relu4 = h
|
44 |
+
h = self.slice5(h)
|
45 |
+
h_relu5 = h
|
46 |
+
h = self.slice6(h)
|
47 |
+
h_relu6 = h
|
48 |
+
h = self.slice7(h)
|
49 |
+
h_relu7 = h
|
50 |
+
vgg_outputs = namedtuple("SqueezeOutputs", ['relu1','relu2','relu3','relu4','relu5','relu6','relu7'])
|
51 |
+
out = vgg_outputs(h_relu1,h_relu2,h_relu3,h_relu4,h_relu5,h_relu6,h_relu7)
|
52 |
+
|
53 |
+
return out
|
54 |
+
|
55 |
+
|
56 |
+
class alexnet(torch.nn.Module):
|
57 |
+
def __init__(self, requires_grad=False, pretrained=True):
|
58 |
+
super(alexnet, self).__init__()
|
59 |
+
alexnet_pretrained_features = tv.alexnet(pretrained=pretrained).features
|
60 |
+
self.slice1 = torch.nn.Sequential()
|
61 |
+
self.slice2 = torch.nn.Sequential()
|
62 |
+
self.slice3 = torch.nn.Sequential()
|
63 |
+
self.slice4 = torch.nn.Sequential()
|
64 |
+
self.slice5 = torch.nn.Sequential()
|
65 |
+
self.N_slices = 5
|
66 |
+
for x in range(2):
|
67 |
+
self.slice1.add_module(str(x), alexnet_pretrained_features[x])
|
68 |
+
for x in range(2, 5):
|
69 |
+
self.slice2.add_module(str(x), alexnet_pretrained_features[x])
|
70 |
+
for x in range(5, 8):
|
71 |
+
self.slice3.add_module(str(x), alexnet_pretrained_features[x])
|
72 |
+
for x in range(8, 10):
|
73 |
+
self.slice4.add_module(str(x), alexnet_pretrained_features[x])
|
74 |
+
for x in range(10, 12):
|
75 |
+
self.slice5.add_module(str(x), alexnet_pretrained_features[x])
|
76 |
+
if not requires_grad:
|
77 |
+
for param in self.parameters():
|
78 |
+
param.requires_grad = False
|
79 |
+
|
80 |
+
def forward(self, X):
|
81 |
+
h = self.slice1(X)
|
82 |
+
h_relu1 = h
|
83 |
+
h = self.slice2(h)
|
84 |
+
h_relu2 = h
|
85 |
+
h = self.slice3(h)
|
86 |
+
h_relu3 = h
|
87 |
+
h = self.slice4(h)
|
88 |
+
h_relu4 = h
|
89 |
+
h = self.slice5(h)
|
90 |
+
h_relu5 = h
|
91 |
+
alexnet_outputs = namedtuple("AlexnetOutputs", ['relu1', 'relu2', 'relu3', 'relu4', 'relu5'])
|
92 |
+
out = alexnet_outputs(h_relu1, h_relu2, h_relu3, h_relu4, h_relu5)
|
93 |
+
|
94 |
+
return out
|
95 |
+
|
96 |
+
class vgg16(torch.nn.Module):
|
97 |
+
def __init__(self, requires_grad=False, pretrained=True):
|
98 |
+
super(vgg16, self).__init__()
|
99 |
+
vgg_pretrained_features = tv.vgg16(pretrained=pretrained).features
|
100 |
+
self.slice1 = torch.nn.Sequential()
|
101 |
+
self.slice2 = torch.nn.Sequential()
|
102 |
+
self.slice3 = torch.nn.Sequential()
|
103 |
+
self.slice4 = torch.nn.Sequential()
|
104 |
+
self.slice5 = torch.nn.Sequential()
|
105 |
+
self.N_slices = 5
|
106 |
+
for x in range(4):
|
107 |
+
self.slice1.add_module(str(x), vgg_pretrained_features[x])
|
108 |
+
for x in range(4, 9):
|
109 |
+
self.slice2.add_module(str(x), vgg_pretrained_features[x])
|
110 |
+
for x in range(9, 16):
|
111 |
+
self.slice3.add_module(str(x), vgg_pretrained_features[x])
|
112 |
+
for x in range(16, 23):
|
113 |
+
self.slice4.add_module(str(x), vgg_pretrained_features[x])
|
114 |
+
for x in range(23, 30):
|
115 |
+
self.slice5.add_module(str(x), vgg_pretrained_features[x])
|
116 |
+
if not requires_grad:
|
117 |
+
for param in self.parameters():
|
118 |
+
param.requires_grad = False
|
119 |
+
|
120 |
+
def forward(self, X):
|
121 |
+
h = self.slice1(X)
|
122 |
+
h_relu1_2 = h
|
123 |
+
h = self.slice2(h)
|
124 |
+
h_relu2_2 = h
|
125 |
+
h = self.slice3(h)
|
126 |
+
h_relu3_3 = h
|
127 |
+
h = self.slice4(h)
|
128 |
+
h_relu4_3 = h
|
129 |
+
h = self.slice5(h)
|
130 |
+
h_relu5_3 = h
|
131 |
+
vgg_outputs = namedtuple("VggOutputs", ['relu1_2', 'relu2_2', 'relu3_3', 'relu4_3', 'relu5_3'])
|
132 |
+
out = vgg_outputs(h_relu1_2, h_relu2_2, h_relu3_3, h_relu4_3, h_relu5_3)
|
133 |
+
|
134 |
+
return out
|
135 |
+
|
136 |
+
|
137 |
+
|
138 |
+
class resnet(torch.nn.Module):
|
139 |
+
def __init__(self, requires_grad=False, pretrained=True, num=18):
|
140 |
+
super(resnet, self).__init__()
|
141 |
+
if(num==18):
|
142 |
+
self.net = tv.resnet18(pretrained=pretrained)
|
143 |
+
elif(num==34):
|
144 |
+
self.net = tv.resnet34(pretrained=pretrained)
|
145 |
+
elif(num==50):
|
146 |
+
self.net = tv.resnet50(pretrained=pretrained)
|
147 |
+
elif(num==101):
|
148 |
+
self.net = tv.resnet101(pretrained=pretrained)
|
149 |
+
elif(num==152):
|
150 |
+
self.net = tv.resnet152(pretrained=pretrained)
|
151 |
+
self.N_slices = 5
|
152 |
+
|
153 |
+
self.conv1 = self.net.conv1
|
154 |
+
self.bn1 = self.net.bn1
|
155 |
+
self.relu = self.net.relu
|
156 |
+
self.maxpool = self.net.maxpool
|
157 |
+
self.layer1 = self.net.layer1
|
158 |
+
self.layer2 = self.net.layer2
|
159 |
+
self.layer3 = self.net.layer3
|
160 |
+
self.layer4 = self.net.layer4
|
161 |
+
|
162 |
+
def forward(self, X):
|
163 |
+
h = self.conv1(X)
|
164 |
+
h = self.bn1(h)
|
165 |
+
h = self.relu(h)
|
166 |
+
h_relu1 = h
|
167 |
+
h = self.maxpool(h)
|
168 |
+
h = self.layer1(h)
|
169 |
+
h_conv2 = h
|
170 |
+
h = self.layer2(h)
|
171 |
+
h_conv3 = h
|
172 |
+
h = self.layer3(h)
|
173 |
+
h_conv4 = h
|
174 |
+
h = self.layer4(h)
|
175 |
+
h_conv5 = h
|
176 |
+
|
177 |
+
outputs = namedtuple("Outputs", ['relu1','conv2','conv3','conv4','conv5'])
|
178 |
+
out = outputs(h_relu1, h_conv2, h_conv3, h_conv4, h_conv5)
|
179 |
+
|
180 |
+
return out
|
lpips/trainer.py
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from __future__ import absolute_import
|
3 |
+
|
4 |
+
import numpy as np
|
5 |
+
import torch
|
6 |
+
from torch import nn
|
7 |
+
from collections import OrderedDict
|
8 |
+
from torch.autograd import Variable
|
9 |
+
from scipy.ndimage import zoom
|
10 |
+
from tqdm import tqdm
|
11 |
+
import lpips
|
12 |
+
import os
|
13 |
+
|
14 |
+
|
15 |
+
class Trainer():
|
16 |
+
def name(self):
|
17 |
+
return self.model_name
|
18 |
+
|
19 |
+
def initialize(self, model='lpips', net='alex', colorspace='Lab', pnet_rand=False, pnet_tune=False, model_path=None,
|
20 |
+
use_gpu=True, printNet=False, spatial=False,
|
21 |
+
is_train=False, lr=.0001, beta1=0.5, version='0.1', gpu_ids=[0]):
|
22 |
+
'''
|
23 |
+
INPUTS
|
24 |
+
model - ['lpips'] for linearly calibrated network
|
25 |
+
['baseline'] for off-the-shelf network
|
26 |
+
['L2'] for L2 distance in Lab colorspace
|
27 |
+
['SSIM'] for ssim in RGB colorspace
|
28 |
+
net - ['squeeze','alex','vgg']
|
29 |
+
model_path - if None, will look in weights/[NET_NAME].pth
|
30 |
+
colorspace - ['Lab','RGB'] colorspace to use for L2 and SSIM
|
31 |
+
use_gpu - bool - whether or not to use a GPU
|
32 |
+
printNet - bool - whether or not to print network architecture out
|
33 |
+
spatial - bool - whether to output an array containing varying distances across spatial dimensions
|
34 |
+
is_train - bool - [True] for training mode
|
35 |
+
lr - float - initial learning rate
|
36 |
+
beta1 - float - initial momentum term for adam
|
37 |
+
version - 0.1 for latest, 0.0 was original (with a bug)
|
38 |
+
gpu_ids - int array - [0] by default, gpus to use
|
39 |
+
'''
|
40 |
+
self.use_gpu = use_gpu
|
41 |
+
self.gpu_ids = gpu_ids
|
42 |
+
self.model = model
|
43 |
+
self.net = net
|
44 |
+
self.is_train = is_train
|
45 |
+
self.spatial = spatial
|
46 |
+
self.model_name = '%s [%s]'%(model,net)
|
47 |
+
|
48 |
+
if(self.model == 'lpips'): # pretrained net + linear layer
|
49 |
+
self.net = lpips.LPIPS(pretrained=not is_train, net=net, version=version, lpips=True, spatial=spatial,
|
50 |
+
pnet_rand=pnet_rand, pnet_tune=pnet_tune,
|
51 |
+
use_dropout=True, model_path=model_path, eval_mode=False)
|
52 |
+
elif(self.model=='baseline'): # pretrained network
|
53 |
+
self.net = lpips.LPIPS(pnet_rand=pnet_rand, net=net, lpips=False)
|
54 |
+
elif(self.model in ['L2','l2']):
|
55 |
+
self.net = lpips.L2(use_gpu=use_gpu,colorspace=colorspace) # not really a network, only for testing
|
56 |
+
self.model_name = 'L2'
|
57 |
+
elif(self.model in ['DSSIM','dssim','SSIM','ssim']):
|
58 |
+
self.net = lpips.DSSIM(use_gpu=use_gpu,colorspace=colorspace)
|
59 |
+
self.model_name = 'SSIM'
|
60 |
+
else:
|
61 |
+
raise ValueError("Model [%s] not recognized." % self.model)
|
62 |
+
|
63 |
+
self.parameters = list(self.net.parameters())
|
64 |
+
|
65 |
+
if self.is_train: # training mode
|
66 |
+
# extra network on top to go from distances (d0,d1) => predicted human judgment (h*)
|
67 |
+
self.rankLoss = lpips.BCERankingLoss()
|
68 |
+
self.parameters += list(self.rankLoss.net.parameters())
|
69 |
+
self.lr = lr
|
70 |
+
self.old_lr = lr
|
71 |
+
self.optimizer_net = torch.optim.Adam(self.parameters, lr=lr, betas=(beta1, 0.999))
|
72 |
+
else: # test mode
|
73 |
+
self.net.eval()
|
74 |
+
|
75 |
+
if(use_gpu):
|
76 |
+
self.net.to(gpu_ids[0])
|
77 |
+
self.net = torch.nn.DataParallel(self.net, device_ids=gpu_ids)
|
78 |
+
if(self.is_train):
|
79 |
+
self.rankLoss = self.rankLoss.to(device=gpu_ids[0]) # just put this on GPU0
|
80 |
+
|
81 |
+
if(printNet):
|
82 |
+
print('---------- Networks initialized -------------')
|
83 |
+
networks.print_network(self.net)
|
84 |
+
print('-----------------------------------------------')
|
85 |
+
|
86 |
+
def forward(self, in0, in1, retPerLayer=False):
|
87 |
+
''' Function computes the distance between image patches in0 and in1
|
88 |
+
INPUTS
|
89 |
+
in0, in1 - torch.Tensor object of shape Nx3xXxY - image patch scaled to [-1,1]
|
90 |
+
OUTPUT
|
91 |
+
computed distances between in0 and in1
|
92 |
+
'''
|
93 |
+
|
94 |
+
return self.net.forward(in0, in1, retPerLayer=retPerLayer)
|
95 |
+
|
96 |
+
# ***** TRAINING FUNCTIONS *****
|
97 |
+
def optimize_parameters(self):
|
98 |
+
self.forward_train()
|
99 |
+
self.optimizer_net.zero_grad()
|
100 |
+
self.backward_train()
|
101 |
+
self.optimizer_net.step()
|
102 |
+
self.clamp_weights()
|
103 |
+
|
104 |
+
def clamp_weights(self):
|
105 |
+
for module in self.net.modules():
|
106 |
+
if(hasattr(module, 'weight') and module.kernel_size==(1,1)):
|
107 |
+
module.weight.data = torch.clamp(module.weight.data,min=0)
|
108 |
+
|
109 |
+
def set_input(self, data):
|
110 |
+
self.input_ref = data['ref']
|
111 |
+
self.input_p0 = data['p0']
|
112 |
+
self.input_p1 = data['p1']
|
113 |
+
self.input_judge = data['judge']
|
114 |
+
|
115 |
+
if(self.use_gpu):
|
116 |
+
self.input_ref = self.input_ref.to(device=self.gpu_ids[0])
|
117 |
+
self.input_p0 = self.input_p0.to(device=self.gpu_ids[0])
|
118 |
+
self.input_p1 = self.input_p1.to(device=self.gpu_ids[0])
|
119 |
+
self.input_judge = self.input_judge.to(device=self.gpu_ids[0])
|
120 |
+
|
121 |
+
self.var_ref = Variable(self.input_ref,requires_grad=True)
|
122 |
+
self.var_p0 = Variable(self.input_p0,requires_grad=True)
|
123 |
+
self.var_p1 = Variable(self.input_p1,requires_grad=True)
|
124 |
+
|
125 |
+
def forward_train(self): # run forward pass
|
126 |
+
self.d0 = self.forward(self.var_ref, self.var_p0)
|
127 |
+
self.d1 = self.forward(self.var_ref, self.var_p1)
|
128 |
+
self.acc_r = self.compute_accuracy(self.d0,self.d1,self.input_judge)
|
129 |
+
|
130 |
+
self.var_judge = Variable(1.*self.input_judge).view(self.d0.size())
|
131 |
+
|
132 |
+
self.loss_total = self.rankLoss.forward(self.d0, self.d1, self.var_judge*2.-1.)
|
133 |
+
|
134 |
+
return self.loss_total
|
135 |
+
|
136 |
+
def backward_train(self):
|
137 |
+
torch.mean(self.loss_total).backward()
|
138 |
+
|
139 |
+
def compute_accuracy(self,d0,d1,judge):
|
140 |
+
''' d0, d1 are Variables, judge is a Tensor '''
|
141 |
+
d1_lt_d0 = (d1<d0).cpu().data.numpy().flatten()
|
142 |
+
judge_per = judge.cpu().numpy().flatten()
|
143 |
+
return d1_lt_d0*judge_per + (1-d1_lt_d0)*(1-judge_per)
|
144 |
+
|
145 |
+
def get_current_errors(self):
|
146 |
+
retDict = OrderedDict([('loss_total', self.loss_total.data.cpu().numpy()),
|
147 |
+
('acc_r', self.acc_r)])
|
148 |
+
|
149 |
+
for key in retDict.keys():
|
150 |
+
retDict[key] = np.mean(retDict[key])
|
151 |
+
|
152 |
+
return retDict
|
153 |
+
|
154 |
+
def get_current_visuals(self):
|
155 |
+
zoom_factor = 256/self.var_ref.data.size()[2]
|
156 |
+
|
157 |
+
ref_img = lpips.tensor2im(self.var_ref.data)
|
158 |
+
p0_img = lpips.tensor2im(self.var_p0.data)
|
159 |
+
p1_img = lpips.tensor2im(self.var_p1.data)
|
160 |
+
|
161 |
+
ref_img_vis = zoom(ref_img,[zoom_factor, zoom_factor, 1],order=0)
|
162 |
+
p0_img_vis = zoom(p0_img,[zoom_factor, zoom_factor, 1],order=0)
|
163 |
+
p1_img_vis = zoom(p1_img,[zoom_factor, zoom_factor, 1],order=0)
|
164 |
+
|
165 |
+
return OrderedDict([('ref', ref_img_vis),
|
166 |
+
('p0', p0_img_vis),
|
167 |
+
('p1', p1_img_vis)])
|
168 |
+
|
169 |
+
def save(self, path, label):
|
170 |
+
if(self.use_gpu):
|
171 |
+
self.save_network(self.net.module, path, '', label)
|
172 |
+
else:
|
173 |
+
self.save_network(self.net, path, '', label)
|
174 |
+
self.save_network(self.rankLoss.net, path, 'rank', label)
|
175 |
+
|
176 |
+
# helper saving function that can be used by subclasses
|
177 |
+
def save_network(self, network, path, network_label, epoch_label):
|
178 |
+
save_filename = '%s_net_%s.pth' % (epoch_label, network_label)
|
179 |
+
save_path = os.path.join(path, save_filename)
|
180 |
+
torch.save(network.state_dict(), save_path)
|
181 |
+
|
182 |
+
# helper loading function that can be used by subclasses
|
183 |
+
def load_network(self, network, network_label, epoch_label):
|
184 |
+
save_filename = '%s_net_%s.pth' % (epoch_label, network_label)
|
185 |
+
save_path = os.path.join(self.save_dir, save_filename)
|
186 |
+
print('Loading network from %s'%save_path)
|
187 |
+
network.load_state_dict(torch.load(save_path))
|
188 |
+
|
189 |
+
def update_learning_rate(self,nepoch_decay):
|
190 |
+
lrd = self.lr / nepoch_decay
|
191 |
+
lr = self.old_lr - lrd
|
192 |
+
|
193 |
+
for param_group in self.optimizer_net.param_groups:
|
194 |
+
param_group['lr'] = lr
|
195 |
+
|
196 |
+
print('update lr [%s] decay: %f -> %f' % (type,self.old_lr, lr))
|
197 |
+
self.old_lr = lr
|
198 |
+
|
199 |
+
|
200 |
+
def get_image_paths(self):
|
201 |
+
return self.image_paths
|
202 |
+
|
203 |
+
def save_done(self, flag=False):
|
204 |
+
np.save(os.path.join(self.save_dir, 'done_flag'),flag)
|
205 |
+
np.savetxt(os.path.join(self.save_dir, 'done_flag'),[flag,],fmt='%i')
|
206 |
+
|
207 |
+
|
208 |
+
def score_2afc_dataset(data_loader, func, name=''):
|
209 |
+
''' Function computes Two Alternative Forced Choice (2AFC) score using
|
210 |
+
distance function 'func' in dataset 'data_loader'
|
211 |
+
INPUTS
|
212 |
+
data_loader - CustomDatasetDataLoader object - contains a TwoAFCDataset inside
|
213 |
+
func - callable distance function - calling d=func(in0,in1) should take 2
|
214 |
+
pytorch tensors with shape Nx3xXxY, and return numpy array of length N
|
215 |
+
OUTPUTS
|
216 |
+
[0] - 2AFC score in [0,1], fraction of time func agrees with human evaluators
|
217 |
+
[1] - dictionary with following elements
|
218 |
+
d0s,d1s - N arrays containing distances between reference patch to perturbed patches
|
219 |
+
gts - N array in [0,1], preferred patch selected by human evaluators
|
220 |
+
(closer to "0" for left patch p0, "1" for right patch p1,
|
221 |
+
"0.6" means 60pct people preferred right patch, 40pct preferred left)
|
222 |
+
scores - N array in [0,1], corresponding to what percentage function agreed with humans
|
223 |
+
CONSTS
|
224 |
+
N - number of test triplets in data_loader
|
225 |
+
'''
|
226 |
+
|
227 |
+
d0s = []
|
228 |
+
d1s = []
|
229 |
+
gts = []
|
230 |
+
|
231 |
+
for data in tqdm(data_loader.load_data(), desc=name):
|
232 |
+
d0s+=func(data['ref'],data['p0']).data.cpu().numpy().flatten().tolist()
|
233 |
+
d1s+=func(data['ref'],data['p1']).data.cpu().numpy().flatten().tolist()
|
234 |
+
gts+=data['judge'].cpu().numpy().flatten().tolist()
|
235 |
+
|
236 |
+
d0s = np.array(d0s)
|
237 |
+
d1s = np.array(d1s)
|
238 |
+
gts = np.array(gts)
|
239 |
+
scores = (d0s<d1s)*(1.-gts) + (d1s<d0s)*gts + (d1s==d0s)*.5
|
240 |
+
|
241 |
+
return(np.mean(scores), dict(d0s=d0s,d1s=d1s,gts=gts,scores=scores))
|
242 |
+
|
243 |
+
def score_jnd_dataset(data_loader, func, name=''):
|
244 |
+
''' Function computes JND score using distance function 'func' in dataset 'data_loader'
|
245 |
+
INPUTS
|
246 |
+
data_loader - CustomDatasetDataLoader object - contains a JNDDataset inside
|
247 |
+
func - callable distance function - calling d=func(in0,in1) should take 2
|
248 |
+
pytorch tensors with shape Nx3xXxY, and return pytorch array of length N
|
249 |
+
OUTPUTS
|
250 |
+
[0] - JND score in [0,1], mAP score (area under precision-recall curve)
|
251 |
+
[1] - dictionary with following elements
|
252 |
+
ds - N array containing distances between two patches shown to human evaluator
|
253 |
+
sames - N array containing fraction of people who thought the two patches were identical
|
254 |
+
CONSTS
|
255 |
+
N - number of test triplets in data_loader
|
256 |
+
'''
|
257 |
+
|
258 |
+
ds = []
|
259 |
+
gts = []
|
260 |
+
|
261 |
+
for data in tqdm(data_loader.load_data(), desc=name):
|
262 |
+
ds+=func(data['p0'],data['p1']).data.cpu().numpy().tolist()
|
263 |
+
gts+=data['same'].cpu().numpy().flatten().tolist()
|
264 |
+
|
265 |
+
sames = np.array(gts)
|
266 |
+
ds = np.array(ds)
|
267 |
+
|
268 |
+
sorted_inds = np.argsort(ds)
|
269 |
+
ds_sorted = ds[sorted_inds]
|
270 |
+
sames_sorted = sames[sorted_inds]
|
271 |
+
|
272 |
+
TPs = np.cumsum(sames_sorted)
|
273 |
+
FPs = np.cumsum(1-sames_sorted)
|
274 |
+
FNs = np.sum(sames_sorted)-TPs
|
275 |
+
|
276 |
+
precs = TPs/(TPs+FPs)
|
277 |
+
recs = TPs/(TPs+FNs)
|
278 |
+
score = lpips.voc_ap(recs,precs)
|
279 |
+
|
280 |
+
return(score, dict(ds=ds,sames=sames))
|
lpips/weights/v0.0/alex.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:18720f55913d0af89042f13faa7e536a6ce1444a0914e6db9461355ece1e8cd5
|
3 |
+
size 5455
|
lpips/weights/v0.0/squeeze.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:c27abd3a0145541baa50990817df58d3759c3f8154949f42af3b59b4e042d0bf
|
3 |
+
size 10057
|
lpips/weights/v0.0/vgg.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:b9e4236260c3dd988fc79d2a48d645d885afcbb21f9fd595e6744cf7419b582c
|
3 |
+
size 6735
|