-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathutils.py
More file actions
178 lines (134 loc) · 6.08 KB
/
Copy pathutils.py
File metadata and controls
178 lines (134 loc) · 6.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
'''
Useful helper functions
'''
import os
from os.path import join as fullfile
import numpy as np
import cv2 as cv
import math
import random
import torch
import torch.nn as nn
import pytorch_ssim
from torch.utils.data import DataLoader
from CompenNeStPlusplusDataset import SimpleDataset
# set random number generators' seeds
def resetRNGseed(seed):
np.random.seed(seed)
random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
# read images using multi-thread
def readImgsMT(img_dir, size=None, index=None, gray_scale=False, normalize=False):
img_dataset = SimpleDataset(img_dir, index=index, size=size)
data_loader = DataLoader(img_dataset, batch_size=len(img_dataset), shuffle=False, drop_last=False, num_workers=4) # num_workers>1 only works for linux
for i, imgs in enumerate(data_loader):
# imgs.permute((0, 3, 1, 2)).to('cpu', dtype=torch.float32)/255
# convert to torch.Tensor
imgs = imgs.permute((0, 3, 1, 2)).float().div(255)
if gray_scale:
imgs = 0.2989*imgs[:,0]+0.5870*imgs[:,1]+0.1140*imgs[:,2] # same as MATLAB rgb2gray and OpenCV cvtColor
imgs = imgs[:, None]
# normalize to [-1, 1], should improve model convergence in early training stages.
if normalize:
imgs = (imgs-0.5) / 0.5
return imgs
# Same as np.repeat, while torch.repeat works as np.tile
def repeat_np(a, repeats, dim):
'''
Substitute for numpy's repeat function. Source from https://discuss.pytorch.org/t/how-to-tile-a-tensor/13853/2
torch.repeat([1,2,3], 2) --> [1, 2, 3, 1, 2, 3]
np.repeat([1,2,3], repeats=2, axis=0) --> [1, 1, 2, 2, 3, 3]
:param a: tensor
:param repeats: number of repeats
:param dim: dimension where to repeat
:return: tensor with repitions
'''
init_dim = a.size(dim)
repeat_idx = [1] * a.dim()
repeat_idx[dim] = repeats
a = a.repeat(*(repeat_idx))
if a.is_cuda: # use cuda-device if input was on cuda device already
order_index = torch.cuda.LongTensor(
torch.cat([init_dim * torch.arange(repeats, device=a.device) + i for i in range(init_dim)]))
else:
order_index = torch.LongTensor(
torch.cat([init_dim * torch.arange(repeats) + i for i in range(init_dim)]))
return torch.index_select(a, dim, order_index)
# save 4D np.ndarray or torch tensor to image files
def saveImgs(inputData, dir):
if not os.path.exists(dir):
os.makedirs(dir)
if type(inputData) is torch.Tensor:
if inputData.requires_grad:
inputData = inputData.detach()
if inputData.device.type == 'cuda':
imgs = inputData.cpu().numpy().transpose(0, 2, 3, 1) # (N, C, row, col) to (N, row, col, C)
else:
imgs = inputData.numpy().transpose(0, 2, 3, 1) # (N, C, row, col) to (N, row, col, C)
else:
imgs = inputData
# imgs must have a shape of (N, row, col, C)
imgs = np.uint8(imgs[:, :, :, ::-1] * 255) # convert to BGR and uint8 for opencv
for i in range(imgs.shape[0]):
file_name = 'img_{:04d}.png'.format(i + 1)
cv.imwrite(fullfile(dir, file_name), imgs[i, :, :, :]) # faster than PIL or scipy
# compute PSNR
def psnr(x, y):
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
x = x.to(device) if x.device.type != device.type else x
y = y.to(device) if y.device.type != device.type else y
with torch.no_grad():
l2_fun = nn.MSELoss()
return 10 * math.log10(1 / l2_fun(x, y))
# compute RMSE
def rmse(x, y):
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
x = x.to(device) if x.device.type != device.type else x
y = y.to(device) if y.device.type != device.type else y
with torch.no_grad():
l2_fun = nn.MSELoss()
return math.sqrt(l2_fun(x, y).item() * 3) # only works for RGB, for grayscale, don't multiply by 3
# compute SSIM
def ssim(x, y):
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
x = x.to(device) if x.device.type != device.type else x
y = y.to(device) if y.device.type != device.type else y
with torch.no_grad():
return pytorch_ssim.ssim(x, y).item()
# compute psnr, rmse and ssim
def computeMetrics(x, y):
l2_fun = nn.MSELoss()
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
last_loc = 0
metric_mse, metric_ssim = 0., 0.
num_imgs = x.shape[0]
batch_size = 50 if num_imgs > 50 else num_imgs # Make sure mod(num_imgs, batch_size) == 0
with torch.no_grad():
for i in range(0, num_imgs // batch_size):
idx = range(last_loc, last_loc + batch_size)
x_batch = x[idx, :, :, :].to(device) if x.device.type != 'cuda' else x[idx, :, :, :]
y_batch = y[idx, :, :, :].to(device) if y.device.type != 'cuda' else y[idx, :, :, :]
# compute mse and ssim
metric_mse += l2_fun(x_batch, y_batch).item() * batch_size
metric_ssim += ssim(x_batch, y_batch) * batch_size
last_loc += batch_size
# average
metric_mse /= num_imgs
metric_ssim /= num_imgs
# rmse and psnr
metric_rmse = math.sqrt(metric_mse * 3) # 3 channel image
metric_psnr = 10 * math.log10(1 / metric_mse)
return metric_psnr, metric_rmse, metric_ssim
# count the number of parameters of a model
def countParameters(model):
return sum([param.numel() for param in model.parameters() if param.requires_grad])
# generate training title string
def optionToString(train_option):
return '{}_{}_{}_{}_{}_{}_{}_{}_{}_{}'.format(train_option['data_name'], train_option['model_name'], train_option['loss'],
train_option['num_train'], train_option['batch_size'], train_option['max_iters'],
train_option['lr'], train_option['lr_drop_ratio'], train_option['lr_drop_rate'],
train_option['l2_reg'])