Files
2026-07-13 12:46:08 +08:00

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()