Skip to content

Added gaussian_blur_op #1450

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 84 commits into from
Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
e27bd7f
Gaussian Blur op
ghosalsattam Mar 27, 2020
e1c1562
Adds Average smoothing op
ghosalsattam Mar 27, 2020
0eba6f2
Gaussian Filter
ghosalsattam Mar 27, 2020
ca68de6
Delete averageSmoothing.py
ghosalsattam Mar 28, 2020
60be446
Delete averageSmoothing_test.py
ghosalsattam Mar 28, 2020
1c89c6b
Delete gaussianBlur_ops.py
ghosalsattam Mar 28, 2020
725c3c2
Delete gaussianBlur_ops_test.py
ghosalsattam Mar 28, 2020
f6a952f
Delete gaussianBlur_ops_test.py
ghosalsattam Mar 28, 2020
462f5db
improved test
ghosalsattam Mar 28, 2020
fc17a63
Merge branch 'master' of https://github.com/ghosalsattam/addons
ghosalsattam Mar 28, 2020
2b133f5
improved test
ghosalsattam Mar 28, 2020
494d4f8
added main
ghosalsattam Mar 28, 2020
f82e21e
gaussian
ghosalsattam Mar 28, 2020
a0eba38
test for gaussian Blur
ghosalsattam Mar 28, 2020
c97d764
Merge remote-tracking branch 'upstream/master'
ghosalsattam Mar 28, 2020
4d2f5ee
after flake test
ghosalsattam Mar 28, 2020
d562578
python black
ghosalsattam Mar 28, 2020
8c79b07
Codeowners
ghosalsattam Mar 28, 2020
a2e3950
BUILD
ghosalsattam Mar 28, 2020
f8f5ca2
__init__
ghosalsattam Mar 28, 2020
83128e4
gaussian_blur
ghosalsattam Mar 29, 2020
7b01865
ci test
ghosalsattam Mar 29, 2020
f27eb5d
github check
ghosalsattam Mar 29, 2020
b189c34
github check
ghosalsattam Mar 29, 2020
169a33f
github check
ghosalsattam Mar 29, 2020
32b2ae9
github test
ghosalsattam Mar 29, 2020
3eeca8a
github check
ghosalsattam Mar 29, 2020
a4d32aa
github check
ghosalsattam Mar 29, 2020
4b1fa53
github check
ghosalsattam Mar 29, 2020
7bd60d5
git check
ghosalsattam Mar 29, 2020
ce38bcb
Merge branch 'master' into master
ghosalsattam Mar 29, 2020
f796c9b
github check
ghosalsattam Mar 29, 2020
8b8286b
github check
ghosalsattam Mar 29, 2020
bf13d85
check
ghosalsattam Mar 29, 2020
9f1d492
check
ghosalsattam Mar 29, 2020
cb321aa
ci check
ghosalsattam Mar 30, 2020
08e7632
check
ghosalsattam Mar 30, 2020
dfb9e9a
test
ghosalsattam Mar 30, 2020
1e6b7c9
check
ghosalsattam Mar 30, 2020
8060fa2
test
ghosalsattam Mar 30, 2020
73258f3
github check
ghosalsattam Mar 30, 2020
0908a88
Merge branch 'master' of https://github.com/tensorflow/addons
ghosalsattam Mar 31, 2020
4b59936
github check
ghosalsattam Mar 31, 2020
68e189e
Merge branch 'master' into master
ghosalsattam Apr 2, 2020
07e041f
ci test
ghosalsattam Apr 2, 2020
ffe9547
github check
ghosalsattam Apr 2, 2020
237928a
Merge branch 'master' into master
ghosalsattam Apr 5, 2020
6fa811b
Merge branch 'master' into master
ghosalsattam Apr 6, 2020
687c1ac
merge conflict remove
ghosalsattam Apr 6, 2020
babe83a
resolve conflict
ghosalsattam Apr 6, 2020
3d8ed07
github check
ghosalsattam Apr 6, 2020
0e77a24
github check
ghosalsattam Apr 6, 2020
2566d0f
github check
ghosalsattam Apr 6, 2020
ee996e9
github check
ghosalsattam Apr 6, 2020
9039c91
Changed the kernel computing technique
ghosalsattam Apr 7, 2020
cc79bbb
github test
ghosalsattam Apr 7, 2020
c19cbc6
github check
ghosalsattam Apr 7, 2020
6d8b2d2
github check
ghosalsattam Apr 7, 2020
a59c732
github test
ghosalsattam Apr 7, 2020
219c0d7
Merge branch 'master' into master
ghosalsattam Apr 11, 2020
980c3f9
github check
ghosalsattam Apr 11, 2020
0662ed1
Shifted to filters.py
ghosalsattam Apr 20, 2020
630738e
changed codeowners
ghosalsattam Apr 20, 2020
9733ed1
revert codeowners changes
ghosalsattam Apr 21, 2020
08ec627
changed codeowners
ghosalsattam Apr 21, 2020
ab4d65d
codeowners
ghosalsattam Apr 21, 2020
5224755
Changed TO NHWC format
ghosalsattam Apr 22, 2020
ce7e229
github check
ghosalsattam Apr 22, 2020
f8fe174
Update filters.py
ghosalsattam Apr 23, 2020
4c1431a
github check
ghosalsattam Apr 23, 2020
3ae9b67
github check
ghosalsattam Apr 23, 2020
31aa403
Github Check
ghosalsattam Apr 23, 2020
c58e3a3
new commit
ghosalsattam Apr 23, 2020
283009a
changed to float32
ghosalsattam Apr 23, 2020
2a14a4d
increased flexibility of kernel_size
ghosalsattam Apr 23, 2020
c99f195
added name parameter for the gaussian blur op
ghosalsattam Apr 23, 2020
21ef57e
changed documentation
ghosalsattam Apr 23, 2020
4f57ca4
update __init__.py
ghosalsattam Apr 24, 2020
a1cf163
Added 2D convolution Along with sequence of 1D convolution
ghosalsattam Apr 28, 2020
97117fd
Added experimental_compile
ghosalsattam Apr 29, 2020
a8b9566
revert
ghosalsattam Apr 29, 2020
6f711cc
Merge branch 'master' of https://github.com/tensorflow/addons
ghosalsattam Apr 29, 2020
cd9f5ed
github check
ghosalsattam Apr 29, 2020
7b6bf24
githun check
ghosalsattam Apr 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@
/tensorflow_addons/image/tests/distance_transform_test.py @mels630
/tensorflow_addons/image/distort_image_ops.py @windqaq
/tensorflow_addons/image/tests/distort_image_ops_test.py @windqaq
/tensorflow_addons/image/filters.py @mainak431
/tensorflow_addons/image/tests/filters_test.py @mainak431
/tensorflow_addons/image/filters.py @mainak431 @ghosalsattam
/tensorflow_addons/image/tests/filters_test.py @mainak431 @ghosalsattam
/tensorflow_addons/image/interpolate_spline.py
/tensorflow_addons/image/tests/interpolate_spline_test.py
/tensorflow_addons/image/resampler_ops.py @autoih
Expand Down
1 change: 1 addition & 0 deletions tensorflow_addons/image/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from tensorflow_addons.image.distance_transform import euclidean_dist_transform
from tensorflow_addons.image.dense_image_warp import interpolate_bilinear
from tensorflow_addons.image.interpolate_spline import interpolate_spline
from tensorflow_addons.image.filters import gaussian_filter2d
from tensorflow_addons.image.filters import mean_filter2d
from tensorflow_addons.image.filters import median_filter2d
from tensorflow_addons.image.cutout_ops import random_cutout
Expand Down
90 changes: 90 additions & 0 deletions tensorflow_addons/image/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,93 @@ def median_filter2d(
output = tf.cast(median, image.dtype)
output = img_utils.from_4D_image(output, original_ndims)
return output


def _get_gaussian_kernel(sigma, filter_shape_1d):
"This function creates a kernel of size [filter_shape]"
x = tf.range(-filter_shape_1d // 2 + 1, filter_shape_1d // 2 + 1)
x = tf.math.square(x)
a = tf.exp(-(x) / (2 * (sigma ** 2)))
a = a / tf.math.reduce_sum(a)
return a


def _get_gaussian_kernel_2d(gaussian_filter_x, gaussian_filter_y):
"Compute 2D Gaussian Kernel"
gaussian_kernel = tf.matmul(gaussian_filter_x, gaussian_filter_y)
return gaussian_kernel


@tf.function
def gaussian_filter2d(
image: FloatTensorLike,
filter_shape: Union[List[int], Tuple[int]] = [3, 3],
sigma: FloatTensorLike = 1,
padding: str = "REFLECT",
constant_values: TensorLike = 0,
name: Optional[str] = None,
) -> FloatTensorLike:
"""Perform Gaussian Blur.

Args:
image: Either a 2-D `Tensor` of shape `[height, width]`,
a 3-D `Tensor` of shape `[height, width, channels]`,
or a 4-D `Tensor` of shape `[batch_size, height, width, channels]`.
filter_shape: An `integer` or `tuple`/`list` of 2 integers, specifying
the height and width of the 2-D median filter. Can be a single integer
to specify the same value for all spatial dimensions.
sigma: Standard deviation of Gaussian.
padding: A `string`, one of "REFLECT", "CONSTANT", or "SYMMETRIC".
The type of padding algorithm to use, which is compatible with
`mode` argument in `tf.pad`. For more details, please refer to
https://www.tensorflow.org/api_docs/python/tf/pad.
constant_values: A `scalar`, the pad value to use in "CONSTANT"
padding mode.
name: A name for this operation (optional).
Returns:
3-D or 4-D `Tensor` of the same dtype as input.
Raises:
ValueError: If `image` is not 2, 3 or 4-dimensional,
if `padding` is other than "REFLECT", "CONSTANT" or "SYMMETRIC",
or if `filter_shape` is invalid or sigma<=0.
"""
with tf.name_scope(name or "gaussian_filter2d"):
if sigma <= 0:
raise ValueError("Sigma should not be zero")
if padding not in ["REFLECT", "CONSTANT", "SYMMETRIC"]:
raise ValueError("Padding should be REFLECT, CONSTANT, OR SYMMETRIC")

image = tf.cast(image, tf.float32)
original_ndims = img_utils.get_ndims(image)
image = img_utils.to_4D_image(image)
channels = tf.shape(image)[3]
filter_shape = keras_utils.normalize_tuple(filter_shape, 2, "filter_shape")

gaussian_filter_x = _get_gaussian_kernel(sigma, filter_shape[1])
gaussian_filter_x = tf.cast(gaussian_filter_x, tf.float32)
gaussian_filter_x = tf.reshape(gaussian_filter_x, [1, filter_shape[1]])

gaussian_filter_y = _get_gaussian_kernel(sigma, filter_shape[0])
gaussian_filter_y = tf.reshape(gaussian_filter_y, [filter_shape[0], 1])
gaussian_filter_y = tf.cast(gaussian_filter_y, tf.float32)

gaussian_filter_2d = _get_gaussian_kernel_2d(
gaussian_filter_y, gaussian_filter_x
)
gaussian_filter_2d = tf.repeat(gaussian_filter_2d, channels)
gaussian_filter_2d = tf.reshape(
gaussian_filter_2d, [filter_shape[0], filter_shape[1], channels, 1]
)

image = _pad(
image, filter_shape, mode=padding, constant_values=constant_values,
)

output = tf.nn.depthwise_conv2d(
input=image,
filter=gaussian_filter_2d,
strides=(1, 1, 1, 1),
padding="VALID",
)
output = img_utils.from_4D_image(output, original_ndims)
return output
112 changes: 112 additions & 0 deletions tensorflow_addons/image/tests/filters_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import tensorflow as tf
from tensorflow_addons.image import mean_filter2d
from tensorflow_addons.image import median_filter2d
from tensorflow_addons.image import gaussian_filter2d
from skimage.filters import gaussian

_dtypes_to_test = {
tf.dtypes.uint8,
Expand Down Expand Up @@ -359,3 +361,113 @@ def test_symmetric_padding_with_3x3_filter_median(image_shape):
constant_values=0,
expected_plane=expected_plane,
)


@pytest.mark.usefixtures("maybe_run_functions_eagerly")
def test_gaussian_filter2d_constant():
test_image_tf = tf.random.uniform(
[1, 40, 40, 1], minval=0, maxval=255, dtype=tf.float64
)
gb = gaussian_filter2d(test_image_tf, 5, 1, padding="CONSTANT")
gb = gb.numpy()
gb1 = np.resize(gb, (40, 40))
test_image_np = test_image_tf.numpy()
test_image_np = np.resize(test_image_np, [40, 40])
gb2 = gaussian(test_image_np, 1, mode="constant")
np.testing.assert_allclose(gb2, gb1, 0.06)


@pytest.mark.usefixtures("maybe_run_functions_eagerly")
def test_gaussian_filter2d_reflect():
test_image_tf = tf.random.uniform(
[1, 40, 40, 1], minval=0, maxval=255, dtype=tf.float32
)
gb = gaussian_filter2d(test_image_tf, 5, 1, padding="REFLECT")
gb = gb.numpy()
gb1 = np.resize(gb, (40, 40))
test_image_np = test_image_tf.numpy()
test_image_np = np.resize(test_image_np, [40, 40])
gb2 = gaussian(test_image_np, 1, mode="mirror")
np.testing.assert_allclose(gb2, gb1, 0.06)


@pytest.mark.usefixtures("maybe_run_functions_eagerly")
def test_gaussian_filter2d_symmetric():
test_image_tf = tf.random.uniform(
[1, 40, 40, 1], minval=0, maxval=255, dtype=tf.float64
)
gb = gaussian_filter2d(test_image_tf, (5, 5), 1, padding="SYMMETRIC")
gb = gb.numpy()
gb1 = np.resize(gb, (40, 40))
test_image_np = test_image_tf.numpy()
test_image_np = np.resize(test_image_np, [40, 40])
gb2 = gaussian(test_image_np, 1, mode="reflect")
np.testing.assert_allclose(gb2, gb1, 0.06)


@pytest.mark.usefixtures("maybe_run_functions_eagerly")
@pytest.mark.parametrize("image_shape", [[2, 5, 5, 3]])
def test_gaussian_filter2d_batch(image_shape):
test_image_tf = tf.random.uniform(
[1, 40, 40, 1], minval=0, maxval=255, dtype=tf.float32
)
gb = gaussian_filter2d(test_image_tf, 5, 1, padding="SYMMETRIC")
gb = gb.numpy()
gb1 = np.resize(gb, (40, 40))
test_image_np = test_image_tf.numpy()
test_image_np = np.resize(test_image_np, [40, 40])
gb2 = gaussian(test_image_np, 1, mode="reflect")
np.testing.assert_allclose(gb2, gb1, 0.06)


@pytest.mark.usefixtures("maybe_run_functions_eagerly")
def test_gaussian_filter2d_channels():
test_image_tf = tf.constant(
[
[
[
[0.0, 0.0, 0.0],
[2.0, 2.0, 0.0],
[4.0, 4.0, 0.0],
[6.0, 6.0, 0.0],
[8.0, 8.0, 0.0],
],
[
[10.0, 10.0, 0.0],
[12.0, 12.0, 0.0],
[14.0, 14.0, 0.0],
[16.0, 16.0, 0.0],
[18.0, 18.0, 0.0],
],
[
[20.0, 20.0, 0.0],
[22.0, 22.0, 0.0],
[24.0, 24.0, 0.0],
[26.0, 26.0, 0.0],
[28.0, 28.0, 0.0],
],
[
[30.0, 30.0, 0.0],
[32.0, 32.0, 0.0],
[34.0, 34.0, 0.0],
[36.0, 36.0, 0.0],
[38.0, 38.0, 0.0],
],
[
[40.0, 40.0, 0.0],
[42.0, 42.0, 0.0],
[44.0, 44.0, 0.0],
[46.0, 46.0, 0.0],
[48.0, 48.0, 0.0],
],
]
],
dtype=tf.float32,
)
gb = gaussian_filter2d(test_image_tf, 5, 1, padding="SYMMETRIC", name="gaussian")
gb = gb.numpy()
gb1 = np.resize(gb, (5, 5, 3))
test_image_np = test_image_tf.numpy()
test_image_np = np.resize(test_image_np, [5, 5, 3])
gb2 = gaussian(test_image_np, sigma=1, mode="reflect", multichannel=True)
np.testing.assert_allclose(gb2, gb1, 0.06)