mirror of
https://github.com/zhigang1992/fastai.git
synced 2026-03-28 07:58:46 +08:00
314 lines
11 KiB
Python
314 lines
11 KiB
Python
import numpy as np
|
|
import pytest
|
|
|
|
from fastai.transforms import *
|
|
|
|
t_rand_img128x128x1 = np.random.uniform(size=[128,128,1])
|
|
t_rand_img128x128x3 = np.random.uniform(size=[128,128,3])
|
|
#
|
|
# # as per https://stackoverflow.com/questions/7100242/python-numpy-first-occurrence-of-subarray
|
|
# def rolling_window(a, size):
|
|
# shape = a.shape[:-1] + (a.shape[-1] - size + 1, size)
|
|
# strides = a.strides + (a. strides[-1],)
|
|
# return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
|
|
|
|
|
|
def test_scale_min_works_with_masks():
|
|
mask = np.ones([128, 256], dtype=np.float32)
|
|
mask[0:64,0:128] = 20
|
|
|
|
em = np.array([[20., 20., 1., 1.],
|
|
[1., 1., 1., 1.]], dtype=np.float32)
|
|
msmall = scale_min(mask, 2, cv2.INTER_NEAREST)
|
|
np.testing.assert_equal(msmall, em, "sacle_min can scale down a mask")
|
|
|
|
mlarge = scale_min(msmall, 128, cv2.INTER_NEAREST)
|
|
np.testing.assert_equal(mlarge, mask, "sacle_min can scale up a mask")
|
|
|
|
def test_scale_min_works_with_rgb():
|
|
r_layer = np.ones([128, 256], dtype=np.float32)
|
|
r_layer[0:64, 0:128] = 0.5
|
|
im = np.stack([r_layer, np.zeros_like(r_layer), np.ones_like(r_layer)], axis=-1)
|
|
|
|
r_layer_small = np.array([[0.5, 0.5, 1., 1.],
|
|
[1., 1., 1., 1.]])
|
|
im_small = scale_min(im, 2, cv2.INTER_AREA)
|
|
np.testing.assert_equal(im_small[..., 0], r_layer_small, "sacle_min can scale down an rgb image")
|
|
assert im_small[..., 1].sum() == 0, "sacle_min can scale down an rgb image"
|
|
assert im_small[..., 2].max() == im_small[..., 2].min() == 1, "sacle_min can scale down an rgb image"
|
|
|
|
im_large = scale_min(im_small, 128, cv2.INTER_AREA)
|
|
np.testing.assert_equal(im_large[..., 0], r_layer, "sacle_min can scale up an rgb image")
|
|
assert im_large[..., 1].sum() == 0, "sacle_min can scale down an rgb image"
|
|
assert im_large[..., 2].max() == im_large[..., 2].min() == 1, "sacle_min can scale down an rgb image"
|
|
|
|
|
|
def test_zoom_cv():
|
|
r_layer = np.array([[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 1, 0, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0], ], dtype=np.float32)
|
|
im = np.stack([r_layer, np.zeros_like(r_layer), np.ones_like(r_layer)], axis=-1)
|
|
np.testing.assert_equal(zoom_cv(im, 0), im, "Z==0 leaves image unchanged")
|
|
# TODO: Figure out why the circle is moved slightly to the top left corner.
|
|
expect = np.array([[0, 0, 0, 0, 0.],
|
|
[0, 0.01562, 0.12109, 0.00391, 0.],
|
|
[0, 0.12109, 0.93848, 0.03027, 0.],
|
|
[0, 0.00391, 0.03027, 0.00098, 0.],
|
|
[0, 0, 0, 0, 0.],], dtype=np.float32)
|
|
actual = zoom_cv(im, 0.1)[..., 0]
|
|
print(actual)
|
|
np.testing.assert_array_almost_equal(actual, expect, decimal=5)
|
|
|
|
def test_stretch_cv():
|
|
im = np.array([[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 1, 0, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0], ], dtype=np.float32)
|
|
np.testing.assert_equal(stretch_cv(im, sr=0, sc=0), im, "sr==0 && sc==0 leaves image unchanged")
|
|
|
|
expect = np.array([[0, 0, 0, 0, 0.],
|
|
[0, 0., 0, 0, 0.],
|
|
[0, 0., 0.64, 0.24, 0.],
|
|
[0, 0., 0.24, 0.09, 0.],
|
|
[0, 0, 0, 0, 0.],], dtype=np.float32)
|
|
actual = stretch_cv(im, 0.1, 0.1)
|
|
print(actual)
|
|
np.testing.assert_array_almost_equal(actual, expect, decimal=5)
|
|
|
|
expect = np.array([[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 1, 1, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0], ], dtype=np.float32)
|
|
actual = stretch_cv(im, 1, 0)
|
|
print(actual)
|
|
np.testing.assert_array_almost_equal(actual, expect, decimal=5)
|
|
|
|
expect = np.array([[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 1, 1, 0],
|
|
[0, 0, 1, 1, 0],
|
|
[0, 0, 0, 0, 0], ], dtype=np.float32)
|
|
actual = stretch_cv(im, 1, 1)
|
|
print(actual)
|
|
np.testing.assert_array_almost_equal(actual, expect, decimal=5)
|
|
|
|
expect = np.array([[0, 0, 0, 0, 0],
|
|
[0, 1, 1, 1, 0],
|
|
[0, 1, 1, 1, 0],
|
|
[0, 1, 1, 1, 0],
|
|
[0, 0, 0, 0, 0], ], dtype=np.float32)
|
|
actual = stretch_cv(im, 2, 2)
|
|
print(actual)
|
|
np.testing.assert_array_almost_equal(actual, expect, decimal=5)
|
|
|
|
@pytest.mark.skip(reason="It does not work for some reason see #429")
|
|
def test_zoom_cv_equals_stretch_cv():
|
|
im = np.array([[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 1, 0, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0], ], dtype=np.float32)
|
|
|
|
np.testing.assert_array_almost_equal(zoom_cv(im, 2), stretch_cv(im, 2, 2), decimal=4)
|
|
|
|
def test_dihedral():
|
|
im = np.array([
|
|
[0., 0.1, 0., ],
|
|
[0.01, 0.2, 0.03,],
|
|
[0., 0.3, 0., ],])
|
|
e = im
|
|
a = dihedral(im, 0)
|
|
np.testing.assert_array_equal(a, e)
|
|
e = np.array([
|
|
[0., 0.03, 0., ],
|
|
[0.1, 0.2, 0.3, ],
|
|
[0., 0.01, 0., ]])
|
|
a = dihedral(im, 1)
|
|
np.testing.assert_array_equal(a, e)
|
|
e = np.array([
|
|
[0., 0.3, 0., ],
|
|
[0.03, 0.2, 0.01,],
|
|
[0., 0.1, 0., ]])
|
|
a = dihedral(im, 2)
|
|
np.testing.assert_array_equal(a, e)
|
|
e = np.array([
|
|
[0., 0.01, 0., ],
|
|
[0.3, 0.2, 0.1, ],
|
|
[0., 0.03, 0., ]])
|
|
a = dihedral(im, 3)
|
|
np.testing.assert_array_equal(a, e)
|
|
e = np.array([
|
|
[0., 0.1, 0., ],
|
|
[0.03, 0.2, 0.01,],
|
|
[0., 0.3, 0., ]])
|
|
a = dihedral(im, 4)
|
|
np.testing.assert_array_equal(a, e)
|
|
e = np.array([
|
|
[0., 0.03, 0., ],
|
|
[0.3, 0.2, 0.1, ],
|
|
[0., 0.01, 0., ]])
|
|
a = dihedral(im, 5)
|
|
np.testing.assert_array_equal(a, e)
|
|
e = np.array([
|
|
[0., 0.3, 0., ],
|
|
[0.01, 0.2, 0.03,],
|
|
[0., 0.1, 0., ]])
|
|
a = dihedral(im, 6)
|
|
np.testing.assert_array_equal(a, e)
|
|
e = np.array([
|
|
[0., 0.01, 0., ],
|
|
[0.1, 0.2, 0.3, ],
|
|
[0., 0.03, 0., ]])
|
|
a = dihedral(im, 7)
|
|
np.testing.assert_array_equal(a, e)
|
|
|
|
def test_lighting():
|
|
im = np.array([
|
|
[0., 0.1, 0., ],
|
|
[0.01, 0.2, 0.03,],
|
|
[0., 0.3, 0., ],])
|
|
e = im
|
|
a = lighting(im, 0, 1)
|
|
# TODO: better test taht allows for visual inspection
|
|
np.testing.assert_array_equal(a, e)
|
|
e =np.array([[0.5 , 0.6 , 0.5 ],
|
|
[0.51, 0.7 , 0.53],
|
|
[0.5 , 0.8 , 0.5 ]], dtype=np.float32)
|
|
a = lighting(im, 0.5, 1)
|
|
np.testing.assert_array_equal(a, e)
|
|
@pytest.mark.skip(reason="It does not work for some reason see #431")
|
|
def test_rotate_cv():
|
|
im = np.array([
|
|
[0., 0.1, 0., ],
|
|
[0., 0.2, 0., ],
|
|
[0., 0.3, 0., ],])
|
|
a = rotate_cv(im, 90)
|
|
# TODO: find out why this test breaks
|
|
e = np.array([[0. , 0. , 0. ],
|
|
[0.1, 0.2, 0.3],
|
|
[0. , 0. , 0. ],])
|
|
np.testing.assert_array_equal(a, e)
|
|
|
|
@pytest.mark.skip(reason="It does not work for some reason see #431")
|
|
def test_rotate_cv_vs_dihedral():
|
|
im = np.array([
|
|
[0., 0.1, 0., ],
|
|
[0., 0.2, 0., ],
|
|
[0., 0.3, 0., ],])
|
|
a = rotate_cv(im, 180)
|
|
e = dihedral(im, 6)
|
|
np.testing.assert_array_equal(a, e)
|
|
|
|
def test_no_crop():
|
|
im = np.array([
|
|
[0., 0.1, 0., ],
|
|
[0., 0.2, 0., ],])
|
|
a = no_crop(im, 4)
|
|
e = np.array([[0. , 0.066 , 0.066, 0 ],
|
|
[0, 0.066, 0.066, 0 ],
|
|
[0. , 0.133 , 0.133, 0 ],
|
|
[0. , 0.133 , 0.133, 0 ]])
|
|
np.testing.assert_array_almost_equal(a, e, decimal=3)
|
|
|
|
def test_center_crop():
|
|
im = np.array([
|
|
[0., 0.1, 0., ],
|
|
[0.01, 0.2, 0.03,],
|
|
[0., 0.3, 0., ],])
|
|
a = center_crop(im, 1)
|
|
e = np.array([[0.2]])
|
|
np.testing.assert_array_equal(a, e)
|
|
im = np.array([
|
|
[0., 0.1, 0., 0],
|
|
[0.01, 0.2, 0.9, 0.04],
|
|
[0., 0.3, 0., 0],])
|
|
a = center_crop(im, 1)
|
|
e = np.array([[0.9]])
|
|
np.testing.assert_array_equal(a, e)
|
|
|
|
def test_googlenet_resize():
|
|
# TODO: figure out how to test this in a way it make sense
|
|
pass
|
|
|
|
def test_cutout():
|
|
im = np.ones([128,128,3], np.float32)
|
|
with_holes = cutout(im, 1, 10)
|
|
assert (with_holes == 0).sum() == 300, "There is one cut out hole 10px x 10px in size (over 3 channels)"
|
|
|
|
def test_scale_to():
|
|
h=10
|
|
w=20
|
|
ratio = 127./h
|
|
assert scale_to(h, ratio, 127) == 127
|
|
assert scale_to(w, ratio, 127) == 254
|
|
|
|
def test_crop():
|
|
im = np.ones([128,128,3], np.float32)
|
|
assert crop(im, 1, 1, 10).shape == (10,10,3)
|
|
|
|
def test_to_bb():
|
|
im = np.array([[0, 0, 0, 0, 0],
|
|
[0, 1, 1, 1, 0],
|
|
[0, 1, 1, 1, 0],
|
|
[0, 1, 1, 1, 0],
|
|
[0, 0, 0, 0, 0], ], dtype=np.float32)
|
|
expect = [1,1,3,3]
|
|
np.testing.assert_array_equal(to_bb(im, "not used"), expect)
|
|
|
|
### tests for transformation objects
|
|
def test_RandomCrop():
|
|
tfm = RandomCrop(23)
|
|
x = t_rand_img128x128x1
|
|
x2, cls = tfm(x, None)
|
|
assert x2.shape == (23,23,1)
|
|
|
|
def test_AddPadding():
|
|
tfm = AddPadding(1)
|
|
x = t_rand_img128x128x3
|
|
x2, cls = tfm(x, None)
|
|
assert x2.shape == (130,130,3)
|
|
|
|
def test_CenterCrop():
|
|
tfm = CenterCrop(10)
|
|
x = t_rand_img128x128x3
|
|
x2, cls = tfm(x, None)
|
|
assert x2.shape == (10,10,3)
|
|
|
|
def test_NoCrop():
|
|
tfm = NoCrop(10)
|
|
x = t_rand_img128x128x3
|
|
x2, cls = tfm(x, None)
|
|
assert x2.shape == (10,10,3)
|
|
|
|
def test_applying_tranfrom_multiple_times_reset_the_state():
|
|
tfm = RandomScale(10, 1000, p=1)
|
|
x1,_ = tfm(t_rand_img128x128x3, None)
|
|
x2,_ = tfm(t_rand_img128x128x3, None)
|
|
x3,_ = tfm(t_rand_img128x128x3, None)
|
|
assert x1.shape[0] != x2.shape[0] or x1.shape[0] != x3.shape[0], "Each transfromation should give a bit different shape"
|
|
assert x1.shape[0] < 10000
|
|
assert x2.shape[0] < 10000
|
|
assert x3.shape[0] < 10000
|
|
|
|
stats = inception_stats
|
|
tfm_norm = Normalize(*stats, tfm_y=TfmType.COORD)
|
|
tfm_denorm = Denormalize(*stats)
|
|
buggy_offset = 2 # This is a bug in the current transform_coord, I will fix it in the next commit
|
|
|
|
def test_transforms_works_with_coords(): # test of backward compatible behavior
|
|
sz = 16
|
|
transforms = image_gen(tfm_norm, tfm_denorm, sz, tfms=None, max_zoom=None, pad=0, crop_type=CropType.NO,
|
|
tfm_y=TfmType.COORD, sz_y=sz, pad_mode=cv2.BORDER_REFLECT)
|
|
|
|
x, y = transforms(t_rand_img128x128x3, np.array([0,0,128,128, 0,0,64,64]))
|
|
bbs = partition(y, 4)
|
|
assert x.shape[0] == 3, "The image was converted from NHWC to NCHW (channle first pytorch format)"
|
|
|
|
h,w = x.shape[1:]
|
|
np.testing.assert_equal(bbs[0], [0, 0, h-buggy_offset, w-buggy_offset], "The outer bounding box was converted correctly")
|
|
np.testing.assert_equal(bbs[1], [0, 0, h/2-buggy_offset, w/2-buggy_offset], "The inner bounding box was converted correctly")
|