1from random import shuffle 2 3import pytest 4 5import numpy as np 6from numpy.testing import assert_allclose 7from numpy.testing import assert_array_equal 8 9from skimage.transform import integral_image 10from skimage.feature import haar_like_feature 11from skimage.feature import haar_like_feature_coord 12from skimage.feature import draw_haar_like_feature 13 14 15def test_haar_like_feature_error(): 16 img = np.ones((5, 5), dtype=np.float32) 17 img_ii = integral_image(img) 18 19 feature_type = 'unknown_type' 20 with pytest.raises(ValueError): 21 haar_like_feature(img_ii, 0, 0, 5, 5, feature_type=feature_type) 22 haar_like_feature_coord(5, 5, feature_type=feature_type) 23 draw_haar_like_feature(img, 0, 0, 5, 5, feature_type=feature_type) 24 25 feat_coord, feat_type = haar_like_feature_coord(5, 5, 'type-2-x') 26 with pytest.raises(ValueError): 27 haar_like_feature(img_ii, 0, 0, 5, 5, feature_type=feat_type[:3], 28 feature_coord=feat_coord) 29 30 31@pytest.mark.parametrize("dtype", [np.uint8, np.int8, 32 np.float32, np.float64]) 33@pytest.mark.parametrize("feature_type,shape_feature,expected_feature_value", 34 [('type-2-x', (84,), [0.]), 35 ('type-2-y', (84,), [0.]), 36 ('type-3-x', (42,), [-5, -4., -3., -2., -1.]), 37 ('type-3-y', (42,), [-5, -4., -3., -2., -1.]), 38 ('type-4', (36,), [0.])]) 39def test_haar_like_feature(feature_type, shape_feature, 40 expected_feature_value, dtype): 41 # test Haar-like feature on a basic one image 42 img = np.ones((5, 5), dtype=dtype) 43 img_ii = integral_image(img) 44 haar_feature = haar_like_feature(img_ii, 0, 0, 5, 5, 45 feature_type=feature_type) 46 assert_allclose(np.sort(np.unique(haar_feature)), expected_feature_value) 47 48 49@pytest.mark.parametrize("dtype", [np.uint8, np.int8, 50 np.float32, np.float64]) 51@pytest.mark.parametrize("feature_type", ['type-2-x', 'type-2-y', 52 'type-3-x', 'type-3-y', 53 'type-4']) 54def test_haar_like_feature_fused_type(dtype, feature_type): 55 # check that the input type is kept 56 img = np.ones((5, 5), dtype=dtype) 57 img_ii = integral_image(img) 58 expected_dtype = img_ii.dtype 59 # to avoid overflow, unsigned type are converted to signed 60 if 'uint' in expected_dtype.name: 61 expected_dtype = np.dtype(expected_dtype.name.replace('u', '')) 62 haar_feature = haar_like_feature(img_ii, 0, 0, 5, 5, 63 feature_type=feature_type) 64 assert haar_feature.dtype == expected_dtype 65 66 67def test_haar_like_feature_list(): 68 img = np.ones((5, 5), dtype=np.int8) 69 img_ii = integral_image(img) 70 feature_type = ['type-2-x', 'type-2-y', 'type-3-x', 'type-3-y', 'type-4'] 71 haar_list = haar_like_feature(img_ii, 0, 0, 5, 5, 72 feature_type=feature_type) 73 haar_all = haar_like_feature(img_ii, 0, 0, 5, 5) 74 assert_array_equal(haar_list, haar_all) 75 76 77@pytest.mark.parametrize("feature_type", ['type-2-x', 'type-2-y', 78 'type-3-x', 'type-3-y', 79 'type-4', 80 ['type-2-y', 'type-3-x', 81 'type-4']]) 82def test_haar_like_feature_precomputed(feature_type): 83 img = np.ones((5, 5), dtype=np.int8) 84 img_ii = integral_image(img) 85 if isinstance(feature_type, list): 86 # shuffle the index of the feature to be sure that we are output 87 # the features in the same order 88 shuffle(feature_type) 89 feat_coord, feat_type = zip(*[haar_like_feature_coord(5, 5, feat_t) 90 for feat_t in feature_type]) 91 feat_coord = np.concatenate(feat_coord) 92 feat_type = np.concatenate(feat_type) 93 else: 94 feat_coord, feat_type = haar_like_feature_coord(5, 5, feature_type) 95 haar_feature_precomputed = haar_like_feature(img_ii, 0, 0, 5, 5, 96 feature_type=feat_type, 97 feature_coord=feat_coord) 98 haar_feature = haar_like_feature(img_ii, 0, 0, 5, 5, feature_type) 99 assert_array_equal(haar_feature_precomputed, haar_feature) 100 101 102@pytest.mark.parametrize("feature_type,height,width,expected_coord", 103 [('type-2-x', 2, 2, 104 [[[(0, 0), (0, 0)], [(0, 1), (0, 1)]], 105 [[(0, 0), (1, 0)], [(0, 1), (1, 1)]], 106 [[(1, 0), (1, 0)], [(1, 1), (1, 1)]]]), 107 ('type-2-y', 2, 2, 108 [[[(0, 0), (0, 0)], [(1, 0), (1, 0)]], 109 [[(0, 0), (0, 1)], [(1, 0), (1, 1)]], 110 [[(0, 1), (0, 1)], [(1, 1), (1, 1)]]]), 111 ('type-3-x', 3, 3, 112 [[[(0, 0), (0, 0)], [(0, 1), (0, 1)], 113 [(0, 2), (0, 2)]], 114 [[(0, 0), (1, 0)], [(0, 1), (1, 1)], 115 [(0, 2), (1, 2)]], 116 [[(0, 0), (2, 0)], [(0, 1), (2, 1)], 117 [(0, 2), (2, 2)]], 118 [[(1, 0), (1, 0)], [(1, 1), (1, 1)], 119 [(1, 2), (1, 2)]], 120 [[(1, 0), (2, 0)], [(1, 1), (2, 1)], 121 [(1, 2), (2, 2)]], 122 [[(2, 0), (2, 0)], [(2, 1), (2, 1)], 123 [(2, 2), (2, 2)]]]), 124 ('type-3-y', 3, 3, 125 [[[(0, 0), (0, 0)], [(1, 0), (1, 0)], 126 [(2, 0), (2, 0)]], 127 [[(0, 0), (0, 1)], [(1, 0), (1, 1)], 128 [(2, 0), (2, 1)]], 129 [[(0, 0), (0, 2)], [(1, 0), (1, 2)], 130 [(2, 0), (2, 2)]], 131 [[(0, 1), (0, 1)], [(1, 1), (1, 1)], 132 [(2, 1), (2, 1)]], 133 [[(0, 1), (0, 2)], [(1, 1), (1, 2)], 134 [(2, 1), (2, 2)]], 135 [[(0, 2), (0, 2)], [(1, 2), (1, 2)], 136 [(2, 2), (2, 2)]]]), 137 ('type-4', 2, 2, 138 [[[(0, 0), (0, 0)], [(0, 1), (0, 1)], 139 [(1, 1), (1, 1)], [(1, 0), (1, 0)]]])]) 140def test_haar_like_feature_coord(feature_type, height, width, expected_coord): 141 feat_coord, feat_type = haar_like_feature_coord(width, height, 142 feature_type) 143 # convert the output to a full numpy array just for comparison 144 feat_coord = np.array([hf for hf in feat_coord]) 145 assert_array_equal(feat_coord, expected_coord) 146 assert np.all(feat_type == feature_type) 147 148 149@pytest.mark.parametrize("max_n_features,nnz_values", [(None, 46), 150 (1, 4)]) 151def test_draw_haar_like_feature(max_n_features, nnz_values): 152 img = np.zeros((5, 5), dtype=np.float32) 153 coord, _ = haar_like_feature_coord(5, 5, 'type-4') 154 image = draw_haar_like_feature(img, 0, 0, 5, 5, coord, 155 max_n_features=max_n_features, 156 random_state=0) 157 assert image.shape == (5, 5, 3) 158 assert np.count_nonzero(image) == nnz_values 159