-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathbicubic_downsample.py
More file actions
45 lines (42 loc) · 1.66 KB
/
Copy pathbicubic_downsample.py
File metadata and controls
45 lines (42 loc) · 1.66 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
# TensorFlow Better Bicubic Downsample
def bicubic_kernel(x, a=-0.5):
"""https://clouard.users.greyc.fr/Pantheon/experiments/rescaling/index-en.html#bicubic"""
if abs(x) <= 1:
return (a + 2)*abs(x)**3 - (a + 3)*abs(x)**2 + 1
elif 1 < abs(x) and abs(x) < 2:
return a*abs(x)**3 - 5*a*abs(x)**2 + 8*a*abs(x) - 4*a
else:
return 0
def build_filter(factor):
size = factor*4
k = np.zeros((size))
for i in range(size):
x = (1/factor)*(i- np.floor(size/2) +0.5)
k[i] = bicubic_kernel(x)
k = k / np.sum(k)
# make 2d
k = np.outer(k, k.T)
k = tf.constant(k, dtype=tf.float32, shape=(size, size, 1, 1))
return tf.concat([k, k, k], axis=2)
def apply_bicubic_downsample(x, filter, factor):
"""Downsample x by a factor of factor, using the filter built by build_filter()
x: a rank 4 tensor with format NHWC
filter: from build_filter(factor)
factor: downsampling factor (ex: factor=2 means the output size is (h/2, w/2))
"""
# using padding calculations from https://www.tensorflow.org/api_guides/python/nn#Convolution
filter_height = factor*4
filter_width = factor*4
strides = factor
pad_along_height = max(filter_height - strides, 0)
pad_along_width = max(filter_width - strides, 0)
# compute actual padding values for each side
pad_top = pad_along_height // 2
pad_bottom = pad_along_height - pad_top
pad_left = pad_along_width // 2
pad_right = pad_along_width - pad_left
# apply mirror padding
x = tf.pad(x, [[0,0], [pad_top,pad_bottom], [pad_left,pad_right], [0,0]], mode='REFLECT')
# downsampling performed by strided conv
x = tf.nn.depthwise_conv2d(x, filter=filter, strides=[1,strides,strides,1], padding='VALID')
return x