scikit-image

Форк
0
/
test_template.py 
189 строк · 6.0 Кб
1
import numpy as np
2
from skimage._shared.testing import assert_almost_equal, assert_equal
3

4
from skimage import data, img_as_float
5
from skimage.morphology import diamond
6
from skimage.feature import match_template, peak_local_max
7
from skimage._shared import testing
8

9

10
@testing.parametrize('dtype', [np.float32, np.float64])
11
def test_template(dtype):
12
    size = 100
13
    # Float prefactors ensure that image range is between 0 and 1
14
    image = np.full((400, 400), 0.5, dtype=dtype)
15
    target = 0.1 * (np.tri(size) + np.tri(size)[::-1])
16
    target = target.astype(dtype, copy=False)
17
    target_positions = [(50, 50), (200, 200)]
18
    for x, y in target_positions:
19
        image[x : x + size, y : y + size] = target
20
    np.random.seed(1)
21
    image += 0.1 * np.random.uniform(size=(400, 400)).astype(dtype, copy=False)
22

23
    result = match_template(image, target)
24
    assert result.dtype == dtype
25
    delta = 5
26

27
    positions = peak_local_max(result, min_distance=delta)
28

29
    if len(positions) > 2:
30
        # Keep the two maximum peaks.
31
        intensities = result[tuple(positions.T)]
32
        i_maxsort = np.argsort(intensities)[::-1]
33
        positions = positions[i_maxsort][:2]
34

35
    # Sort so that order matches `target_positions`.
36
    positions = positions[np.argsort(positions[:, 0])]
37

38
    for xy_target, xy in zip(target_positions, positions):
39
        assert_almost_equal(xy, xy_target)
40

41

42
def test_normalization():
43
    """Test that `match_template` gives the correct normalization.
44

45
    Normalization gives 1 for a perfect match and -1 for an inverted-match.
46
    This test adds positive and negative squares to a zero-array and matches
47
    the array with a positive template.
48
    """
49
    n = 5
50
    N = 20
51
    ipos, jpos = (2, 3)
52
    ineg, jneg = (12, 11)
53
    image = np.full((N, N), 0.5)
54
    image[ipos : ipos + n, jpos : jpos + n] = 1
55
    image[ineg : ineg + n, jneg : jneg + n] = 0
56

57
    # white square with a black border
58
    template = np.zeros((n + 2, n + 2))
59
    template[1 : 1 + n, 1 : 1 + n] = 1
60

61
    result = match_template(image, template)
62

63
    # get the max and min results.
64
    sorted_result = np.argsort(result.flat)
65
    iflat_min = sorted_result[0]
66
    iflat_max = sorted_result[-1]
67
    min_result = np.unravel_index(iflat_min, result.shape)
68
    max_result = np.unravel_index(iflat_max, result.shape)
69

70
    # shift result by 1 because of template border
71
    assert np.all((np.array(min_result) + 1) == (ineg, jneg))
72
    assert np.all((np.array(max_result) + 1) == (ipos, jpos))
73

74
    assert np.allclose(result.flat[iflat_min], -1)
75
    assert np.allclose(result.flat[iflat_max], 1)
76

77

78
def test_no_nans():
79
    """Test that `match_template` doesn't return NaN values.
80

81
    When image values are only slightly different, floating-point errors can
82
    cause a subtraction inside of a square root to go negative (without an
83
    explicit check that was added to `match_template`).
84
    """
85
    np.random.seed(1)
86
    image = 0.5 + 1e-9 * np.random.normal(size=(20, 20))
87
    template = np.ones((6, 6))
88
    template[:3, :] = 0
89
    result = match_template(image, template)
90
    assert not np.any(np.isnan(result))
91

92

93
def test_switched_arguments():
94
    image = np.ones((5, 5))
95
    template = np.ones((3, 3))
96
    with testing.raises(ValueError):
97
        match_template(template, image)
98

99

100
def test_pad_input():
101
    """Test `match_template` when `pad_input=True`.
102

103
    This test places two full templates (one with values lower than the image
104
    mean, the other higher) and two half templates, which are on the edges of
105
    the image. The two full templates should score the top (positive and
106
    negative) matches and the centers of the half templates should score 2nd.
107
    """
108
    # Float prefactors ensure that image range is between 0 and 1
109
    template = 0.5 * diamond(2)
110
    image = 0.5 * np.ones((9, 19))
111
    mid = slice(2, 7)
112
    image[mid, :3] -= template[:, -3:]  # half min template centered at 0
113
    image[mid, 4:9] += template  # full max template centered at 6
114
    image[mid, -9:-4] -= template  # full min template centered at 12
115
    image[mid, -3:] += template[:, :3]  # half max template centered at 18
116

117
    result = match_template(
118
        image, template, pad_input=True, constant_values=image.mean()
119
    )
120

121
    # get the max and min results.
122
    sorted_result = np.argsort(result.flat)
123
    i, j = np.unravel_index(sorted_result[:2], result.shape)
124
    assert_equal(j, (12, 0))
125
    i, j = np.unravel_index(sorted_result[-2:], result.shape)
126
    assert_equal(j, (18, 6))
127

128

129
def test_3d():
130
    np.random.seed(1)
131
    template = np.random.rand(3, 3, 3)
132
    image = np.zeros((12, 12, 12))
133

134
    image[3:6, 5:8, 4:7] = template
135

136
    result = match_template(image, template)
137

138
    assert_equal(result.shape, (10, 10, 10))
139
    assert_equal(np.unravel_index(result.argmax(), result.shape), (3, 5, 4))
140

141

142
def test_3d_pad_input():
143
    np.random.seed(1)
144
    template = np.random.rand(3, 3, 3)
145
    image = np.zeros((12, 12, 12))
146

147
    image[3:6, 5:8, 4:7] = template
148

149
    result = match_template(image, template, pad_input=True)
150

151
    assert_equal(result.shape, (12, 12, 12))
152
    assert_equal(np.unravel_index(result.argmax(), result.shape), (4, 6, 5))
153

154

155
def test_padding_reflect():
156
    template = diamond(2)
157
    image = np.zeros((10, 10))
158
    image[2:7, :3] = template[:, -3:]
159

160
    result = match_template(image, template, pad_input=True, mode='reflect')
161

162
    assert_equal(np.unravel_index(result.argmax(), result.shape), (4, 0))
163

164

165
def test_wrong_input():
166
    image = np.ones((5, 5, 1))
167
    template = np.ones((3, 3))
168
    with testing.raises(ValueError):
169
        match_template(template, image)
170

171
    image = np.ones((5, 5))
172
    template = np.ones((3, 3, 2))
173
    with testing.raises(ValueError):
174
        match_template(template, image)
175

176
    image = np.ones((5, 5, 3, 3))
177
    template = np.ones((3, 3, 2))
178
    with testing.raises(ValueError):
179
        match_template(template, image)
180

181

182
def test_bounding_values():
183
    image = img_as_float(data.page())
184
    template = np.zeros((3, 3))
185
    template[1, 1] = 1
186
    result = match_template(image, template)
187
    print(result.max())
188
    assert result.max() < 1 + 1e-7
189
    assert result.min() > -1 - 1e-7
190

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.