-
Notifications
You must be signed in to change notification settings - Fork 5
/
tf_filters.py
89 lines (67 loc) · 3.38 KB
/
tf_filters.py
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
import numpy as np
import tensorflow as tf
def get_sobel_kernel(ksize):
if (ksize % 2 == 0) or (ksize < 1):
raise ValueError("Kernel size must be a positive odd number")
_base = np.arange(ksize) - ksize//2
a = np.broadcast_to(_base, (ksize,ksize))
b = ksize//2 - np.abs(a).T
s = np.sign(a)
return a + s*b
def get_gaussian_kernel(ksize = 3, sigma = -1.0):
ksigma = 0.15*ksize + 0.35 if sigma <= 0 else sigma
i, j = np.mgrid[0:ksize,0:ksize] - (ksize-1)//2
kernel = np.exp(-(i**2 + j**2) / (2*ksigma**2))
return kernel / kernel.sum()
def get_laplacian_of_gaussian_kernel(ksize = 3, sigma = -1.0):
ksigma = 0.15*ksize + 0.35 if sigma <= 0 else sigma
i, j = np.mgrid[0:ksize,0:ksize] - (ksize-1)//2
kernel = (i**2 + j**2 - 2*ksigma**2) / (ksigma**4) * np.exp(-(i**2 + j**2) / (2*ksigma**2))
return kernel - kernel.mean()
def tf_kernel_prep_4d(kernel, n_channels):
return np.tile(kernel, (n_channels, 1, 1, 1)).swapaxes(0,2).swapaxes(1,3)
def tf_kernel_prep_3d(kernel, n_channels):
return np.tile(kernel, (n_channels, 1, 1)).swapaxes(0,1).swapaxes(1,2)
def tf_filter2d(batch, kernel, strides=(1,1), padding='SAME'):
n_ch = batch.shape[3].value
tf_kernel = tf.constant(tf_kernel_prep_4d(kernel, n_ch))
return tf.nn.depthwise_conv2d(batch, tf_kernel, [1, strides[0], strides[1], 1], padding=padding)
def tf_deriv(batch, ksize=3, padding='SAME'):
try:
n_ch = batch.shape[3].value
except:
n_ch = int(batch.get_shape()[3])
gx = tf_kernel_prep_3d(np.array([[ 0, 0, 0],
[-1, 0, 1],
[ 0, 0, 0]]), n_ch)
gy = tf_kernel_prep_3d(np.array([[ 0, -1, 0],
[ 0, 0, 0],
[ 0, 1, 0]]), n_ch)
kernel = tf.constant(np.stack([gx, gy], axis=-1), name="DerivKernel", dtype = np.float32)
return tf.nn.depthwise_conv2d(batch, kernel, [1, 1, 1, 1], padding=padding, name="GradXY")
def tf_sobel(batch, ksize=3, padding='SAME'):
n_ch = batch.shape[3].value
gx = tf_kernel_prep_3d(get_sobel_kernel(ksize), n_ch)
gy = tf_kernel_prep_3d(get_sobel_kernel(ksize).T, n_ch)
kernel = tf.constant(np.stack([gx, gy], axis=-1), dtype = np.float32)
return tf.nn.depthwise_conv2d(batch, kernel, [1, 1, 1, 1], padding=padding)
def tf_sharr(batch, ksize=3, padding='SAME'):
n_ch = batch.shape[3].value
gx = tf_kernel_prep_3d([[ -3, 0, 3],
[-10, 0, 10],
[ -3, 0, 3]], n_ch)
gy = tf_kernel_prep_3d([[-3,-10,-3],
[ 0, 0, 0],
[ 3, 10, 3]], n_ch)
kernel = tf.constant(np.stack([gx, gy], axis=-1), dtype = np.float32)
return tf.nn.depthwise_conv2d(batch, kernel, [1, 1, 1, 1], padding=padding)
def tf_laplacian(batch, padding='SAME'):
kernel = np.array([[0, 1, 0],
[1,-4, 1],
[0, 1, 0]], dtype=batch.dtype)
return tf_filter2d(batch, kernel, padding=padding)
def tf_boxfilter(batch, ksize = 3, padding='SAME'):
kernel = np.ones((ksize, ksize), dtype=batch.dtype) / ksize**2
return tf_filter2d(batch, kernel, padding=padding)
def tf_rad2deg(rad):
return 180 * rad / tf.constant(np.pi)