sczhou commited on
Commit
6bb77c4
·
1 Parent(s): c021434

add gaussian_kernels.py

Browse files
Files changed (2) hide show
  1. README.md +1 -1
  2. basicsr/data/gaussian_kernels.py +690 -0
README.md CHANGED
@@ -142,7 +142,7 @@ python inference_colorization.py --input_path [image folder]|[image path]
142
  # (check out the examples in inputs/masked_faces)
143
  python inference_inpainting.py --input_path [image folder]|[image path]
144
  ```
145
- #### Training:
146
  The training commands can be found in the documents: [English](docs/train.md) **|** [简体中文](docs/train_CN.md).
147
 
148
  ### Citation
 
142
  # (check out the examples in inputs/masked_faces)
143
  python inference_inpainting.py --input_path [image folder]|[image path]
144
  ```
145
+ ### Training:
146
  The training commands can be found in the documents: [English](docs/train.md) **|** [简体中文](docs/train_CN.md).
147
 
148
  ### Citation
basicsr/data/gaussian_kernels.py ADDED
@@ -0,0 +1,690 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import numpy as np
3
+ import random
4
+ from scipy.ndimage.interpolation import shift
5
+ from scipy.stats import multivariate_normal
6
+
7
+
8
+ def sigma_matrix2(sig_x, sig_y, theta):
9
+ """Calculate the rotated sigma matrix (two dimensional matrix).
10
+ Args:
11
+ sig_x (float):
12
+ sig_y (float):
13
+ theta (float): Radian measurement.
14
+ Returns:
15
+ ndarray: Rotated sigma matrix.
16
+ """
17
+ D = np.array([[sig_x**2, 0], [0, sig_y**2]])
18
+ U = np.array([[np.cos(theta), -np.sin(theta)],
19
+ [np.sin(theta), np.cos(theta)]])
20
+ return np.dot(U, np.dot(D, U.T))
21
+
22
+
23
+ def mesh_grid(kernel_size):
24
+ """Generate the mesh grid, centering at zero.
25
+ Args:
26
+ kernel_size (int):
27
+ Returns:
28
+ xy (ndarray): with the shape (kernel_size, kernel_size, 2)
29
+ xx (ndarray): with the shape (kernel_size, kernel_size)
30
+ yy (ndarray): with the shape (kernel_size, kernel_size)
31
+ """
32
+ ax = np.arange(-kernel_size // 2 + 1., kernel_size // 2 + 1.)
33
+ xx, yy = np.meshgrid(ax, ax)
34
+ xy = np.hstack((xx.reshape((kernel_size * kernel_size, 1)),
35
+ yy.reshape(kernel_size * kernel_size,
36
+ 1))).reshape(kernel_size, kernel_size, 2)
37
+ return xy, xx, yy
38
+
39
+
40
+ def pdf2(sigma_matrix, grid):
41
+ """Calculate PDF of the bivariate Gaussian distribution.
42
+ Args:
43
+ sigma_matrix (ndarray): with the shape (2, 2)
44
+ grid (ndarray): generated by :func:`mesh_grid`,
45
+ with the shape (K, K, 2), K is the kernel size.
46
+ Returns:
47
+ kernel (ndarrray): un-normalized kernel.
48
+ """
49
+ inverse_sigma = np.linalg.inv(sigma_matrix)
50
+ kernel = np.exp(-0.5 * np.sum(np.dot(grid, inverse_sigma) * grid, 2))
51
+ return kernel
52
+
53
+
54
+ def cdf2(D, grid):
55
+ """Calculate the CDF of the standard bivariate Gaussian distribution.
56
+ Used in skewed Gaussian distribution.
57
+ Args:
58
+ D (ndarrasy): skew matrix.
59
+ grid (ndarray): generated by :func:`mesh_grid`,
60
+ with the shape (K, K, 2), K is the kernel size.
61
+ Returns:
62
+ cdf (ndarray): skewed cdf.
63
+ """
64
+ rv = multivariate_normal([0, 0], [[1, 0], [0, 1]])
65
+ grid = np.dot(grid, D)
66
+ cdf = rv.cdf(grid)
67
+ return cdf
68
+
69
+
70
+ def bivariate_skew_Gaussian(kernel_size, sig_x, sig_y, theta, D, grid=None):
71
+ """Generate a bivariate skew Gaussian kernel.
72
+ Described in `A multivariate skew normal distribution`_ by Shi et. al (2004).
73
+ Args:
74
+ kernel_size (int):
75
+ sig_x (float):
76
+ sig_y (float):
77
+ theta (float): Radian measurement.
78
+ D (ndarrasy): skew matrix.
79
+ grid (ndarray, optional): generated by :func:`mesh_grid`,
80
+ with the shape (K, K, 2), K is the kernel size. Default: None
81
+ Returns:
82
+ kernel (ndarray): normalized kernel.
83
+ .. _A multivariate skew normal distribution:
84
+ https://www.sciencedirect.com/science/article/pii/S0047259X03001313
85
+ """
86
+ if grid is None:
87
+ grid, _, _ = mesh_grid(kernel_size)
88
+ sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)
89
+ pdf = pdf2(sigma_matrix, grid)
90
+ cdf = cdf2(D, grid)
91
+ kernel = pdf * cdf
92
+ kernel = kernel / np.sum(kernel)
93
+ return kernel
94
+
95
+
96
+ def mass_center_shift(kernel_size, kernel):
97
+ """Calculate the shift of the mass center of a kenrel.
98
+ Args:
99
+ kernel_size (int):
100
+ kernel (ndarray): normalized kernel.
101
+ Returns:
102
+ delta_h (float):
103
+ delta_w (float):
104
+ """
105
+ ax = np.arange(-kernel_size // 2 + 1., kernel_size // 2 + 1.)
106
+ col_sum, row_sum = np.sum(kernel, axis=0), np.sum(kernel, axis=1)
107
+ delta_h = np.dot(row_sum, ax)
108
+ delta_w = np.dot(col_sum, ax)
109
+ return delta_h, delta_w
110
+
111
+
112
+ def bivariate_skew_Gaussian_center(kernel_size,
113
+ sig_x,
114
+ sig_y,
115
+ theta,
116
+ D,
117
+ grid=None):
118
+ """Generate a bivariate skew Gaussian kernel at center. Shift with nearest padding.
119
+ Args:
120
+ kernel_size (int):
121
+ sig_x (float):
122
+ sig_y (float):
123
+ theta (float): Radian measurement.
124
+ D (ndarrasy): skew matrix.
125
+ grid (ndarray, optional): generated by :func:`mesh_grid`,
126
+ with the shape (K, K, 2), K is the kernel size. Default: None
127
+ Returns:
128
+ kernel (ndarray): centered and normalized kernel.
129
+ """
130
+ if grid is None:
131
+ grid, _, _ = mesh_grid(kernel_size)
132
+ kernel = bivariate_skew_Gaussian(kernel_size, sig_x, sig_y, theta, D, grid)
133
+ delta_h, delta_w = mass_center_shift(kernel_size, kernel)
134
+ kernel = shift(kernel, [-delta_h, -delta_w], mode='nearest')
135
+ kernel = kernel / np.sum(kernel)
136
+ return kernel
137
+
138
+
139
+ def bivariate_anisotropic_Gaussian(kernel_size,
140
+ sig_x,
141
+ sig_y,
142
+ theta,
143
+ grid=None):
144
+ """Generate a bivariate anisotropic Gaussian kernel.
145
+ Args:
146
+ kernel_size (int):
147
+ sig_x (float):
148
+ sig_y (float):
149
+ theta (float): Radian measurement.
150
+ grid (ndarray, optional): generated by :func:`mesh_grid`,
151
+ with the shape (K, K, 2), K is the kernel size. Default: None
152
+ Returns:
153
+ kernel (ndarray): normalized kernel.
154
+ """
155
+ if grid is None:
156
+ grid, _, _ = mesh_grid(kernel_size)
157
+ sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)
158
+ kernel = pdf2(sigma_matrix, grid)
159
+ kernel = kernel / np.sum(kernel)
160
+ return kernel
161
+
162
+
163
+ def bivariate_isotropic_Gaussian(kernel_size, sig, grid=None):
164
+ """Generate a bivariate isotropic Gaussian kernel.
165
+ Args:
166
+ kernel_size (int):
167
+ sig (float):
168
+ grid (ndarray, optional): generated by :func:`mesh_grid`,
169
+ with the shape (K, K, 2), K is the kernel size. Default: None
170
+ Returns:
171
+ kernel (ndarray): normalized kernel.
172
+ """
173
+ if grid is None:
174
+ grid, _, _ = mesh_grid(kernel_size)
175
+ sigma_matrix = np.array([[sig**2, 0], [0, sig**2]])
176
+ kernel = pdf2(sigma_matrix, grid)
177
+ kernel = kernel / np.sum(kernel)
178
+ return kernel
179
+
180
+
181
+ def bivariate_generalized_Gaussian(kernel_size,
182
+ sig_x,
183
+ sig_y,
184
+ theta,
185
+ beta,
186
+ grid=None):
187
+ """Generate a bivariate generalized Gaussian kernel.
188
+ Described in `Parameter Estimation For Multivariate Generalized Gaussian Distributions`_
189
+ by Pascal et. al (2013).
190
+ Args:
191
+ kernel_size (int):
192
+ sig_x (float):
193
+ sig_y (float):
194
+ theta (float): Radian measurement.
195
+ beta (float): shape parameter, beta = 1 is the normal distribution.
196
+ grid (ndarray, optional): generated by :func:`mesh_grid`,
197
+ with the shape (K, K, 2), K is the kernel size. Default: None
198
+ Returns:
199
+ kernel (ndarray): normalized kernel.
200
+ .. _Parameter Estimation For Multivariate Generalized Gaussian Distributions:
201
+ https://arxiv.org/abs/1302.6498
202
+ """
203
+ if grid is None:
204
+ grid, _, _ = mesh_grid(kernel_size)
205
+ sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)
206
+ inverse_sigma = np.linalg.inv(sigma_matrix)
207
+ kernel = np.exp(
208
+ -0.5 * np.power(np.sum(np.dot(grid, inverse_sigma) * grid, 2), beta))
209
+ kernel = kernel / np.sum(kernel)
210
+ return kernel
211
+
212
+
213
+ def bivariate_plateau_type1(kernel_size, sig_x, sig_y, theta, beta, grid=None):
214
+ """Generate a plateau-like anisotropic kernel.
215
+ 1 / (1+x^(beta))
216
+ Args:
217
+ kernel_size (int):
218
+ sig_x (float):
219
+ sig_y (float):
220
+ theta (float): Radian measurement.
221
+ beta (float): shape parameter, beta = 1 is the normal distribution.
222
+ grid (ndarray, optional): generated by :func:`mesh_grid`,
223
+ with the shape (K, K, 2), K is the kernel size. Default: None
224
+ Returns:
225
+ kernel (ndarray): normalized kernel.
226
+ """
227
+ if grid is None:
228
+ grid, _, _ = mesh_grid(kernel_size)
229
+ sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)
230
+ inverse_sigma = np.linalg.inv(sigma_matrix)
231
+ kernel = np.reciprocal(
232
+ np.power(np.sum(np.dot(grid, inverse_sigma) * grid, 2), beta) + 1)
233
+ kernel = kernel / np.sum(kernel)
234
+ return kernel
235
+
236
+
237
+ def bivariate_plateau_type1_iso(kernel_size, sig, beta, grid=None):
238
+ """Generate a plateau-like isotropic kernel.
239
+ 1 / (1+x^(beta))
240
+ Args:
241
+ kernel_size (int):
242
+ sig (float):
243
+ beta (float): shape parameter, beta = 1 is the normal distribution.
244
+ grid (ndarray, optional): generated by :func:`mesh_grid`,
245
+ with the shape (K, K, 2), K is the kernel size. Default: None
246
+ Returns:
247
+ kernel (ndarray): normalized kernel.
248
+ """
249
+ if grid is None:
250
+ grid, _, _ = mesh_grid(kernel_size)
251
+ sigma_matrix = np.array([[sig**2, 0], [0, sig**2]])
252
+ inverse_sigma = np.linalg.inv(sigma_matrix)
253
+ kernel = np.reciprocal(
254
+ np.power(np.sum(np.dot(grid, inverse_sigma) * grid, 2), beta) + 1)
255
+ kernel = kernel / np.sum(kernel)
256
+ return kernel
257
+
258
+
259
+ def random_bivariate_skew_Gaussian_center(kernel_size,
260
+ sigma_x_range,
261
+ sigma_y_range,
262
+ rotation_range,
263
+ noise_range=None,
264
+ strict=False):
265
+ """Randomly generate bivariate skew Gaussian kernels at center.
266
+ Args:
267
+ kernel_size (int):
268
+ sigma_x_range (tuple): [0.6, 5]
269
+ sigma_y_range (tuple): [0.6, 5]
270
+ rotation range (tuple): [-math.pi, math.pi]
271
+ noise_range(tuple, optional): multiplicative kernel noise, [0.75, 1.25]. Default: None
272
+ Returns:
273
+ kernel (ndarray):
274
+ """
275
+ assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
276
+ assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'
277
+ assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'
278
+ assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'
279
+ sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])
280
+ sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])
281
+ if strict:
282
+ sigma_max = np.max([sigma_x, sigma_y])
283
+ sigma_min = np.min([sigma_x, sigma_y])
284
+ sigma_x, sigma_y = sigma_max, sigma_min
285
+ rotation = np.random.uniform(rotation_range[0], rotation_range[1])
286
+
287
+ sigma_max = np.max([sigma_x, sigma_y])
288
+ thres = 3 / sigma_max
289
+ D = [[np.random.uniform(-thres, thres),
290
+ np.random.uniform(-thres, thres)],
291
+ [np.random.uniform(-thres, thres),
292
+ np.random.uniform(-thres, thres)]]
293
+
294
+ kernel = bivariate_skew_Gaussian_center(kernel_size, sigma_x, sigma_y,
295
+ rotation, D)
296
+
297
+ # add multiplicative noise
298
+ if noise_range is not None:
299
+ assert noise_range[0] < noise_range[1], 'Wrong noise range.'
300
+ noise = np.random.uniform(
301
+ noise_range[0], noise_range[1], size=kernel.shape)
302
+ kernel = kernel * noise
303
+ kernel = kernel / np.sum(kernel)
304
+ if strict:
305
+ return kernel, sigma_x, sigma_y, rotation, D
306
+ else:
307
+ return kernel
308
+
309
+
310
+ def random_bivariate_anisotropic_Gaussian(kernel_size,
311
+ sigma_x_range,
312
+ sigma_y_range,
313
+ rotation_range,
314
+ noise_range=None,
315
+ strict=False):
316
+ """Randomly generate bivariate anisotropic Gaussian kernels.
317
+ Args:
318
+ kernel_size (int):
319
+ sigma_x_range (tuple): [0.6, 5]
320
+ sigma_y_range (tuple): [0.6, 5]
321
+ rotation range (tuple): [-math.pi, math.pi]
322
+ noise_range(tuple, optional): multiplicative kernel noise, [0.75, 1.25]. Default: None
323
+ Returns:
324
+ kernel (ndarray):
325
+ """
326
+ assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
327
+ assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'
328
+ assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'
329
+ assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'
330
+ sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])
331
+ sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])
332
+ if strict:
333
+ sigma_max = np.max([sigma_x, sigma_y])
334
+ sigma_min = np.min([sigma_x, sigma_y])
335
+ sigma_x, sigma_y = sigma_max, sigma_min
336
+ rotation = np.random.uniform(rotation_range[0], rotation_range[1])
337
+
338
+ kernel = bivariate_anisotropic_Gaussian(kernel_size, sigma_x, sigma_y,
339
+ rotation)
340
+
341
+ # add multiplicative noise
342
+ if noise_range is not None:
343
+ assert noise_range[0] < noise_range[1], 'Wrong noise range.'
344
+ noise = np.random.uniform(
345
+ noise_range[0], noise_range[1], size=kernel.shape)
346
+ kernel = kernel * noise
347
+ kernel = kernel / np.sum(kernel)
348
+ if strict:
349
+ return kernel, sigma_x, sigma_y, rotation
350
+ else:
351
+ return kernel
352
+
353
+
354
+ def random_bivariate_isotropic_Gaussian(kernel_size,
355
+ sigma_range,
356
+ noise_range=None,
357
+ strict=False):
358
+ """Randomly generate bivariate isotropic Gaussian kernels.
359
+ Args:
360
+ kernel_size (int):
361
+ sigma_range (tuple): [0.6, 5]
362
+ noise_range(tuple, optional): multiplicative kernel noise, [0.75, 1.25]. Default: None
363
+ Returns:
364
+ kernel (ndarray):
365
+ """
366
+ assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
367
+ assert sigma_range[0] < sigma_range[1], 'Wrong sigma_x_range.'
368
+ sigma = np.random.uniform(sigma_range[0], sigma_range[1])
369
+
370
+ kernel = bivariate_isotropic_Gaussian(kernel_size, sigma)
371
+
372
+ # add multiplicative noise
373
+ if noise_range is not None:
374
+ assert noise_range[0] < noise_range[1], 'Wrong noise range.'
375
+ noise = np.random.uniform(
376
+ noise_range[0], noise_range[1], size=kernel.shape)
377
+ kernel = kernel * noise
378
+ kernel = kernel / np.sum(kernel)
379
+ if strict:
380
+ return kernel, sigma
381
+ else:
382
+ return kernel
383
+
384
+
385
+ def random_bivariate_generalized_Gaussian(kernel_size,
386
+ sigma_x_range,
387
+ sigma_y_range,
388
+ rotation_range,
389
+ beta_range,
390
+ noise_range=None,
391
+ strict=False):
392
+ """Randomly generate bivariate generalized Gaussian kernels.
393
+ Args:
394
+ kernel_size (int):
395
+ sigma_x_range (tuple): [0.6, 5]
396
+ sigma_y_range (tuple): [0.6, 5]
397
+ rotation range (tuple): [-math.pi, math.pi]
398
+ beta_range (tuple): [0.5, 8]
399
+ noise_range(tuple, optional): multiplicative kernel noise, [0.75, 1.25]. Default: None
400
+ Returns:
401
+ kernel (ndarray):
402
+ """
403
+ assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
404
+ assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'
405
+ assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'
406
+ assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'
407
+ sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])
408
+ sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])
409
+ if strict:
410
+ sigma_max = np.max([sigma_x, sigma_y])
411
+ sigma_min = np.min([sigma_x, sigma_y])
412
+ sigma_x, sigma_y = sigma_max, sigma_min
413
+ rotation = np.random.uniform(rotation_range[0], rotation_range[1])
414
+ if np.random.uniform() < 0.5:
415
+ beta = np.random.uniform(beta_range[0], 1)
416
+ else:
417
+ beta = np.random.uniform(1, beta_range[1])
418
+
419
+ kernel = bivariate_generalized_Gaussian(kernel_size, sigma_x, sigma_y,
420
+ rotation, beta)
421
+
422
+ # add multiplicative noise
423
+ if noise_range is not None:
424
+ assert noise_range[0] < noise_range[1], 'Wrong noise range.'
425
+ noise = np.random.uniform(
426
+ noise_range[0], noise_range[1], size=kernel.shape)
427
+ kernel = kernel * noise
428
+ kernel = kernel / np.sum(kernel)
429
+ if strict:
430
+ return kernel, sigma_x, sigma_y, rotation, beta
431
+ else:
432
+ return kernel
433
+
434
+
435
+ def random_bivariate_plateau_type1(kernel_size,
436
+ sigma_x_range,
437
+ sigma_y_range,
438
+ rotation_range,
439
+ beta_range,
440
+ noise_range=None,
441
+ strict=False):
442
+ """Randomly generate bivariate plateau type1 kernels.
443
+ Args:
444
+ kernel_size (int):
445
+ sigma_x_range (tuple): [0.6, 5]
446
+ sigma_y_range (tuple): [0.6, 5]
447
+ rotation range (tuple): [-math.pi/2, math.pi/2]
448
+ beta_range (tuple): [1, 4]
449
+ noise_range(tuple, optional): multiplicative kernel noise, [0.75, 1.25]. Default: None
450
+ Returns:
451
+ kernel (ndarray):
452
+ """
453
+ assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
454
+ assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'
455
+ assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'
456
+ assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'
457
+ sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])
458
+ sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])
459
+ if strict:
460
+ sigma_max = np.max([sigma_x, sigma_y])
461
+ sigma_min = np.min([sigma_x, sigma_y])
462
+ sigma_x, sigma_y = sigma_max, sigma_min
463
+ rotation = np.random.uniform(rotation_range[0], rotation_range[1])
464
+ if np.random.uniform() < 0.5:
465
+ beta = np.random.uniform(beta_range[0], 1)
466
+ else:
467
+ beta = np.random.uniform(1, beta_range[1])
468
+
469
+ kernel = bivariate_plateau_type1(kernel_size, sigma_x, sigma_y, rotation,
470
+ beta)
471
+
472
+ # add multiplicative noise
473
+ if noise_range is not None:
474
+ assert noise_range[0] < noise_range[1], 'Wrong noise range.'
475
+ noise = np.random.uniform(
476
+ noise_range[0], noise_range[1], size=kernel.shape)
477
+ kernel = kernel * noise
478
+ kernel = kernel / np.sum(kernel)
479
+ if strict:
480
+ return kernel, sigma_x, sigma_y, rotation, beta
481
+ else:
482
+ return kernel
483
+
484
+
485
+ def random_bivariate_plateau_type1_iso(kernel_size,
486
+ sigma_range,
487
+ beta_range,
488
+ noise_range=None,
489
+ strict=False):
490
+ """Randomly generate bivariate plateau type1 kernels (iso).
491
+ Args:
492
+ kernel_size (int):
493
+ sigma_range (tuple): [0.6, 5]
494
+ beta_range (tuple): [1, 4]
495
+ noise_range(tuple, optional): multiplicative kernel noise, [0.75, 1.25]. Default: None
496
+ Returns:
497
+ kernel (ndarray):
498
+ """
499
+ assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'
500
+ assert sigma_range[0] < sigma_range[1], 'Wrong sigma_x_range.'
501
+ sigma = np.random.uniform(sigma_range[0], sigma_range[1])
502
+ beta = np.random.uniform(beta_range[0], beta_range[1])
503
+
504
+ kernel = bivariate_plateau_type1_iso(kernel_size, sigma, beta)
505
+
506
+ # add multiplicative noise
507
+ if noise_range is not None:
508
+ assert noise_range[0] < noise_range[1], 'Wrong noise range.'
509
+ noise = np.random.uniform(
510
+ noise_range[0], noise_range[1], size=kernel.shape)
511
+ kernel = kernel * noise
512
+ kernel = kernel / np.sum(kernel)
513
+ if strict:
514
+ return kernel, sigma, beta
515
+ else:
516
+ return kernel
517
+
518
+
519
+ def random_mixed_kernels(kernel_list,
520
+ kernel_prob,
521
+ kernel_size=21,
522
+ sigma_x_range=[0.6, 5],
523
+ sigma_y_range=[0.6, 5],
524
+ rotation_range=[-math.pi, math.pi],
525
+ beta_range=[0.5, 8],
526
+ noise_range=None):
527
+ """Randomly generate mixed kernels.
528
+ Args:
529
+ kernel_list (tuple): a list name of kenrel types,
530
+ support ['iso', 'aniso', 'skew', 'generalized', 'plateau_iso', 'plateau_aniso']
531
+ kernel_prob (tuple): corresponding kernel probability for each kernel type
532
+ kernel_size (int):
533
+ sigma_x_range (tuple): [0.6, 5]
534
+ sigma_y_range (tuple): [0.6, 5]
535
+ rotation range (tuple): [-math.pi, math.pi]
536
+ beta_range (tuple): [0.5, 8]
537
+ noise_range(tuple, optional): multiplicative kernel noise, [0.75, 1.25]. Default: None
538
+ Returns:
539
+ kernel (ndarray):
540
+ """
541
+ kernel_type = random.choices(kernel_list, kernel_prob)[0]
542
+ if kernel_type == 'iso':
543
+ kernel = random_bivariate_isotropic_Gaussian(
544
+ kernel_size, sigma_x_range, noise_range=noise_range)
545
+ elif kernel_type == 'aniso':
546
+ kernel = random_bivariate_anisotropic_Gaussian(
547
+ kernel_size,
548
+ sigma_x_range,
549
+ sigma_y_range,
550
+ rotation_range,
551
+ noise_range=noise_range)
552
+ elif kernel_type == 'skew':
553
+ kernel = random_bivariate_skew_Gaussian_center(
554
+ kernel_size,
555
+ sigma_x_range,
556
+ sigma_y_range,
557
+ rotation_range,
558
+ noise_range=noise_range)
559
+ elif kernel_type == 'generalized':
560
+ kernel = random_bivariate_generalized_Gaussian(
561
+ kernel_size,
562
+ sigma_x_range,
563
+ sigma_y_range,
564
+ rotation_range,
565
+ beta_range,
566
+ noise_range=noise_range)
567
+ elif kernel_type == 'plateau_iso':
568
+ kernel = random_bivariate_plateau_type1_iso(
569
+ kernel_size, sigma_x_range, beta_range, noise_range=noise_range)
570
+ elif kernel_type == 'plateau_aniso':
571
+ kernel = random_bivariate_plateau_type1(
572
+ kernel_size,
573
+ sigma_x_range,
574
+ sigma_y_range,
575
+ rotation_range,
576
+ beta_range,
577
+ noise_range=noise_range)
578
+ # add multiplicative noise
579
+ if noise_range is not None:
580
+ assert noise_range[0] < noise_range[1], 'Wrong noise range.'
581
+ noise = np.random.uniform(
582
+ noise_range[0], noise_range[1], size=kernel.shape)
583
+ kernel = kernel * noise
584
+ kernel = kernel / np.sum(kernel)
585
+ return kernel
586
+
587
+
588
+ def show_one_kernel():
589
+ import matplotlib.pyplot as plt
590
+ kernel_size = 21
591
+
592
+ # bivariate skew Gaussian
593
+ D = [[0, 0], [0, 0]]
594
+ D = [[3 / 4, 0], [0, 0.5]]
595
+ kernel = bivariate_skew_Gaussian_center(kernel_size, 2, 4, -math.pi / 4, D)
596
+ # bivariate anisotropic Gaussian
597
+ kernel = bivariate_anisotropic_Gaussian(kernel_size, 2, 4, -math.pi / 4)
598
+ # bivariate anisotropic Gaussian
599
+ kernel = bivariate_isotropic_Gaussian(kernel_size, 1)
600
+ # bivariate generalized Gaussian
601
+ kernel = bivariate_generalized_Gaussian(
602
+ kernel_size, 2, 4, -math.pi / 4, beta=4)
603
+
604
+ delta_h, delta_w = mass_center_shift(kernel_size, kernel)
605
+ print(delta_h, delta_w)
606
+
607
+ fig, axs = plt.subplots(nrows=2, ncols=2)
608
+ # axs.set_axis_off()
609
+ ax = axs[0][0]
610
+ im = ax.matshow(kernel, cmap='jet', origin='upper')
611
+ fig.colorbar(im, ax=ax)
612
+
613
+ # image
614
+ ax = axs[0][1]
615
+ kernel_vis = kernel - np.min(kernel)
616
+ kernel_vis = kernel_vis / np.max(kernel_vis) * 255.
617
+ ax.imshow(kernel_vis, interpolation='nearest')
618
+
619
+ _, xx, yy = mesh_grid(kernel_size)
620
+ # contour
621
+ ax = axs[1][0]
622
+ CS = ax.contour(xx, yy, kernel, origin='upper')
623
+ ax.clabel(CS, inline=1, fontsize=3)
624
+
625
+ # contourf
626
+ ax = axs[1][1]
627
+ kernel = kernel / np.max(kernel)
628
+ p = ax.contourf(
629
+ xx, yy, kernel, origin='upper', levels=np.linspace(-0.05, 1.05, 10))
630
+ fig.colorbar(p)
631
+
632
+ plt.show()
633
+
634
+
635
+ def show_plateau_kernel():
636
+ import matplotlib.pyplot as plt
637
+ kernel_size = 21
638
+
639
+ kernel = plateau_type1(kernel_size, 2, 4, -math.pi / 8, 2, grid=None)
640
+ kernel_norm = bivariate_isotropic_Gaussian(kernel_size, 5)
641
+ kernel_gau = bivariate_generalized_Gaussian(
642
+ kernel_size, 2, 4, -math.pi / 8, 2, grid=None)
643
+ delta_h, delta_w = mass_center_shift(kernel_size, kernel)
644
+ print(delta_h, delta_w)
645
+
646
+ # kernel_slice = kernel[10, :]
647
+ # kernel_gau_slice = kernel_gau[10, :]
648
+ # kernel_norm_slice = kernel_norm[10, :]
649
+ # fig, ax = plt.subplots()
650
+ # t = list(range(1, 22))
651
+
652
+ # ax.plot(t, kernel_gau_slice)
653
+ # ax.plot(t, kernel_slice)
654
+ # ax.plot(t, kernel_norm_slice)
655
+
656
+ # t = np.arange(0, 10, 0.1)
657
+ # y = np.exp(-0.5 * t)
658
+ # y2 = np.reciprocal(1 + t)
659
+ # print(t.shape)
660
+ # print(y.shape)
661
+ # ax.plot(t, y)
662
+ # ax.plot(t, y2)
663
+ # plt.show()
664
+
665
+ fig, axs = plt.subplots(nrows=2, ncols=2)
666
+ # axs.set_axis_off()
667
+ ax = axs[0][0]
668
+ im = ax.matshow(kernel, cmap='jet', origin='upper')
669
+ fig.colorbar(im, ax=ax)
670
+
671
+ # image
672
+ ax = axs[0][1]
673
+ kernel_vis = kernel - np.min(kernel)
674
+ kernel_vis = kernel_vis / np.max(kernel_vis) * 255.
675
+ ax.imshow(kernel_vis, interpolation='nearest')
676
+
677
+ _, xx, yy = mesh_grid(kernel_size)
678
+ # contour
679
+ ax = axs[1][0]
680
+ CS = ax.contour(xx, yy, kernel, origin='upper')
681
+ ax.clabel(CS, inline=1, fontsize=3)
682
+
683
+ # contourf
684
+ ax = axs[1][1]
685
+ kernel = kernel / np.max(kernel)
686
+ p = ax.contourf(
687
+ xx, yy, kernel, origin='upper', levels=np.linspace(-0.05, 1.05, 10))
688
+ fig.colorbar(p)
689
+
690
+ plt.show()