1773 lines
63 KiB
Python
1773 lines
63 KiB
Python
from __future__ import print_function, division, absolute_import
|
|
|
|
import time
|
|
import warnings
|
|
import sys
|
|
# unittest only added in 3.4 self.subTest()
|
|
if sys.version_info[0] < 3 or sys.version_info[1] < 4:
|
|
import unittest2 as unittest
|
|
else:
|
|
import unittest
|
|
# unittest.mock is not available in 2.7 (though unittest2 might contain it?)
|
|
try:
|
|
import unittest.mock as mock
|
|
except ImportError:
|
|
import mock
|
|
|
|
import matplotlib
|
|
matplotlib.use('Agg') # fix execution of tests involving matplotlib on travis
|
|
import numpy as np
|
|
import six.moves as sm
|
|
import cv2
|
|
|
|
import imgaug as ia
|
|
from imgaug import dtypes as iadt
|
|
import imgaug.random as iarandom
|
|
from imgaug.testutils import assertWarns
|
|
|
|
# TODO clean up this file
|
|
|
|
|
|
def main():
|
|
time_start = time.time()
|
|
|
|
test_is_np_array()
|
|
test_is_single_integer()
|
|
test_is_single_float()
|
|
test_is_single_number()
|
|
test_is_iterable()
|
|
test_is_string()
|
|
test_is_single_bool()
|
|
test_is_integer_array()
|
|
test_is_float_array()
|
|
test_is_callable()
|
|
test_caller_name()
|
|
# test_seed()
|
|
# test_current_random_state()
|
|
# test_new_random_state()
|
|
# test_dummy_random_state()
|
|
# test_copy_random_state()
|
|
# test_derive_random_state()
|
|
# test_derive_random_states()
|
|
# test_forward_random_state()
|
|
# test_angle_between_vectors()
|
|
test_compute_line_intersection_point()
|
|
test_draw_text()
|
|
test_imresize_many_images()
|
|
test_imresize_single_image()
|
|
test_pool()
|
|
test_avg_pool()
|
|
test_max_pool()
|
|
test_min_pool()
|
|
test_draw_grid()
|
|
# test_show_grid()
|
|
# test_do_assert()
|
|
# test_HooksImages_is_activated()
|
|
# test_HooksImages_is_propagating()
|
|
# test_HooksImages_preprocess()
|
|
# test_HooksImages_postprocess()
|
|
test_classes_and_functions_marked_deprecated()
|
|
|
|
time_end = time.time()
|
|
print("<%s> Finished without errors in %.4fs." % (__file__, time_end - time_start,))
|
|
|
|
|
|
def test_is_np_array():
|
|
class _Dummy(object):
|
|
pass
|
|
values_true = [
|
|
np.zeros((1, 2), dtype=np.uint8),
|
|
np.zeros((64, 64, 3), dtype=np.uint8),
|
|
np.zeros((1, 2), dtype=np.float32),
|
|
np.zeros((100,), dtype=np.float64)
|
|
]
|
|
values_false = [
|
|
"A", "BC", "1", True, False, (1.0, 2.0), [1.0, 2.0], _Dummy(),
|
|
-100, 1, 0, 1, 100, -1.2, -0.001, 0.0, 0.001, 1.2, 1e-4
|
|
]
|
|
for value in values_true:
|
|
assert ia.is_np_array(value) is True
|
|
for value in values_false:
|
|
assert ia.is_np_array(value) is False
|
|
|
|
|
|
def test_is_single_integer():
|
|
assert ia.is_single_integer("A") is False
|
|
assert ia.is_single_integer(None) is False
|
|
assert ia.is_single_integer(1.2) is False
|
|
assert ia.is_single_integer(1.0) is False
|
|
assert ia.is_single_integer(np.ones((1,), dtype=np.float32)[0]) is False
|
|
assert ia.is_single_integer(1) is True
|
|
assert ia.is_single_integer(1234) is True
|
|
assert ia.is_single_integer(np.ones((1,), dtype=np.uint8)[0]) is True
|
|
assert ia.is_single_integer(np.ones((1,), dtype=np.int32)[0]) is True
|
|
|
|
|
|
def test_is_single_float():
|
|
assert ia.is_single_float("A") is False
|
|
assert ia.is_single_float(None) is False
|
|
assert ia.is_single_float(1.2) is True
|
|
assert ia.is_single_float(1.0) is True
|
|
assert ia.is_single_float(np.ones((1,), dtype=np.float32)[0]) is True
|
|
assert ia.is_single_float(1) is False
|
|
assert ia.is_single_float(1234) is False
|
|
assert ia.is_single_float(np.ones((1,), dtype=np.uint8)[0]) is False
|
|
assert ia.is_single_float(np.ones((1,), dtype=np.int32)[0]) is False
|
|
|
|
|
|
def test_caller_name():
|
|
assert ia.caller_name() == 'test_caller_name'
|
|
|
|
|
|
class TestDeprecatedDataFunctions(unittest.TestCase):
|
|
def test_quokka(self):
|
|
with assertWarns(self, ia.DeprecationWarning):
|
|
img = ia.quokka()
|
|
assert ia.is_np_array(img)
|
|
|
|
def test_quokka_square(self):
|
|
with assertWarns(self, ia.DeprecationWarning):
|
|
img = ia.quokka_square()
|
|
assert ia.is_np_array(img)
|
|
|
|
def test_quokka_heatmap(self):
|
|
with assertWarns(self, ia.DeprecationWarning):
|
|
result = ia.quokka_heatmap()
|
|
assert isinstance(result, ia.HeatmapsOnImage)
|
|
|
|
def test_quokka_segmentation_map(self):
|
|
with assertWarns(self, ia.DeprecationWarning):
|
|
result = ia.quokka_segmentation_map()
|
|
assert isinstance(result, ia.SegmentationMapsOnImage)
|
|
|
|
def test_quokka_keypoints(self):
|
|
with assertWarns(self, ia.DeprecationWarning):
|
|
result = ia.quokka_keypoints()
|
|
assert isinstance(result, ia.KeypointsOnImage)
|
|
|
|
def test_quokka_bounding_boxes(self):
|
|
with assertWarns(self, ia.DeprecationWarning):
|
|
result = ia.quokka_bounding_boxes()
|
|
assert isinstance(result, ia.BoundingBoxesOnImage)
|
|
|
|
|
|
def test_is_single_number():
|
|
class _Dummy(object):
|
|
pass
|
|
values_true = [-100, 1, 0, 1, 100, -1.2, -0.001, 0.0, 0.001, 1.2, 1e-4]
|
|
values_false = ["A", "BC", "1", True, False, (1.0, 2.0), [1.0, 2.0], _Dummy(), np.zeros((1, 2), dtype=np.uint8)]
|
|
for value in values_true:
|
|
assert ia.is_single_number(value) is True
|
|
for value in values_false:
|
|
assert ia.is_single_number(value) is False
|
|
|
|
|
|
def test_is_iterable():
|
|
class _Dummy(object):
|
|
pass
|
|
values_true = [
|
|
[0, 1, 2],
|
|
["A", "X"],
|
|
[[123], [456, 789]],
|
|
[],
|
|
(1, 2, 3),
|
|
(1,),
|
|
tuple(),
|
|
"A",
|
|
"ABC",
|
|
"",
|
|
np.zeros((100,), dtype=np.uint8)
|
|
]
|
|
values_false = [1, 100, 0, -100, -1, 1.2, -1.2, True, False, _Dummy()]
|
|
for value in values_true:
|
|
assert ia.is_iterable(value) is True, value
|
|
for value in values_false:
|
|
assert ia.is_iterable(value) is False
|
|
|
|
|
|
def test_is_string():
|
|
class _Dummy(object):
|
|
pass
|
|
values_true = ["A", "BC", "1", ""]
|
|
values_false = [-100, 1, 0, 1, 100, -1.2, -0.001, 0.0, 0.001, 1.2, 1e-4, True, False, (1.0, 2.0), [1.0, 2.0],
|
|
_Dummy(), np.zeros((1, 2), dtype=np.uint8)]
|
|
for value in values_true:
|
|
assert ia.is_string(value) is True
|
|
for value in values_false:
|
|
assert ia.is_string(value) is False
|
|
|
|
|
|
def test_is_single_bool():
|
|
class _Dummy(object):
|
|
pass
|
|
values_true = [False, True]
|
|
values_false = [-100, 1, 0, 1, 100, -1.2, -0.001, 0.0, 0.001, 1.2, 1e-4, (1.0, 2.0), [1.0, 2.0], _Dummy(),
|
|
np.zeros((1, 2), dtype=np.uint8), np.zeros((1,), dtype=bool)]
|
|
for value in values_true:
|
|
assert ia.is_single_bool(value) is True
|
|
for value in values_false:
|
|
assert ia.is_single_bool(value) is False
|
|
|
|
|
|
def test_is_integer_array():
|
|
class _Dummy(object):
|
|
pass
|
|
values_true = [
|
|
np.zeros((1, 2), dtype=np.uint8),
|
|
np.zeros((100,), dtype=np.uint8),
|
|
np.zeros((1, 2), dtype=np.uint16),
|
|
np.zeros((1, 2), dtype=np.int32),
|
|
np.zeros((1, 2), dtype=np.int64)
|
|
]
|
|
values_false = [
|
|
"A", "BC", "1", "", -100, 1, 0, 1, 100, -1.2, -0.001, 0.0, 0.001, 1.2, 1e-4, True, False,
|
|
(1.0, 2.0), [1.0, 2.0], _Dummy(),
|
|
np.zeros((1, 2), dtype=np.float16),
|
|
np.zeros((100,), dtype=np.float32),
|
|
np.zeros((1, 2), dtype=np.float64),
|
|
np.zeros((1, 2), dtype=np.bool)
|
|
]
|
|
for value in values_true:
|
|
assert ia.is_integer_array(value) is True
|
|
for value in values_false:
|
|
assert ia.is_integer_array(value) is False
|
|
|
|
|
|
def test_is_float_array():
|
|
class _Dummy(object):
|
|
pass
|
|
|
|
values_true = [
|
|
np.zeros((1, 2), dtype=np.float16),
|
|
np.zeros((100,), dtype=np.float32),
|
|
np.zeros((1, 2), dtype=np.float64)
|
|
]
|
|
values_false = [
|
|
"A", "BC", "1", "", -100, 1, 0, 1, 100, -1.2, -0.001, 0.0, 0.001, 1.2, 1e-4, True, False,
|
|
(1.0, 2.0), [1.0, 2.0], _Dummy(),
|
|
np.zeros((1, 2), dtype=np.uint8),
|
|
np.zeros((100,), dtype=np.uint8),
|
|
np.zeros((1, 2), dtype=np.uint16),
|
|
np.zeros((1, 2), dtype=np.int32),
|
|
np.zeros((1, 2), dtype=np.int64),
|
|
np.zeros((1, 2), dtype=np.bool)
|
|
]
|
|
for value in values_true:
|
|
assert ia.is_float_array(value) is True
|
|
for value in values_false:
|
|
assert ia.is_float_array(value) is False
|
|
|
|
|
|
def test_is_callable():
|
|
def _dummy_func():
|
|
pass
|
|
|
|
_dummy_func2 = lambda x: x
|
|
|
|
class _Dummy1(object):
|
|
pass
|
|
|
|
class _Dummy2(object):
|
|
def __call__(self):
|
|
pass
|
|
|
|
class _Dummy3(object):
|
|
def foo(self):
|
|
pass
|
|
|
|
class _Dummy4(object):
|
|
@classmethod
|
|
def foo(cls):
|
|
pass
|
|
|
|
class _Dummy5(object):
|
|
@classmethod
|
|
def foo(cls):
|
|
pass
|
|
|
|
values_true = [_dummy_func, _dummy_func2, _Dummy2(), _Dummy3().foo,
|
|
_Dummy4.foo, _Dummy5.foo]
|
|
values_false = [
|
|
"A", "BC", "1", "", -100, 1, 0, 1, 100, -1.2, -0.001, 0.0, 0.001, 1.2,
|
|
1e-4, True, False, (1.0, 2.0), [1.0, 2.0], _Dummy1(),
|
|
np.zeros((1, 2), dtype=np.uint8)]
|
|
for value in values_true:
|
|
assert ia.is_callable(value) is True
|
|
for value in values_false:
|
|
assert ia.is_callable(value) is False
|
|
|
|
|
|
@mock.patch("imgaug.random.seed")
|
|
def test_seed(mock_seed):
|
|
ia.seed(10017)
|
|
mock_seed.assert_called_once_with(10017)
|
|
|
|
|
|
def test_current_random_state():
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
rng = ia.current_random_state()
|
|
|
|
assert rng.is_global_rng()
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.RNG")
|
|
def test_new_random_state__induce_pseudo_random(mock_rng):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
_ = ia.new_random_state(seed=None, fully_random=False)
|
|
|
|
assert mock_rng.create_pseudo_random_.call_count == 1
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.RNG")
|
|
def test_new_random_state__induce_fully_random(mock_rng):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
_ = ia.new_random_state(seed=None, fully_random=True)
|
|
|
|
assert mock_rng.create_fully_random.call_count == 1
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.RNG")
|
|
def test_new_random_state__use_seed(mock_rng):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
_ = ia.new_random_state(seed=1)
|
|
|
|
mock_rng.assert_called_once_with(1)
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.RNG")
|
|
def test_dummy_random_state(mock_rng):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
_ = ia.dummy_random_state()
|
|
|
|
mock_rng.assert_called_once_with(1)
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.copy_generator")
|
|
@mock.patch("imgaug.random.copy_generator_unless_global_generator")
|
|
def test_copy_random_state__not_global(mock_copy_gen_glob, mock_copy_gen):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
gen = iarandom.convert_seed_to_generator(1)
|
|
_ = ia.copy_random_state(gen, force_copy=False)
|
|
|
|
assert mock_copy_gen.call_count == 0
|
|
mock_copy_gen_glob.assert_called_once_with(gen)
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.copy_generator")
|
|
@mock.patch("imgaug.random.copy_generator_unless_global_generator")
|
|
def test_copy_random_state__also_global(mock_copy_gen_glob, mock_copy_gen):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
gen = iarandom.convert_seed_to_generator(1)
|
|
_ = ia.copy_random_state(gen, force_copy=True)
|
|
|
|
mock_copy_gen.assert_called_once_with(gen)
|
|
assert mock_copy_gen_glob.call_count == 0
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.derive_generator_")
|
|
def test_derive_random_state(mock_derive):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
gen = iarandom.convert_seed_to_generator(1)
|
|
_ = ia.derive_random_state(gen)
|
|
|
|
mock_derive.assert_called_once_with(gen)
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.derive_generators_")
|
|
def test_derive_random_states(mock_derive):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
gen = iarandom.convert_seed_to_generator(1)
|
|
_ = ia.derive_random_states(gen, n=2)
|
|
|
|
mock_derive.assert_called_once_with(gen, n=2)
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
@mock.patch("imgaug.random.advance_generator_")
|
|
def test_forward_random_state(mock_advance):
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
gen = iarandom.convert_seed_to_generator(1)
|
|
_ = ia.forward_random_state(gen)
|
|
|
|
mock_advance.assert_called_once_with(gen)
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
|
|
def test_compute_line_intersection_point():
|
|
# intersecting lines
|
|
line1 = (0, 0, 1, 0)
|
|
line2 = (0.5, -1, 0.5, 1)
|
|
point = ia.compute_line_intersection_point(
|
|
line1[0], line1[1], line1[2], line1[3],
|
|
line2[0], line2[1], line2[2], line2[3]
|
|
)
|
|
assert np.allclose(point[0], 0.5)
|
|
assert np.allclose(point[1], 0)
|
|
|
|
# intersection point outside of defined interval of one line, should not change anything
|
|
line1 = (0, 0, 1, 0)
|
|
line2 = (0.5, -1, 0.5, -0.5)
|
|
point = ia.compute_line_intersection_point(
|
|
line1[0], line1[1], line1[2], line1[3],
|
|
line2[0], line2[1], line2[2], line2[3]
|
|
)
|
|
assert np.allclose(point[0], 0.5)
|
|
assert np.allclose(point[1], 0)
|
|
|
|
# touching lines
|
|
line1 = (0, 0, 1, 0)
|
|
line2 = (0.5, -1, 0.5, 0)
|
|
point = ia.compute_line_intersection_point(
|
|
line1[0], line1[1], line1[2], line1[3],
|
|
line2[0], line2[1], line2[2], line2[3]
|
|
)
|
|
assert np.allclose(point[0], 0.5)
|
|
assert np.allclose(point[1], 0)
|
|
|
|
# parallel, not intersecting lines
|
|
line1 = (0, 0, 1, 0)
|
|
line2 = (0, -0.1, 1, -0.1)
|
|
point = ia.compute_line_intersection_point(
|
|
line1[0], line1[1], line1[2], line1[3],
|
|
line2[0], line2[1], line2[2], line2[3]
|
|
)
|
|
assert point is False
|
|
|
|
# parallel and overlapping lines (infinite intersection points)
|
|
line1 = (0, 0, 1, 0)
|
|
line2 = (0.1, 0, 1, 0)
|
|
point = ia.compute_line_intersection_point(
|
|
line1[0], line1[1], line1[2], line1[3],
|
|
line2[0], line2[1], line2[2], line2[3]
|
|
)
|
|
assert point is False
|
|
|
|
|
|
def test_draw_text():
|
|
# make roughly sure that shape of drawn text matches expected text
|
|
img = np.zeros((20, 50, 3), dtype=np.uint8)
|
|
img_text = ia.draw_text(img, y=5, x=5, text="---------", size=10, color=[255, 255, 255])
|
|
assert np.max(img_text) == 255
|
|
assert np.min(img_text) == 0
|
|
assert np.sum(img_text == 255) / np.sum(img_text == 0)
|
|
first_row = None
|
|
last_row = None
|
|
first_col = None
|
|
last_col = None
|
|
for i in range(img.shape[0]):
|
|
if np.max(img_text[i, :, :]) == 255:
|
|
first_row = i
|
|
break
|
|
for i in range(img.shape[0]-1, 0, -1):
|
|
if np.max(img_text[i, :, :]) == 255:
|
|
last_row = i
|
|
break
|
|
for i in range(img.shape[1]):
|
|
if np.max(img_text[:, i, :]) == 255:
|
|
first_col = i
|
|
break
|
|
for i in range(img.shape[1]-1, 0, -1):
|
|
if np.max(img_text[:, i, :]) == 255:
|
|
last_col = i
|
|
break
|
|
bb = ia.BoundingBox(x1=first_col, y1=first_row, x2=last_col, y2=last_row)
|
|
assert bb.width > 4.0*bb.height
|
|
|
|
# test x
|
|
img = np.zeros((20, 100, 3), dtype=np.uint8)
|
|
img_text1 = ia.draw_text(img, y=5, x=5, text="XXXXXXX", size=10, color=[255, 255, 255])
|
|
img_text2 = ia.draw_text(img, y=5, x=50, text="XXXXXXX", size=10, color=[255, 255, 255])
|
|
first_col1 = None
|
|
first_col2 = None
|
|
for i in range(img.shape[1]):
|
|
if np.max(img_text1[:, i, :]) == 255:
|
|
first_col1 = i
|
|
break
|
|
for i in range(img.shape[1]):
|
|
if np.max(img_text2[:, i, :]) == 255:
|
|
first_col2 = i
|
|
break
|
|
assert 0 < first_col1 < 10
|
|
assert 45 < first_col2 < 55
|
|
|
|
# test y
|
|
img = np.zeros((100, 20, 3), dtype=np.uint8)
|
|
img_text1 = ia.draw_text(img, y=5, x=5, text="XXXXXXX", size=10, color=[255, 255, 255])
|
|
img_text2 = ia.draw_text(img, y=50, x=5, text="XXXXXXX", size=10, color=[255, 255, 255])
|
|
first_row1 = None
|
|
first_row2 = None
|
|
for i in range(img.shape[0]):
|
|
if np.max(img_text1[i, :, :]) == 255:
|
|
first_row1 = i
|
|
break
|
|
for i in range(img.shape[0]):
|
|
if np.max(img_text2[i, :, :]) == 255:
|
|
first_row2 = i
|
|
break
|
|
assert 0 < first_row1 < 15
|
|
assert 45 < first_row2 < 60
|
|
|
|
# test size
|
|
img = np.zeros((100, 100, 3), dtype=np.uint8)
|
|
img_text_small = ia.draw_text(img, y=5, x=5, text="X", size=10, color=[255, 255, 255])
|
|
img_text_large = ia.draw_text(img, y=5, x=5, text="X", size=50, color=[255, 255, 255])
|
|
nb_filled_small = np.sum(img_text_small > 10)
|
|
nb_filled_large = np.sum(img_text_large > 10)
|
|
assert nb_filled_large > 2*nb_filled_small
|
|
|
|
# text color
|
|
img = np.zeros((20, 20, 3), dtype=np.uint8)
|
|
img_text = ia.draw_text(img, y=5, x=5, text="X", size=10, color=[128, 129, 130])
|
|
maxcol = np.max(img_text, axis=(0, 1))
|
|
assert maxcol[0] == 128
|
|
assert maxcol[1] == 129
|
|
assert maxcol[2] == 130
|
|
|
|
|
|
def test_imresize_many_images():
|
|
interpolations = [None,
|
|
"nearest", "linear", "area", "cubic",
|
|
cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_AREA, cv2.INTER_CUBIC]
|
|
|
|
for c in [1, 3]:
|
|
image1 = np.zeros((16, 16, c), dtype=np.uint8) + 255
|
|
image2 = np.zeros((16, 16, c), dtype=np.uint8)
|
|
image3 = np.pad(
|
|
np.zeros((8, 8, c), dtype=np.uint8) + 255,
|
|
((4, 4), (4, 4), (0, 0)),
|
|
mode="constant",
|
|
constant_values=0
|
|
)
|
|
|
|
image1_small = np.zeros((8, 8, c), dtype=np.uint8) + 255
|
|
image2_small = np.zeros((8, 8, c), dtype=np.uint8)
|
|
image3_small = np.pad(
|
|
np.zeros((4, 4, c), dtype=np.uint8) + 255,
|
|
((2, 2), (2, 2), (0, 0)),
|
|
mode="constant",
|
|
constant_values=0
|
|
)
|
|
|
|
image1_large = np.zeros((32, 32, c), dtype=np.uint8) + 255
|
|
image2_large = np.zeros((32, 32, c), dtype=np.uint8)
|
|
image3_large = np.pad(
|
|
np.zeros((16, 16, c), dtype=np.uint8) + 255,
|
|
((8, 8), (8, 8), (0, 0)),
|
|
mode="constant",
|
|
constant_values=0
|
|
)
|
|
|
|
images = np.uint8([image1, image2, image3])
|
|
images_small = np.uint8([image1_small, image2_small, image3_small])
|
|
images_large = np.uint8([image1_large, image2_large, image3_large])
|
|
|
|
for images_this_iter in [images, list(images)]: # test for ndarray and list(ndarray) input
|
|
for interpolation in interpolations:
|
|
images_same_observed = ia.imresize_many_images(images_this_iter, (16, 16), interpolation=interpolation)
|
|
for image_expected, image_observed in zip(images_this_iter, images_same_observed):
|
|
diff = np.abs(image_expected.astype(np.int32) - image_observed.astype(np.int32))
|
|
assert np.sum(diff) == 0
|
|
|
|
for interpolation in interpolations:
|
|
images_small_observed = ia.imresize_many_images(images_this_iter, (8, 8), interpolation=interpolation)
|
|
for image_expected, image_observed in zip(images_small, images_small_observed):
|
|
diff = np.abs(image_expected.astype(np.int32) - image_observed.astype(np.int32))
|
|
diff_fraction = np.sum(diff) / (image_observed.size * 255)
|
|
assert diff_fraction < 0.5
|
|
|
|
for interpolation in interpolations:
|
|
images_large_observed = ia.imresize_many_images(images_this_iter, (32, 32), interpolation=interpolation)
|
|
for image_expected, image_observed in zip(images_large, images_large_observed):
|
|
diff = np.abs(image_expected.astype(np.int32) - image_observed.astype(np.int32))
|
|
diff_fraction = np.sum(diff) / (image_observed.size * 255)
|
|
assert diff_fraction < 0.5
|
|
|
|
# test size given as single int
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, 8)
|
|
assert observed.shape == (1, 8, 8, 3)
|
|
|
|
# test size given as single float
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, 2.0)
|
|
assert observed.shape == (1, 8, 8, 3)
|
|
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, 0.5)
|
|
assert observed.shape == (1, 2, 2, 3)
|
|
|
|
# test size given as (float, float)
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, (2.0, 2.0))
|
|
assert observed.shape == (1, 8, 8, 3)
|
|
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, (0.5, 0.5))
|
|
assert observed.shape == (1, 2, 2, 3)
|
|
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, (2.0, 0.5))
|
|
assert observed.shape == (1, 8, 2, 3)
|
|
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, (0.5, 2.0))
|
|
assert observed.shape == (1, 2, 8, 3)
|
|
|
|
# test size given as int+float or float+int
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, (11, 2.0))
|
|
assert observed.shape == (1, 11, 8, 3)
|
|
|
|
images = np.zeros((1, 4, 4, 3), dtype=np.uint8)
|
|
observed = ia.imresize_many_images(images, (2.0, 11))
|
|
assert observed.shape == (1, 8, 11, 3)
|
|
|
|
# test no channels
|
|
images = np.zeros((1, 4, 4), dtype=np.uint8)
|
|
images_rs = ia.imresize_many_images(images, (2, 2))
|
|
assert images_rs.shape == (1, 2, 2)
|
|
|
|
images = [np.zeros((4, 4), dtype=np.uint8)]
|
|
images_rs = ia.imresize_many_images(images, (2, 2))
|
|
assert isinstance(images_rs, list)
|
|
assert images_rs[0].shape == (2, 2)
|
|
|
|
# test len 0 input
|
|
observed = ia.imresize_many_images(np.zeros((0, 8, 8, 3), dtype=np.uint8), (4, 4))
|
|
assert ia.is_np_array(observed)
|
|
assert observed.dtype.type == np.uint8
|
|
assert len(observed) == 0
|
|
|
|
observed = ia.imresize_many_images([], (4, 4))
|
|
assert isinstance(observed, list)
|
|
assert len(observed) == 0
|
|
|
|
# test images with zero height/width
|
|
shapes = [(0, 4, 3), (4, 0, 3), (0, 0, 3)]
|
|
for shape in shapes:
|
|
images = [np.zeros(shape, dtype=np.uint8)]
|
|
got_exception = False
|
|
try:
|
|
_ = ia.imresize_many_images(images, sizes=(2, 2))
|
|
except Exception as exc:
|
|
assert (
|
|
"Cannot resize images, because at least one image has a height "
|
|
"and/or width and/or number of channels of zero."
|
|
in str(exc)
|
|
)
|
|
got_exception = True
|
|
assert got_exception
|
|
|
|
# test invalid sizes
|
|
sizes_all = [(-1, 2)]
|
|
sizes_all = sizes_all\
|
|
+ [(float(a), b) for a, b in sizes_all]\
|
|
+ [(a, float(b)) for a, b in sizes_all]\
|
|
+ [(float(a), float(b)) for a, b in sizes_all]\
|
|
+ [(-a, -b) for a, b in sizes_all]\
|
|
+ [(-float(a), -b) for a, b in sizes_all]\
|
|
+ [(-a, -float(b)) for a, b in sizes_all]\
|
|
+ [(-float(a), -float(b)) for a, b in sizes_all]
|
|
sizes_all = sizes_all\
|
|
+ [(b, a) for a, b in sizes_all]
|
|
sizes_all = sizes_all\
|
|
+ [-1.0, -1]
|
|
for sizes in sizes_all:
|
|
images = [np.zeros((4, 4, 3), dtype=np.uint8)]
|
|
got_exception = False
|
|
try:
|
|
_ = ia.imresize_many_images(images, sizes=sizes)
|
|
except Exception as exc:
|
|
assert ">= 0" in str(exc)
|
|
got_exception = True
|
|
assert got_exception
|
|
|
|
# test list input but all with same shape
|
|
images = [np.zeros((8, 8, 3), dtype=np.uint8) for _ in range(2)]
|
|
observed = ia.imresize_many_images(images, (4, 4))
|
|
assert isinstance(observed, list)
|
|
assert all([image.shape == (4, 4, 3) for image in observed])
|
|
assert all([image.dtype.type == np.uint8 for image in observed])
|
|
|
|
# test multiple shapes
|
|
images = [np.zeros((8, 8, 3), dtype=np.uint8), np.zeros((4, 4), dtype=np.uint8)]
|
|
observed = ia.imresize_many_images(images, (4, 4))
|
|
assert observed[0].shape == (4, 4, 3)
|
|
assert observed[1].shape == (4, 4)
|
|
assert observed[0].dtype == np.uint8
|
|
assert observed[1].dtype == np.uint8
|
|
|
|
###################
|
|
# test other dtypes
|
|
###################
|
|
# interpolation="nearest"
|
|
image = np.zeros((4, 4), dtype=bool)
|
|
image[1, :] = True
|
|
image[2, :] = True
|
|
expected = np.zeros((3, 3), dtype=bool)
|
|
expected[1, :] = True
|
|
expected[2, :] = True
|
|
image_rs = ia.imresize_many_images([image], (3, 3), interpolation="nearest")[0]
|
|
assert image_rs.dtype.type == image.dtype.type
|
|
assert np.all(image_rs == expected)
|
|
|
|
for dtype in [np.uint8, np.uint16, np.int8, np.int16, np.int32]:
|
|
min_value, center_value, max_value = iadt.get_value_range_of_dtype(dtype)
|
|
for value in [min_value, max_value]:
|
|
image = np.zeros((4, 4), dtype=dtype)
|
|
image[1, :] = value
|
|
image[2, :] = value
|
|
expected = np.zeros((3, 3), dtype=dtype)
|
|
expected[1, :] = value
|
|
expected[2, :] = value
|
|
image_rs = ia.imresize_many_images([image], (3, 3), interpolation="nearest")[0]
|
|
assert image_rs.dtype.type == dtype
|
|
assert np.all(image_rs == expected)
|
|
|
|
for dtype in [np.float16, np.float32, np.float64]:
|
|
isize = np.dtype(dtype).itemsize
|
|
for value in [0.5, -0.5, 1.0, -1.0, 10.0, -10.0, -1000 ** (isize-1), 1000 * (isize+1)]:
|
|
image = np.zeros((4, 4), dtype=dtype)
|
|
image[1, :] = value
|
|
image[2, :] = value
|
|
expected = np.zeros((3, 3), dtype=dtype)
|
|
expected[1, :] = value
|
|
expected[2, :] = value
|
|
image_rs = ia.imresize_many_images([image], (3, 3), interpolation="nearest")[0]
|
|
assert image_rs.dtype.type == dtype
|
|
assert np.allclose(image_rs, expected, rtol=0, atol=1e-8)
|
|
|
|
# other interpolations
|
|
for ip in ["linear", "cubic", "area"]:
|
|
mask = np.zeros((4, 4), dtype=np.uint8)
|
|
mask[1, :] = 255
|
|
mask[2, :] = 255
|
|
mask = ia.imresize_many_images([mask], (3, 3), interpolation=ip)[0]
|
|
mask = mask.astype(np.float64) / 255.0
|
|
|
|
image = np.zeros((4, 4), dtype=bool)
|
|
image[1, :] = True
|
|
image[2, :] = True
|
|
expected = mask > 0.5
|
|
image_rs = ia.imresize_many_images([image], (3, 3), interpolation=ip)[0]
|
|
assert image_rs.dtype.type == image.dtype.type
|
|
assert np.all(image_rs == expected)
|
|
|
|
for dtype in [np.uint8, np.uint16, np.int8, np.int16]:
|
|
min_value, center_value, max_value = iadt.get_value_range_of_dtype(dtype)
|
|
dynamic_range = max_value - min_value
|
|
for value in [min_value+1, max_value-1]:
|
|
image = np.zeros((4, 4), dtype=dtype)
|
|
image[1, :] = value
|
|
image[2, :] = value
|
|
expected = np.round(mask * value).astype(dtype)
|
|
image_rs = ia.imresize_many_images([image], (3, 3), interpolation=ip)[0]
|
|
assert image_rs.dtype.type == dtype
|
|
diff = np.abs(image_rs.astype(np.int64) - expected.astype(np.int64))
|
|
assert np.all(diff < 2 * (1/255) * dynamic_range)
|
|
|
|
mask = np.zeros((4, 4), dtype=np.float64)
|
|
mask[1, :] = 1.0
|
|
mask[2, :] = 1.0
|
|
mask = ia.imresize_many_images([mask], (3, 3), interpolation=ip)[0]
|
|
mask = mask.astype(np.float64)
|
|
|
|
for dtype in [np.float16, np.float32, np.float64]:
|
|
isize = np.dtype(dtype).itemsize
|
|
|
|
for value in [0.5, -0.5, 1.0, -1.0, 10.0, -10.0, -1000 ** (isize-1), 1000 * (isize+1)]:
|
|
image = np.zeros((4, 4), dtype=dtype)
|
|
image[1, :] = value
|
|
image[2, :] = value
|
|
expected = (mask * np.float64(value)).astype(dtype)
|
|
image_rs = ia.imresize_many_images([image], (3, 3), interpolation=ip)[0]
|
|
assert image_rs.dtype.type == dtype
|
|
# Our basis for the expected image is derived from uint8 as that is most likely to work, so we will
|
|
# have to accept here deviations of around 1/255.
|
|
atol = np.float64(1 / 255) * np.abs(np.float64(value)) + 1e-8
|
|
assert np.allclose(image_rs, expected, rtol=0, atol=atol)
|
|
# Expect at least one cell to have a difference between observed and expected image of approx. 0,
|
|
# currently we seem to be able to get away with this despite the above mentioned inaccuracy.
|
|
assert np.any(np.isclose(image_rs, expected, rtol=0, atol=1e-4))
|
|
|
|
|
|
def test_imresize_single_image():
|
|
for c in [-1, 1, 3]:
|
|
image1 = np.zeros((16, 16, abs(c)), dtype=np.uint8) + 255
|
|
image2 = np.zeros((16, 16, abs(c)), dtype=np.uint8)
|
|
image3 = np.pad(
|
|
np.zeros((8, 8, abs(c)), dtype=np.uint8) + 255,
|
|
((4, 4), (4, 4), (0, 0)),
|
|
mode="constant",
|
|
constant_values=0
|
|
)
|
|
|
|
image1_small = np.zeros((8, 8, abs(c)), dtype=np.uint8) + 255
|
|
image2_small = np.zeros((8, 8, abs(c)), dtype=np.uint8)
|
|
image3_small = np.pad(
|
|
np.zeros((4, 4, abs(c)), dtype=np.uint8) + 255,
|
|
((2, 2), (2, 2), (0, 0)),
|
|
mode="constant",
|
|
constant_values=0
|
|
)
|
|
|
|
image1_large = np.zeros((32, 32, abs(c)), dtype=np.uint8) + 255
|
|
image2_large = np.zeros((32, 32, abs(c)), dtype=np.uint8)
|
|
image3_large = np.pad(
|
|
np.zeros((16, 16, abs(c)), dtype=np.uint8) + 255,
|
|
((8, 8), (8, 8), (0, 0)),
|
|
mode="constant",
|
|
constant_values=0
|
|
)
|
|
|
|
images = np.uint8([image1, image2, image3])
|
|
images_small = np.uint8([image1_small, image2_small, image3_small])
|
|
images_large = np.uint8([image1_large, image2_large, image3_large])
|
|
|
|
if c == -1:
|
|
images = images[:, :, 0]
|
|
images_small = images_small[:, :, 0]
|
|
images_large = images_large[:, :, 0]
|
|
|
|
interpolations = [None,
|
|
"nearest", "linear", "area", "cubic",
|
|
cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_AREA, cv2.INTER_CUBIC]
|
|
|
|
for interpolation in interpolations:
|
|
for image in images:
|
|
image_observed = ia.imresize_single_image(image, (16, 16), interpolation=interpolation)
|
|
diff = np.abs(image.astype(np.int32) - image_observed.astype(np.int32))
|
|
assert np.sum(diff) == 0
|
|
|
|
for interpolation in interpolations:
|
|
for image, image_expected in zip(images, images_small):
|
|
image_observed = ia.imresize_single_image(image, (8, 8), interpolation=interpolation)
|
|
diff = np.abs(image_expected.astype(np.int32) - image_observed.astype(np.int32))
|
|
diff_fraction = np.sum(diff) / (image_observed.size * 255)
|
|
assert diff_fraction < 0.5
|
|
|
|
for interpolation in interpolations:
|
|
for image, image_expected in zip(images, images_large):
|
|
image_observed = ia.imresize_single_image(image, (32, 32), interpolation=interpolation)
|
|
diff = np.abs(image_expected.astype(np.int32) - image_observed.astype(np.int32))
|
|
diff_fraction = np.sum(diff) / (image_observed.size * 255)
|
|
assert diff_fraction < 0.5
|
|
|
|
|
|
def test_pool():
|
|
# -----
|
|
# uint, int
|
|
# -----
|
|
for dtype in [np.uint8, np.uint16, np.uint32, np.int8, np.int16, np.int32]:
|
|
min_value, center_value, max_value = iadt.get_value_range_of_dtype(dtype)
|
|
|
|
for func in [np.min, np.average, np.max]:
|
|
arr = np.array([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
], dtype=dtype)
|
|
arr_pooled = ia.pool(arr, 2, func)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == np.dtype(dtype)
|
|
assert arr_pooled[0, 0] == int(func([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(func([2, 3, 6, 7]))
|
|
assert arr_pooled[1, 0] == int(func([8, 9, 12, 13]))
|
|
assert arr_pooled[1, 1] == int(func([10, 11, 14, 15]))
|
|
|
|
arr = np.array([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
], dtype=dtype)
|
|
arr = np.tile(arr[:, :, np.newaxis], (1, 1, 3))
|
|
arr[..., 1] += 1
|
|
arr[..., 2] += 2
|
|
arr_pooled = ia.pool(arr, 2, func)
|
|
assert arr_pooled.shape == (2, 2, 3)
|
|
assert arr_pooled.dtype == np.dtype(dtype)
|
|
for c in sm.xrange(3):
|
|
assert arr_pooled[0, 0, c] == int(func([0, 1, 4, 5])) + c
|
|
assert arr_pooled[0, 1, c] == int(func([2, 3, 6, 7])) + c
|
|
assert arr_pooled[1, 0, c] == int(func([8, 9, 12, 13])) + c
|
|
assert arr_pooled[1, 1, c] == int(func([10, 11, 14, 15])) + c
|
|
|
|
for value in [min_value, min_value+50, min_value+100, 0, 10, max_value,
|
|
int(center_value + 0.10*max_value),
|
|
int(center_value + 0.20*max_value),
|
|
int(center_value + 0.25*max_value),
|
|
int(center_value + 0.33*max_value)]:
|
|
arr = np.full((4, 4), value, dtype=dtype)
|
|
arr_pooled = ia.pool(arr, 2, func)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == np.dtype(dtype)
|
|
assert np.all(arr_pooled == value)
|
|
|
|
arr = np.full((4, 4, 3), value, dtype=dtype)
|
|
arr_pooled = ia.pool(arr, 2, func)
|
|
assert arr_pooled.shape == (2, 2, 3)
|
|
assert arr_pooled.dtype == np.dtype(dtype)
|
|
assert np.all(arr_pooled == value)
|
|
|
|
# -----
|
|
# float
|
|
# -----
|
|
try:
|
|
high_res_dt = np.float128
|
|
dtypes = ["float16", "float32", "float64", "float128"]
|
|
except AttributeError:
|
|
high_res_dt = np.float64
|
|
dtypes = ["float16", "float32", "float64"]
|
|
|
|
for dtype in dtypes:
|
|
dtype = np.dtype(dtype)
|
|
|
|
def _allclose(a, b):
|
|
atol = 1e-4 if dtype == np.float16 else 1e-8
|
|
return np.allclose(a, b, atol=atol, rtol=0)
|
|
|
|
for func in [np.min, np.average, np.max]:
|
|
arr = np.array([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
], dtype=dtype)
|
|
arr_pooled = ia.pool(arr, 2, func)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == np.dtype(dtype)
|
|
assert arr_pooled[0, 0] == func([0, 1, 4, 5])
|
|
assert arr_pooled[0, 1] == func([2, 3, 6, 7])
|
|
assert arr_pooled[1, 0] == func([8, 9, 12, 13])
|
|
assert arr_pooled[1, 1] == func([10, 11, 14, 15])
|
|
|
|
arr = np.array([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
], dtype=dtype)
|
|
arr = np.tile(arr[:, :, np.newaxis], (1, 1, 3))
|
|
arr[..., 1] += 1
|
|
arr[..., 2] += 2
|
|
arr_pooled = ia.pool(arr, 2, func)
|
|
assert arr_pooled.shape == (2, 2, 3)
|
|
assert arr_pooled.dtype == np.dtype(dtype)
|
|
for c in sm.xrange(3):
|
|
assert arr_pooled[0, 0, c] == func([0, 1, 4, 5]) + c
|
|
assert arr_pooled[0, 1, c] == func([2, 3, 6, 7]) + c
|
|
assert arr_pooled[1, 0, c] == func([8, 9, 12, 13]) + c
|
|
assert arr_pooled[1, 1, c] == func([10, 11, 14, 15]) + c
|
|
|
|
isize = np.dtype(dtype).itemsize
|
|
for value in [(-1) * (1000 ** (isize-1)), -50.0, 0.0, 50.0, 1000 ** (isize-1)]:
|
|
arr = np.full((4, 4), value, dtype=dtype)
|
|
arr_pooled = ia.pool(arr, 2, func)
|
|
dt = np.result_type(arr_pooled, 1.)
|
|
y = np.array(arr_pooled, dtype=dt, copy=False, subok=True)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == np.dtype(dtype)
|
|
assert _allclose(arr_pooled, high_res_dt(value))
|
|
|
|
arr = np.full((4, 4, 3), value, dtype=dtype)
|
|
arr_pooled = ia.pool(arr, 2, func)
|
|
assert arr_pooled.shape == (2, 2, 3)
|
|
assert arr_pooled.dtype == np.dtype(dtype)
|
|
assert _allclose(arr_pooled, high_res_dt(value))
|
|
|
|
# ----
|
|
# bool
|
|
# ----
|
|
arr = np.zeros((4, 4), dtype=bool)
|
|
arr[0, 0] = True
|
|
arr[0, 1] = True
|
|
arr[1, 0] = True
|
|
arr_pooled = ia.pool(arr, 2, np.min)
|
|
assert arr_pooled.dtype == arr.dtype
|
|
assert np.all(arr_pooled == 0)
|
|
|
|
arr_pooled = ia.pool(arr, 2, np.average)
|
|
assert arr_pooled.dtype == arr.dtype
|
|
assert np.all(arr_pooled[0, 0] == 1)
|
|
assert np.all(arr_pooled[:, 1] == 0)
|
|
assert np.all(arr_pooled[1, :] == 0)
|
|
|
|
arr_pooled = ia.pool(arr, 2, np.max)
|
|
assert arr_pooled.dtype == arr.dtype
|
|
assert np.all(arr_pooled[0, 0] == 1)
|
|
assert np.all(arr_pooled[:, 1] == 0)
|
|
assert np.all(arr_pooled[1, :] == 0)
|
|
|
|
# preserve_dtype off
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
arr_pooled = ia.pool(arr, 2, np.average, preserve_dtype=False)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == np.float64
|
|
assert np.allclose(arr_pooled[0, 0], np.average([0, 1, 4, 5]))
|
|
assert np.allclose(arr_pooled[0, 1], np.average([2, 3, 6, 7]))
|
|
assert np.allclose(arr_pooled[1, 0], np.average([8, 9, 12, 13]))
|
|
assert np.allclose(arr_pooled[1, 1], np.average([10, 11, 14, 15]))
|
|
|
|
# maximum function
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
arr_pooled = ia.pool(arr, 2, np.max)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.max([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.max([2, 3, 6, 7]))
|
|
assert arr_pooled[1, 0] == int(np.max([8, 9, 12, 13]))
|
|
assert arr_pooled[1, 1] == int(np.max([10, 11, 14, 15]))
|
|
|
|
# 3d array
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
arr = np.tile(arr[..., np.newaxis], (1, 1, 3))
|
|
arr_pooled = ia.pool(arr, 2, np.average)
|
|
assert arr_pooled.shape == (2, 2, 3)
|
|
assert np.array_equal(arr_pooled[..., 0], arr_pooled[..., 1])
|
|
assert np.array_equal(arr_pooled[..., 1], arr_pooled[..., 2])
|
|
arr_pooled = arr_pooled[..., 0]
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.average([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.average([2, 3, 6, 7]))
|
|
assert arr_pooled[1, 0] == int(np.average([8, 9, 12, 13]))
|
|
assert arr_pooled[1, 1] == int(np.average([10, 11, 14, 15]))
|
|
|
|
# block_size per axis
|
|
arr = np.float32([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
arr_pooled = ia.pool(arr, (2, 1), np.average)
|
|
assert arr_pooled.shape == (2, 4)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert np.allclose(arr_pooled[0, 0], np.average([0, 4]))
|
|
assert np.allclose(arr_pooled[0, 1], np.average([1, 5]))
|
|
assert np.allclose(arr_pooled[0, 2], np.average([2, 6]))
|
|
assert np.allclose(arr_pooled[0, 3], np.average([3, 7]))
|
|
assert np.allclose(arr_pooled[1, 0], np.average([8, 12]))
|
|
assert np.allclose(arr_pooled[1, 1], np.average([9, 13]))
|
|
assert np.allclose(arr_pooled[1, 2], np.average([10, 14]))
|
|
assert np.allclose(arr_pooled[1, 3], np.average([11, 15]))
|
|
|
|
# cval
|
|
arr = np.uint8([
|
|
[0, 1, 2],
|
|
[4, 5, 6],
|
|
[8, 9, 10]
|
|
])
|
|
arr_pooled = ia.pool(arr, 2, np.average)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.average([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.average([2, 0, 6, 0]))
|
|
assert arr_pooled[1, 0] == int(np.average([8, 9, 0, 0]))
|
|
assert arr_pooled[1, 1] == int(np.average([10, 0, 0, 0]))
|
|
|
|
arr = np.uint8([
|
|
[0, 1],
|
|
[4, 5]
|
|
])
|
|
arr_pooled = ia.pool(arr, (4, 1), np.average)
|
|
assert arr_pooled.shape == (1, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.average([0, 4, 0, 0]))
|
|
assert arr_pooled[0, 1] == int(np.average([1, 5, 0, 0]))
|
|
|
|
arr = np.uint8([
|
|
[0, 1, 2],
|
|
[4, 5, 6],
|
|
[8, 9, 10]
|
|
])
|
|
arr_pooled = ia.pool(arr, 2, np.average, pad_cval=22)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.average([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.average([2, 22, 6, 22]))
|
|
assert arr_pooled[1, 0] == int(np.average([8, 9, 22, 22]))
|
|
assert arr_pooled[1, 1] == int(np.average([10, 22, 22, 22]))
|
|
|
|
# padding mode
|
|
arr = np.uint8([
|
|
[0, 1, 2],
|
|
[4, 5, 6],
|
|
[8, 9, 10]
|
|
])
|
|
arr_pooled = ia.pool(arr, 2, np.average, pad_mode="edge")
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.average([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.average([2, 2, 6, 6]))
|
|
assert arr_pooled[1, 0] == int(np.average([8, 9, 8, 9]))
|
|
assert arr_pooled[1, 1] == int(np.average([10, 10, 10, 10]))
|
|
|
|
# same as above, but with float32 to make averages more accurate
|
|
arr = np.float32([
|
|
[0, 1, 2],
|
|
[4, 5, 6],
|
|
[8, 9, 10]
|
|
])
|
|
arr_pooled = ia.pool(arr, 2, np.average, pad_mode="edge")
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert np.isclose(arr_pooled[0, 0], np.average([0, 1, 4, 5]))
|
|
assert np.isclose(arr_pooled[0, 1], np.average([2, 2, 6, 6]))
|
|
assert np.isclose(arr_pooled[1, 0], np.average([8, 9, 8, 9]))
|
|
assert np.isclose(arr_pooled[1, 1], np.average([10, 10, 10, 10]))
|
|
|
|
|
|
# TODO add test that verifies the default padding mode
|
|
def test_avg_pool():
|
|
# very basic test, as avg_pool() just calls pool(), which is tested in test_pool()
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
arr_pooled = ia.avg_pool(arr, 2)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
# add 1e-4 here to force 0.5 to be rounded up, as that's how OpenCV
|
|
# handles it
|
|
assert arr_pooled[0, 0] == int(np.round(1e-4 + np.average([0, 1, 4, 5])))
|
|
assert arr_pooled[0, 1] == int(np.round(1e-4 + np.average([2, 3, 6, 7])))
|
|
assert arr_pooled[1, 0] == int(np.round(1e-4 + np.average([8, 9, 12, 13])))
|
|
assert arr_pooled[1, 1] == int(np.round(1e-4 + np.average([10, 11, 14, 15])))
|
|
|
|
|
|
# TODO add test that verifies the default padding mode
|
|
def test_max_pool():
|
|
# very basic test, as max_pool() just calls pool(), which is tested in
|
|
# test_pool()
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
arr_pooled = ia.max_pool(arr, 2)
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.max([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.max([2, 3, 6, 7]))
|
|
assert arr_pooled[1, 0] == int(np.max([8, 9, 12, 13]))
|
|
assert arr_pooled[1, 1] == int(np.max([10, 11, 14, 15]))
|
|
|
|
|
|
# TODO add test that verifies the default padding mode
|
|
def test_min_pool():
|
|
# very basic test, as min_pool() just calls pool(), which is tested in
|
|
# test_pool()
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
|
|
arr_pooled = ia.min_pool(arr, 2)
|
|
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.min([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.min([2, 3, 6, 7]))
|
|
assert arr_pooled[1, 0] == int(np.min([8, 9, 12, 13]))
|
|
assert arr_pooled[1, 1] == int(np.min([10, 11, 14, 15]))
|
|
|
|
|
|
# TODO add test that verifies the default padding mode
|
|
def test_median_pool():
|
|
# very basic test, as median_pool() just calls pool(), which is tested in
|
|
# test_pool()
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
|
|
arr_pooled = ia.median_pool(arr, 2)
|
|
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.median([0, 1, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.median([2, 3, 6, 7]))
|
|
assert arr_pooled[1, 0] == int(np.median([8, 9, 12, 13]))
|
|
assert arr_pooled[1, 1] == int(np.median([10, 11, 14, 15]))
|
|
|
|
|
|
# TODO add test that verifies the default padding mode
|
|
def test_median_pool_ksize_1_3():
|
|
# very basic test, as median_pool() just calls pool(), which is tested in
|
|
# test_pool()
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
|
|
arr_pooled = ia.median_pool(arr, (1, 3))
|
|
|
|
assert arr_pooled.shape == (4, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.median([0, 1, 2]))
|
|
assert arr_pooled[0, 1] == int(np.median([3, 2, 1]))
|
|
assert arr_pooled[1, 0] == int(np.median([4, 5, 6]))
|
|
assert arr_pooled[1, 1] == int(np.median([7, 6, 5]))
|
|
assert arr_pooled[2, 0] == int(np.median([8, 9, 10]))
|
|
assert arr_pooled[2, 1] == int(np.median([11, 10, 9]))
|
|
assert arr_pooled[3, 0] == int(np.median([12, 13, 14]))
|
|
assert arr_pooled[3, 1] == int(np.median([15, 14, 13]))
|
|
|
|
|
|
def test_median_pool_ksize_3():
|
|
# After padding:
|
|
# [5, 4, 5, 6, 7, 6],
|
|
# [1, 0, 1, 2, 3, 2],
|
|
# [5, 4, 5, 6, 7, 6],
|
|
# [9, 8, 9, 10, 11, 10],
|
|
# [13, 12, 13, 14, 15, 14],
|
|
# [9, 8, 9, 10, 11, 10]
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
])
|
|
|
|
arr_pooled = ia.median_pool(arr, 3)
|
|
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.median([5, 4, 5, 1, 0, 1, 5, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.median([6, 7, 6, 2, 3, 2, 6, 7, 6]))
|
|
assert arr_pooled[1, 0] == int(np.median([9, 8, 9, 13, 12, 13, 9, 8, 9]))
|
|
assert arr_pooled[1, 1] == int(np.median([10, 11, 10, 14, 15, 13, 10, 11,
|
|
10]))
|
|
|
|
|
|
def test_median_pool_ksize_3_view():
|
|
# After padding:
|
|
# [5, 4, 5, 6, 7, 6],
|
|
# [1, 0, 1, 2, 3, 2],
|
|
# [5, 4, 5, 6, 7, 6],
|
|
# [9, 8, 9, 10, 11, 10],
|
|
# [13, 12, 13, 14, 15, 14],
|
|
# [9, 8, 9, 10, 11, 10]
|
|
arr = np.uint8([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15],
|
|
[0, 0, 0, 0]
|
|
])
|
|
|
|
arr_in = arr[0:4, :]
|
|
assert arr_in.flags["OWNDATA"] is False
|
|
assert arr_in.flags["C_CONTIGUOUS"] is True
|
|
arr_pooled = ia.median_pool(arr_in, 3)
|
|
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.median([5, 4, 5, 1, 0, 1, 5, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.median([6, 7, 6, 2, 3, 2, 6, 7, 6]))
|
|
assert arr_pooled[1, 0] == int(np.median([9, 8, 9, 13, 12, 13, 9, 8, 9]))
|
|
assert arr_pooled[1, 1] == int(np.median([10, 11, 10, 14, 15, 13, 10, 11,
|
|
10]))
|
|
|
|
|
|
def test_median_pool_ksize_3_non_contiguous():
|
|
# After padding:
|
|
# [5, 4, 5, 6, 7, 6],
|
|
# [1, 0, 1, 2, 3, 2],
|
|
# [5, 4, 5, 6, 7, 6],
|
|
# [9, 8, 9, 10, 11, 10],
|
|
# [13, 12, 13, 14, 15, 14],
|
|
# [9, 8, 9, 10, 11, 10]
|
|
arr = np.array([
|
|
[0, 1, 2, 3],
|
|
[4, 5, 6, 7],
|
|
[8, 9, 10, 11],
|
|
[12, 13, 14, 15]
|
|
], dtype=np.uint8, order="F")
|
|
|
|
assert arr.flags["OWNDATA"] is True
|
|
assert arr.flags["C_CONTIGUOUS"] is False
|
|
arr_pooled = ia.median_pool(arr, 3)
|
|
|
|
assert arr_pooled.shape == (2, 2)
|
|
assert arr_pooled.dtype == arr.dtype.type
|
|
assert arr_pooled[0, 0] == int(np.median([5, 4, 5, 1, 0, 1, 5, 4, 5]))
|
|
assert arr_pooled[0, 1] == int(np.median([6, 7, 6, 2, 3, 2, 6, 7, 6]))
|
|
assert arr_pooled[1, 0] == int(np.median([9, 8, 9, 13, 12, 13, 9, 8, 9]))
|
|
assert arr_pooled[1, 1] == int(np.median([10, 11, 10, 14, 15, 13, 10, 11,
|
|
10]))
|
|
|
|
|
|
def test_draw_grid():
|
|
# bool
|
|
dtype = bool
|
|
image = np.zeros((2, 2, 3), dtype=dtype)
|
|
|
|
image[0, 0] = False
|
|
image[0, 1] = True
|
|
image[1, 0] = True
|
|
image[1, 1] = False
|
|
|
|
grid = ia.draw_grid([image], rows=1, cols=1)
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, image)
|
|
|
|
grid = ia.draw_grid(np.array([image], dtype=dtype), rows=1, cols=1)
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, image)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=2, cols=2)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image], rows=1, cols=2)
|
|
expected = np.hstack([image, image])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=2, cols=None)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=None, cols=2)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=None, cols=None)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
# int, uint
|
|
for dtype in [np.uint8, np.uint16, np.uint32, np.uint64, np.int8, np.int16, np.int32, np.int64]:
|
|
min_value, center_value, max_value = iadt.get_value_range_of_dtype(dtype)
|
|
|
|
image = np.zeros((2, 2, 3), dtype=dtype)
|
|
|
|
image[0, 0] = min_value
|
|
image[0, 1] = center_value
|
|
image[1, 0] = center_value + int(0.3 * max_value)
|
|
image[1, 1] = max_value
|
|
|
|
grid = ia.draw_grid([image], rows=1, cols=1)
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, image)
|
|
|
|
grid = ia.draw_grid(np.array([image], dtype=dtype), rows=1, cols=1)
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, image)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=2, cols=2)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert np.array_equal(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image], rows=1, cols=2)
|
|
expected = np.hstack([image, image])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=2, cols=None)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=None, cols=2)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=None, cols=None)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert np.array_equal(grid, expected)
|
|
|
|
# float
|
|
try:
|
|
_high_res_dt = np.float128
|
|
dtypes = ["float16", "float32", "float64", "float128"]
|
|
except AttributeError:
|
|
_high_res_dt = np.float64
|
|
dtypes = ["float16", "float32", "float64"]
|
|
|
|
for dtype in dtypes:
|
|
dtype = np.dtype(dtype)
|
|
|
|
def _allclose(a, b):
|
|
atol = 1e-4 if dtype == np.float16 else 1e-8
|
|
return np.allclose(a, b, atol=atol, rtol=0)
|
|
|
|
image = np.zeros((2, 2, 3), dtype=dtype)
|
|
|
|
isize = np.dtype(dtype).itemsize
|
|
image[0, 0] = (-1) * (1000 ** (isize-1))
|
|
image[0, 1] = -10.0
|
|
image[1, 0] = 10.0
|
|
image[1, 1] = 1000 ** (isize-1)
|
|
|
|
grid = ia.draw_grid([image], rows=1, cols=1)
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert _allclose(grid, image)
|
|
|
|
grid = ia.draw_grid(np.array([image], dtype=dtype), rows=1, cols=1)
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert _allclose(grid, image)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=2, cols=2)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert _allclose(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image], rows=1, cols=2)
|
|
expected = np.hstack([image, image])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert _allclose(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=2, cols=None)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert _allclose(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=None, cols=2)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert _allclose(grid, expected)
|
|
|
|
grid = ia.draw_grid([image, image, image, image], rows=None, cols=None)
|
|
expected = np.vstack([
|
|
np.hstack([image, image]),
|
|
np.hstack([image, image])
|
|
])
|
|
assert grid.dtype == np.dtype(dtype)
|
|
assert _allclose(grid, expected)
|
|
|
|
|
|
def test_classes_and_functions_marked_deprecated():
|
|
import imgaug.imgaug as iia
|
|
|
|
# class
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
_kp = iia.Keypoint(x=1, y=2)
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
# function
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
_result = iia.compute_geometric_median(np.float32([[0, 0]]))
|
|
assert len(caught_warnings) == 1
|
|
assert "is deprecated" in str(caught_warnings[-1].message)
|
|
|
|
# no deprecated warning for calls to imgaug.<name>
|
|
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
warnings.simplefilter("always")
|
|
_kp = ia.Keypoint(x=1, y=2)
|
|
assert len(caught_warnings) == 0
|
|
|
|
|
|
class Test_apply_lut(unittest.TestCase):
|
|
def test_2d_image(self):
|
|
table = np.mod(np.arange(256) + 10, 256).astype(np.uint8)
|
|
|
|
image = np.uint8([
|
|
[0, 50, 100, 245, 254, 255],
|
|
[1, 51, 101, 246, 255, 0]
|
|
])
|
|
|
|
image_aug = ia.apply_lut(image, table)
|
|
|
|
expected = np.uint8([
|
|
[10, 60, 110, 255, 8, 9],
|
|
[11, 61, 111, 0, 9, 10]
|
|
])
|
|
assert np.array_equal(image_aug, expected)
|
|
assert image_aug is not image
|
|
assert image_aug.shape == (2, 6)
|
|
assert image_aug.dtype.name == "uint8"
|
|
|
|
|
|
class Test_apply_lut_(unittest.TestCase):
|
|
def test_2d_image(self):
|
|
table = np.mod(np.arange(256) + 10, 256).astype(np.uint8)
|
|
tables = [
|
|
("array-1d", table),
|
|
("array-2d", table[:, np.newaxis]),
|
|
("array-3d", table[np.newaxis, :, np.newaxis]),
|
|
("list", [table])
|
|
]
|
|
|
|
for subtable_descr, subtable in tables:
|
|
with self.subTest(table_type=subtable_descr):
|
|
image = np.uint8([
|
|
[0, 50, 100, 245, 254, 255],
|
|
[1, 51, 101, 246, 255, 0]
|
|
])
|
|
|
|
image_aug = ia.apply_lut_(image, subtable)
|
|
|
|
expected = np.uint8([
|
|
[10, 60, 110, 255, 8, 9],
|
|
[11, 61, 111, 0, 9, 10]
|
|
])
|
|
assert np.array_equal(image_aug, expected)
|
|
assert image_aug is image
|
|
assert image_aug.shape == (2, 6)
|
|
assert image_aug.dtype.name == "uint8"
|
|
|
|
def test_HW1_image(self):
|
|
table = np.mod(np.arange(256) + 10, 256).astype(np.uint8)
|
|
tables = [
|
|
("array-1d", table),
|
|
("array-2d", table[:, np.newaxis]),
|
|
("array-3d", table[np.newaxis, :, np.newaxis]),
|
|
("list", [table])
|
|
]
|
|
|
|
for subtable_descr, subtable in tables:
|
|
with self.subTest(table_type=subtable_descr):
|
|
image = np.uint8([
|
|
[0, 50, 100, 245, 254, 255],
|
|
[1, 51, 101, 246, 255, 0]
|
|
])
|
|
image = image[:, :, np.newaxis]
|
|
|
|
image_aug = ia.apply_lut_(image, subtable)
|
|
|
|
expected = np.uint8([
|
|
[10, 60, 110, 255, 8, 9],
|
|
[11, 61, 111, 0, 9, 10]
|
|
])
|
|
expected = expected[:, :, np.newaxis]
|
|
assert np.array_equal(image_aug, expected)
|
|
# (H,W,1) images always lead to a copy
|
|
assert image_aug is not image
|
|
assert image_aug.shape == (2, 6, 1)
|
|
assert image_aug.dtype.name == "uint8"
|
|
|
|
def test_HWC_image(self):
|
|
# Base table, mapping all values to value+10.
|
|
# For channels C>0 we additionally add +C below.
|
|
table_base = np.mod(np.arange(256) + 10, 256).astype(np.int32)
|
|
nb_channels_lst = [2, 3, 4, 5, 511, 512, 513, 512*2-1, 512*2, 512*2+1]
|
|
|
|
for nb_channels in nb_channels_lst:
|
|
# Create channelwise LUT.
|
|
tables = []
|
|
for c in np.arange(nb_channels):
|
|
tables.append(np.mod(table_base + c, 256).astype(np.uint8))
|
|
|
|
tables_by_type = [
|
|
("array-1d", table_base.astype(np.uint8)),
|
|
("array-2d", np.stack(tables, axis=-1)),
|
|
("array-3d", np.stack(tables, axis=-1).reshape((1, 256, -1))),
|
|
("list", tables)
|
|
]
|
|
|
|
for subtable_descr, subtable in tables_by_type:
|
|
with self.subTest(nb_channels=nb_channels,
|
|
table_type=subtable_descr):
|
|
# Create a normalized lut table, so that we can easily
|
|
# find the projected value via x,y,c coordinates.
|
|
# In case of array-1d, all channels are treated the same
|
|
# way.
|
|
if subtable_descr == "array-1d":
|
|
tables_3d = np.stack([table_base] * nb_channels,
|
|
axis=-1)
|
|
else:
|
|
tables_3d = np.stack(tables, axis=-1).reshape(
|
|
(256, -1))
|
|
|
|
image = np.int32([
|
|
[0, 50, 100, 245, 254, 255],
|
|
[1, 51, 101, 246, 255, 0]
|
|
])
|
|
image = image[:, :, np.newaxis]
|
|
image = np.tile(image, (1, 1, nb_channels))
|
|
for c in np.arange(nb_channels):
|
|
image[:, :, c] += c
|
|
image = np.mod(image, 256).astype(np.uint8)
|
|
image_orig = np.copy(image)
|
|
|
|
image_aug = ia.apply_lut_(image, subtable)
|
|
|
|
# Reproduce effect of a LUT mapping on the input
|
|
# image.
|
|
expected = np.zeros_like(image_orig)
|
|
for c in np.arange(nb_channels):
|
|
for x in np.arange(image.shape[1]):
|
|
for y in np.arange(image.shape[0]):
|
|
v = image_orig[y, x, c]
|
|
v_proj = tables_3d[v, c]
|
|
expected[y, x, c] = v_proj
|
|
|
|
assert np.array_equal(image_aug, expected)
|
|
if nb_channels < 512:
|
|
assert image_aug is image
|
|
assert image_aug.shape == (2, 6, nb_channels)
|
|
assert image_aug.dtype.name == "uint8"
|
|
|
|
def test_image_is_noncontiguous(self):
|
|
table = np.mod(np.arange(256) + 10, 256).astype(np.uint8)
|
|
|
|
image = np.uint8([
|
|
[0, 50, 100, 245, 254, 255],
|
|
[1, 51, 101, 246, 255, 0]
|
|
])
|
|
image = np.fliplr(image)
|
|
assert image.flags["C_CONTIGUOUS"] is False
|
|
|
|
image_aug = ia.apply_lut_(image, table)
|
|
|
|
expected = np.uint8([
|
|
[10, 60, 110, 255, 8, 9],
|
|
[11, 61, 111, 0, 9, 10]
|
|
])
|
|
assert np.array_equal(np.fliplr(image_aug), expected)
|
|
assert image_aug is not image # non-contiguous should lead to copy
|
|
assert image_aug.shape == (2, 6)
|
|
assert image_aug.dtype.name == "uint8"
|
|
|
|
def test_image_is_view(self):
|
|
table = np.mod(np.arange(256) + 10, 256).astype(np.uint8)
|
|
|
|
image = np.uint8([
|
|
[0, 50, 100, 245, 254, 255],
|
|
[1, 51, 101, 246, 255, 0]
|
|
])
|
|
image = image[:, 1:4]
|
|
assert image.flags["OWNDATA"] is False
|
|
|
|
image_aug = ia.apply_lut_(image, table)
|
|
|
|
expected = np.uint8([
|
|
[60, 110, 255],
|
|
[61, 111, 0]
|
|
])
|
|
assert np.array_equal(image_aug, expected)
|
|
assert image_aug is not image # non-owndata should lead to copy
|
|
assert image_aug.shape == (2, 3)
|
|
assert image_aug.dtype.name == "uint8"
|
|
|
|
def test_zero_sized_axes(self):
|
|
table = np.mod(np.arange(256) + 10, 256).astype(np.uint8)
|
|
shapes = [
|
|
(0, 0),
|
|
(0, 1),
|
|
(1, 0),
|
|
(0, 1, 0),
|
|
(1, 0, 0),
|
|
(0, 1, 1),
|
|
(1, 0, 1)
|
|
]
|
|
|
|
for shape in shapes:
|
|
with self.subTest(shape=shape):
|
|
image = np.zeros(shape, dtype=np.uint8)
|
|
image_aug = ia.apply_lut_(image, table)
|
|
assert image_aug.shape == shape
|
|
assert image_aug.dtype.name == "uint8"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|