36
36
import pathlib
37
37
from argparse import ArgumentParser , ArgumentDefaultsHelpFormatter
38
38
39
- import torch
40
39
import numpy as np
41
- from scipy . misc import imread
40
+ import torch
42
41
from scipy import linalg
43
- from torch . autograd import Variable
42
+ from scipy . misc import imread
44
43
from torch .nn .functional import adaptive_avg_pool2d
45
- from tqdm import tqdm
44
+
45
+ try :
46
+ from tqdm import tqdm
47
+ except ImportError :
48
+ # If not tqdm is not available, provide a mock version of it
49
+ def tqdm (x ): return x
46
50
47
51
from inception import InceptionV3
48
52
@@ -65,8 +69,7 @@ def get_activations(files, model, batch_size=64, dims=2048,
65
69
"""Calculates the activations of the pool_3 layer for all images.
66
70
67
71
Params:
68
- -- images : Numpy array of dimension (n_images, 3, hi, wi). The values
69
- must lie between 0 and 1.
72
+ -- files : List of image files paths
70
73
-- model : Instance of inception model
71
74
-- batch_size : the images numpy array is split into batches with
72
75
batch size batch_size. A reasonable batch size depends
@@ -81,34 +84,32 @@ def get_activations(files, model, batch_size=64, dims=2048,
81
84
query tensor.
82
85
"""
83
86
model .eval ()
84
-
85
- #calculate number of total files
86
- d0 = len (files )
87
- if batch_size > d0 :
87
+
88
+ if batch_size > len (files ):
88
89
print (('Warning: batch size is bigger than the data size. '
89
90
'Setting batch size to data size' ))
90
- batch_size = d0
91
+ batch_size = len ( files )
91
92
92
- n_batches = d0 // batch_size
93
+ n_batches = len ( files ) // batch_size
93
94
n_used_imgs = n_batches * batch_size
94
95
95
96
pred_arr = np .empty ((n_used_imgs , dims ))
96
-
97
- #Add processbar to know process
97
+
98
98
for i in tqdm (range (n_batches )):
99
99
if verbose :
100
100
print ('\r Propagating batch %d/%d' % (i + 1 , n_batches ),
101
101
end = '' , flush = True )
102
102
start = i * batch_size
103
103
end = start + batch_size
104
-
105
- # real batch of images here
106
- images = np .array ([imread (str (fn )).astype (np .float32 ) for fn in files [start :end ]])
104
+
105
+ images = np .array ([imread (str (f )).astype (np .float32 )
106
+ for f in files [start :end ]])
107
+
108
+ # Reshape to (n_images, 3, height, width)
107
109
images = images .transpose ((0 , 3 , 1 , 2 ))
108
110
images /= 255
109
-
111
+
110
112
batch = torch .from_numpy (images ).type (torch .FloatTensor )
111
- batch = Variable (batch , volatile = True )
112
113
if cuda :
113
114
batch = batch .cuda ()
114
115
@@ -139,10 +140,10 @@ def calculate_frechet_distance(mu1, sigma1, mu2, sigma2, eps=1e-6):
139
140
-- mu1 : Numpy array containing the activations of a layer of the
140
141
inception net (like returned by the function 'get_predictions')
141
142
for generated samples.
142
- -- mu2 : The sample mean over activations, precalculated on an
143
+ -- mu2 : The sample mean over activations, precalculated on an
143
144
representative data set.
144
145
-- sigma1: The covariance matrix over activations for generated samples.
145
- -- sigma2: The covariance matrix over activations, precalculated on an
146
+ -- sigma2: The covariance matrix over activations, precalculated on an
146
147
representative data set.
147
148
148
149
Returns:
@@ -188,8 +189,7 @@ def calculate_activation_statistics(files, model, batch_size=64,
188
189
dims = 2048 , cuda = False , verbose = False ):
189
190
"""Calculation of the statistics used by the FID.
190
191
Params:
191
- -- images : Numpy array of dimension (n_images, 3, hi, wi). The values
192
- must lie between 0 and 1.
192
+ -- files : List of image files paths
193
193
-- model : Instance of inception model
194
194
-- batch_size : The images numpy array is split into batches with
195
195
batch size batch_size. A reasonable batch size
@@ -204,31 +204,20 @@ def calculate_activation_statistics(files, model, batch_size=64,
204
204
-- sigma : The covariance matrix of the activations of the pool_3 layer of
205
205
the inception model.
206
206
"""
207
- # Instead of load all the images, we pass the file name list
208
207
act = get_activations (files , model , batch_size , dims , cuda , verbose )
209
208
mu = np .mean (act , axis = 0 )
210
209
sigma = np .cov (act , rowvar = False )
211
210
return mu , sigma
212
211
213
212
214
- def _compute_statistics_of_path (path , model , batch_size , dims , cuda , flag ):
213
+ def _compute_statistics_of_path (path , model , batch_size , dims , cuda ):
215
214
if path .endswith ('.npz' ):
216
215
f = np .load (path )
217
216
m , s = f ['mu' ][:], f ['sigma' ][:]
218
217
f .close ()
219
218
else :
220
219
path = pathlib .Path (path )
221
220
files = list (path .glob ('*.jpg' )) + list (path .glob ('*.png' ))
222
-
223
- # imgs = np.array([imread(str(fn)).astype(np.float32) for fn in files])
224
-
225
- # Bring images to shape (B, 3, H, W)
226
- # imgs = imgs.transpose((0, 3, 1, 2))
227
-
228
- # Rescale images to be between 0 and 1
229
- # imgs /= 255
230
-
231
- # Instead of load all the images, we pass the file name list
232
221
m , s = calculate_activation_statistics (files , model , batch_size ,
233
222
dims , cuda )
234
223
@@ -246,11 +235,11 @@ def calculate_fid_given_paths(paths, batch_size, cuda, dims):
246
235
model = InceptionV3 ([block_idx ])
247
236
if cuda :
248
237
model .cuda ()
249
-
238
+
250
239
m1 , s1 = _compute_statistics_of_path (paths [0 ], model , batch_size ,
251
- dims , cuda , 1 )
240
+ dims , cuda )
252
241
m2 , s2 = _compute_statistics_of_path (paths [1 ], model , batch_size ,
253
- dims , cuda , 0 )
242
+ dims , cuda )
254
243
fid_value = calculate_frechet_distance (m1 , s1 , m2 , s2 )
255
244
256
245
return fid_value
0 commit comments