Skip to content

Commit 2595947

Browse files
author
NoobMaster
authored
Blend Image Op (#1275)
* autoaugment, no changes * autoaugment with tfa and tf2 * removed contrib_training, hparams for now * Delete hparam.py * init augment_ops, added blend * typo in BUILD * added random test, round, unint8 ValueError * fixed build * image test * add previous tests * removed image test
1 parent 69be560 commit 2595947

File tree

4 files changed

+162
-0
lines changed

4 files changed

+162
-0
lines changed

Diff for: tensorflow_addons/image/BUILD

+13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ py_library(
1717
"interpolate_spline.py",
1818
"connected_components.py",
1919
"resampler_ops.py",
20+
"compose_ops.py",
2021
]),
2122
data = [
2223
":sparse_image_warp_test_data",
@@ -164,3 +165,15 @@ py_test(
164165
":image",
165166
],
166167
)
168+
169+
py_test(
170+
name = "compose_ops_test",
171+
size = "medium",
172+
srcs = [
173+
"compose_ops_test.py",
174+
],
175+
main = "compose_ops_test.py",
176+
deps = [
177+
":image",
178+
],
179+
)

Diff for: tensorflow_addons/image/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@
2828
from tensorflow_addons.image.transform_ops import rotate
2929
from tensorflow_addons.image.transform_ops import transform
3030
from tensorflow_addons.image.translate_ops import translate
31+
from tensorflow_addons.image.compose_ops import blend

Diff for: tensorflow_addons/image/compose_ops.py

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ==============================================================================
15+
"""Compose Ops"""
16+
17+
import tensorflow as tf
18+
19+
from tensorflow_addons.utils.types import TensorLike
20+
21+
22+
def blend(image1: TensorLike, image2: TensorLike, factor: float) -> TensorLike:
23+
"""Blend image1 and image2 using 'factor'.
24+
25+
Factor can be above 0.0. A value of 0.0 means only image1 is used.
26+
A value of 1.0 means only image2 is used. A value between 0.0 and
27+
1.0 means we linearly interpolate the pixel values between the two
28+
images. A value greater than 1.0 "extrapolates" the difference
29+
between the two pixel values, and we clip the results to values
30+
between 0 and 255.
31+
32+
Args:
33+
image1: An image Tensor of type uint8.
34+
image2: An image Tensor of type uint8.
35+
factor: A floating point value above 0.0.
36+
37+
Returns:
38+
A blended image Tensor of type uint8.
39+
40+
"""
41+
with tf.name_scope("blend"):
42+
if image1.dtype != tf.uint8 or image2.dtype != tf.uint8:
43+
raise ValueError("Images must have dtype tf.uint8")
44+
45+
if factor == 0.0:
46+
return tf.convert_to_tensor(image1)
47+
if factor == 1.0:
48+
return tf.convert_to_tensor(image2)
49+
50+
image1 = tf.cast(image1, dtype=tf.dtypes.float32)
51+
image2 = tf.cast(image2, dtype=tf.dtypes.float32)
52+
53+
difference = image2 - image1
54+
scaled = factor * difference
55+
56+
# Do addition in float.
57+
temp = image1 + scaled
58+
59+
# Interpolate
60+
if factor > 0.0 and factor < 1.0:
61+
# Interpolation means we always stay within 0 and 255.
62+
temp = tf.round(temp)
63+
return tf.cast(temp, tf.dtypes.uint8)
64+
65+
# Extrapolate:
66+
#
67+
# We need to clip and then cast.
68+
temp = tf.round(tf.clip_by_value(temp, 0.0, 255.0))
69+
return tf.cast(temp, tf.dtypes.uint8)

Diff for: tensorflow_addons/image/compose_ops_test.py

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ==============================================================================
15+
"""Tests of augmentation ops"""
16+
17+
import sys
18+
import pytest
19+
import tensorflow as tf
20+
import numpy as np
21+
22+
from tensorflow_addons.image import compose_ops
23+
from tensorflow_addons.utils import test_utils
24+
25+
_DTYPES = {
26+
tf.dtypes.uint8,
27+
}
28+
29+
30+
def blend_np(image1, image2, factor):
31+
image1 = image1.astype("float32")
32+
image2 = image2.astype("float32")
33+
difference = image2 - image1
34+
scaled = factor * difference
35+
temp = image1 + scaled
36+
if factor >= 0.0 and factor <= 1.0:
37+
temp = np.round(temp)
38+
return temp.astype("uint8")
39+
temp = np.round(np.clip(temp, 0.0, 255.0))
40+
return temp.astype("uint8")
41+
42+
43+
@test_utils.run_all_in_graph_and_eager_modes
44+
class ComposeOpTest(tf.test.TestCase):
45+
def test_blend(self):
46+
for dtype in _DTYPES:
47+
image1 = tf.constant(
48+
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], dtype=dtype
49+
)
50+
image2 = tf.constant(
51+
[
52+
[255, 255, 255, 255],
53+
[255, 255, 255, 255],
54+
[255, 255, 255, 255],
55+
[255, 255, 255, 255],
56+
],
57+
dtype=dtype,
58+
)
59+
blended = compose_ops.blend(image1, image2, 0.5)
60+
self.assertAllEqual(
61+
self.evaluate(blended),
62+
[
63+
[128, 128, 128, 128],
64+
[128, 128, 128, 128],
65+
[128, 128, 128, 128],
66+
[128, 128, 128, 128],
67+
],
68+
)
69+
70+
image1 = np.random.randint(0, 255, (4, 4, 3), np.uint8)
71+
image2 = np.random.randint(0, 255, (4, 4, 3), np.uint8)
72+
blended = compose_ops.blend(
73+
tf.convert_to_tensor(image1), tf.convert_to_tensor(image2), 0.35
74+
)
75+
self.assertAllEqual(self.evaluate(blended), blend_np(image1, image2, 0.35))
76+
77+
78+
if __name__ == "__main__":
79+
sys.exit(pytest.main([__file__]))

0 commit comments

Comments
 (0)