scikit-image

Форк
0
/
test_texture.py 
368 строк · 13.3 Кб
1
import numpy as np
2
import pytest
3

4
from skimage._shared.testing import expected_warnings, run_in_parallel
5
from skimage.feature import (
6
    graycomatrix,
7
    graycoprops,
8
    local_binary_pattern,
9
    multiblock_lbp,
10
)
11
from skimage.transform import integral_image
12

13

14
class TestGLCM:
15
    def setup_method(self):
16
        self.image = np.array(
17
            [[0, 0, 1, 1], [0, 0, 1, 1], [0, 2, 2, 2], [2, 2, 3, 3]], dtype=np.uint8
18
        )
19

20
    @run_in_parallel()
21
    def test_output_angles(self):
22
        result = graycomatrix(
23
            self.image, [1], [0, np.pi / 4, np.pi / 2, 3 * np.pi / 4], 4
24
        )
25
        assert result.shape == (4, 4, 1, 4)
26
        expected1 = np.array(
27
            [[2, 2, 1, 0], [0, 2, 0, 0], [0, 0, 3, 1], [0, 0, 0, 1]], dtype=np.uint32
28
        )
29
        np.testing.assert_array_equal(result[:, :, 0, 0], expected1)
30
        expected2 = np.array(
31
            [[1, 1, 3, 0], [0, 1, 1, 0], [0, 0, 0, 2], [0, 0, 0, 0]], dtype=np.uint32
32
        )
33
        np.testing.assert_array_equal(result[:, :, 0, 1], expected2)
34
        expected3 = np.array(
35
            [[3, 0, 2, 0], [0, 2, 2, 0], [0, 0, 1, 2], [0, 0, 0, 0]], dtype=np.uint32
36
        )
37
        np.testing.assert_array_equal(result[:, :, 0, 2], expected3)
38
        expected4 = np.array(
39
            [[2, 0, 0, 0], [1, 1, 2, 0], [0, 0, 2, 1], [0, 0, 0, 0]], dtype=np.uint32
40
        )
41
        np.testing.assert_array_equal(result[:, :, 0, 3], expected4)
42

43
    def test_output_symmetric_1(self):
44
        result = graycomatrix(self.image, [1], [np.pi / 2], 4, symmetric=True)
45
        assert result.shape == (4, 4, 1, 1)
46
        expected = np.array(
47
            [[6, 0, 2, 0], [0, 4, 2, 0], [2, 2, 2, 2], [0, 0, 2, 0]], dtype=np.uint32
48
        )
49
        np.testing.assert_array_equal(result[:, :, 0, 0], expected)
50

51
    def test_error_raise_float(self):
52
        for dtype in [float, np.double, np.float16, np.float32, np.float64]:
53
            with pytest.raises(ValueError):
54
                graycomatrix(self.image.astype(dtype), [1], [np.pi], 4)
55

56
    def test_error_raise_int_types(self):
57
        for dtype in [np.int16, np.int32, np.int64, np.uint16, np.uint32, np.uint64]:
58
            with pytest.raises(ValueError):
59
                graycomatrix(self.image.astype(dtype), [1], [np.pi])
60

61
    def test_error_raise_negative(self):
62
        with pytest.raises(ValueError):
63
            graycomatrix(self.image.astype(np.int16) - 1, [1], [np.pi], 4)
64

65
    def test_error_raise_levels_smaller_max(self):
66
        with pytest.raises(ValueError):
67
            graycomatrix(self.image - 1, [1], [np.pi], 3)
68

69
    def test_image_data_types(self):
70
        for dtype in [np.uint16, np.uint32, np.uint64, np.int16, np.int32, np.int64]:
71
            img = self.image.astype(dtype)
72
            result = graycomatrix(img, [1], [np.pi / 2], 4, symmetric=True)
73
            assert result.shape == (4, 4, 1, 1)
74
            expected = np.array(
75
                [[6, 0, 2, 0], [0, 4, 2, 0], [2, 2, 2, 2], [0, 0, 2, 0]],
76
                dtype=np.uint32,
77
            )
78
            np.testing.assert_array_equal(result[:, :, 0, 0], expected)
79

80
        return
81

82
    def test_output_distance(self):
83
        im = np.array(
84
            [[0, 0, 0, 0], [1, 0, 0, 1], [2, 0, 0, 2], [3, 0, 0, 3]], dtype=np.uint8
85
        )
86
        result = graycomatrix(im, [3], [0], 4, symmetric=False)
87
        expected = np.array(
88
            [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], dtype=np.uint32
89
        )
90
        np.testing.assert_array_equal(result[:, :, 0, 0], expected)
91

92
    def test_output_combo(self):
93
        im = np.array([[0], [1], [2], [3]], dtype=np.uint8)
94
        result = graycomatrix(im, [1, 2], [0, np.pi / 2], 4)
95
        assert result.shape == (4, 4, 2, 2)
96

97
        z = np.zeros((4, 4), dtype=np.uint32)
98
        e1 = np.array(
99
            [[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], [0, 0, 0, 0]], dtype=np.uint32
100
        )
101
        e2 = np.array(
102
            [[0, 0, 1, 0], [0, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0]], dtype=np.uint32
103
        )
104

105
        np.testing.assert_array_equal(result[:, :, 0, 0], z)
106
        np.testing.assert_array_equal(result[:, :, 1, 0], z)
107
        np.testing.assert_array_equal(result[:, :, 0, 1], e1)
108
        np.testing.assert_array_equal(result[:, :, 1, 1], e2)
109

110
    def test_output_empty(self):
111
        result = graycomatrix(self.image, [10], [0], 4)
112
        np.testing.assert_array_equal(
113
            result[:, :, 0, 0], np.zeros((4, 4), dtype=np.uint32)
114
        )
115
        result = graycomatrix(self.image, [10], [0], 4, normed=True)
116
        np.testing.assert_array_equal(
117
            result[:, :, 0, 0], np.zeros((4, 4), dtype=np.uint32)
118
        )
119

120
    def test_normed_symmetric(self):
121
        result = graycomatrix(
122
            self.image, [1, 2, 3], [0, np.pi / 2, np.pi], 4, normed=True, symmetric=True
123
        )
124
        for d in range(result.shape[2]):
125
            for a in range(result.shape[3]):
126
                np.testing.assert_almost_equal(result[:, :, d, a].sum(), 1.0)
127
                np.testing.assert_array_equal(
128
                    result[:, :, d, a], result[:, :, d, a].transpose()
129
                )
130

131
    def test_contrast(self):
132
        result = graycomatrix(self.image, [1, 2], [0], 4, normed=True, symmetric=True)
133
        result = np.round(result, 3)
134
        contrast = graycoprops(result, 'contrast')
135
        np.testing.assert_almost_equal(contrast[0, 0], 0.585, decimal=3)
136

137
    def test_dissimilarity(self):
138
        result = graycomatrix(
139
            self.image, [1], [0, np.pi / 2], 4, normed=True, symmetric=True
140
        )
141
        result = np.round(result, 3)
142
        dissimilarity = graycoprops(result, 'dissimilarity')
143
        np.testing.assert_almost_equal(dissimilarity[0, 0], 0.418, decimal=3)
144

145
    def test_dissimilarity_2(self):
146
        result = graycomatrix(
147
            self.image, [1, 3], [np.pi / 2], 4, normed=True, symmetric=True
148
        )
149
        result = np.round(result, 3)
150
        dissimilarity = graycoprops(result, 'dissimilarity')[0, 0]
151
        np.testing.assert_almost_equal(dissimilarity, 0.665, decimal=3)
152

153
    def test_non_normalized_glcm(self):
154
        img = (np.random.random((100, 100)) * 8).astype(np.uint8)
155
        p = graycomatrix(img, [1, 2, 4, 5], [0, 0.25, 1, 1.5], levels=8)
156
        np.testing.assert_(np.max(graycoprops(p, 'correlation')) < 1.0)
157

158
    def test_invalid_property(self):
159
        result = graycomatrix(self.image, [1], [0], 4)
160
        with pytest.raises(ValueError):
161
            graycoprops(result, 'ABC')
162

163
    def test_homogeneity(self):
164
        result = graycomatrix(self.image, [1], [0, 6], 4, normed=True, symmetric=True)
165
        homogeneity = graycoprops(result, 'homogeneity')[0, 0]
166
        np.testing.assert_almost_equal(homogeneity, 0.80833333)
167

168
    def test_energy(self):
169
        result = graycomatrix(self.image, [1], [0, 4], 4, normed=True, symmetric=True)
170
        energy = graycoprops(result, 'energy')[0, 0]
171
        np.testing.assert_almost_equal(energy, 0.38188131)
172

173
    def test_correlation(self):
174
        result = graycomatrix(self.image, [1, 2], [0], 4, normed=True, symmetric=True)
175
        energy = graycoprops(result, 'correlation')
176
        np.testing.assert_almost_equal(energy[0, 0], 0.71953255)
177
        np.testing.assert_almost_equal(energy[1, 0], 0.41176470)
178

179
    def test_mean(self):
180
        result = graycomatrix(
181
            self.image, [1], [0, np.pi / 2], 4, normed=True, symmetric=True
182
        )
183
        mean = graycoprops(result, 'mean')[0, 0]
184

185
        # Reference value was calculated by hand and is close to original source if precision 3 is used.
186
        np.testing.assert_almost_equal(mean, 1.29166667)
187

188
    def test_variance(self):
189
        result = graycomatrix(
190
            self.image, [1], [0, np.pi / 2], 4, normed=True, symmetric=True
191
        )
192
        variance = graycoprops(result, 'variance')[0, 0]
193

194
        # Reference value was calculated by hand and is close to original source if precision 3 is used.
195
        np.testing.assert_almost_equal(variance, 1.03993055)
196

197
    def test_std(self):
198
        result = graycomatrix(
199
            self.image, [1], [0, np.pi / 2], 4, normed=True, symmetric=True
200
        )
201
        std = graycoprops(result, 'std')[0, 0]
202

203
        # Reference value was calculated by hand and is close to original source if precision 3 is used.
204
        np.testing.assert_almost_equal(std, 1.01976985)
205

206
    def test_entropy(self):
207
        result = graycomatrix(
208
            self.image, [1], [0, np.pi / 2], 4, normed=True, symmetric=True
209
        )
210
        entropy = graycoprops(result, 'entropy')[0, 0]
211

212
        # Reference value was calculated by hand and is close to original source if precision 3 is used.
213
        np.testing.assert_almost_equal(entropy, 2.09472904)
214

215
    def test_uniform_properties(self):
216
        im = np.ones((4, 4), dtype=np.uint8)
217
        result = graycomatrix(
218
            im, [1, 2, 8], [0, np.pi / 2], 4, normed=True, symmetric=True
219
        )
220
        for prop in [
221
            'contrast',
222
            'dissimilarity',
223
            'homogeneity',
224
            'energy',
225
            'correlation',
226
            'ASM',
227
            'mean',
228
            'variance',
229
            'std',
230
            'entropy',
231
        ]:
232
            graycoprops(result, prop)
233

234

235
class TestLBP:
236
    def setup_method(self):
237
        self.image = np.array(
238
            [
239
                [255, 6, 255, 0, 141, 0],
240
                [48, 250, 204, 166, 223, 63],
241
                [8, 0, 159, 50, 255, 30],
242
                [167, 255, 63, 40, 128, 255],
243
                [0, 255, 30, 34, 255, 24],
244
                [146, 241, 255, 0, 189, 126],
245
            ],
246
            dtype=np.uint8,
247
        )
248

249
    @run_in_parallel()
250
    def test_default(self):
251
        lbp = local_binary_pattern(self.image, 8, 1, 'default')
252
        ref = np.array(
253
            [
254
                [0, 251, 0, 255, 96, 255],
255
                [143, 0, 20, 153, 64, 56],
256
                [238, 255, 12, 191, 0, 252],
257
                [129, 64.0, 62, 159, 199, 0],
258
                [255, 4, 255, 175, 0, 254],
259
                [3, 5, 0, 255, 4, 24],
260
            ]
261
        )
262
        np.testing.assert_array_equal(lbp, ref)
263

264
    def test_ror(self):
265
        lbp = local_binary_pattern(self.image, 8, 1, 'ror')
266
        ref = np.array(
267
            [
268
                [0, 127, 0, 255, 3, 255],
269
                [31, 0, 5, 51, 1, 7],
270
                [119, 255, 3, 127, 0, 63],
271
                [3, 1, 31, 63, 31, 0],
272
                [255, 1, 255, 95, 0, 127],
273
                [3, 5, 0, 255, 1, 3],
274
            ]
275
        )
276
        np.testing.assert_array_equal(lbp, ref)
277

278
    @pytest.mark.parametrize('dtype', [np.float16, np.float32, np.float64])
279
    def test_float_warning(self, dtype):
280
        image = self.image.astype(dtype)
281
        msg = "Applying `local_binary_pattern` to floating-point images"
282
        with expected_warnings([msg]):
283
            lbp = local_binary_pattern(image, 8, 1, 'ror')
284
        ref = np.array(
285
            [
286
                [0, 127, 0, 255, 3, 255],
287
                [31, 0, 5, 51, 1, 7],
288
                [119, 255, 3, 127, 0, 63],
289
                [3, 1, 31, 63, 31, 0],
290
                [255, 1, 255, 95, 0, 127],
291
                [3, 5, 0, 255, 1, 3],
292
            ]
293
        )
294
        np.testing.assert_array_equal(lbp, ref)
295

296
    def test_uniform(self):
297
        lbp = local_binary_pattern(self.image, 8, 1, 'uniform')
298
        ref = np.array(
299
            [
300
                [0, 7, 0, 8, 2, 8],
301
                [5, 0, 9, 9, 1, 3],
302
                [9, 8, 2, 7, 0, 6],
303
                [2, 1, 5, 6, 5, 0],
304
                [8, 1, 8, 9, 0, 7],
305
                [2, 9, 0, 8, 1, 2],
306
            ]
307
        )
308
        np.testing.assert_array_equal(lbp, ref)
309

310
    def test_var(self):
311
        # Test idea: mean of variance is estimate of overall variance.
312

313
        # Fix random seed for test stability.
314
        np.random.seed(13141516)
315

316
        # Create random image with known variance.
317
        image = np.random.rand(500, 500)
318
        target_std = 0.3
319
        image = image / image.std() * target_std
320

321
        # Use P=4 to avoid interpolation effects
322
        P, R = 4, 1
323
        msg = "Applying `local_binary_pattern` to floating-point images"
324
        with expected_warnings([msg]):
325
            lbp = local_binary_pattern(image, P, R, 'var')
326

327
        # Take central part to avoid border effect.
328
        lbp = lbp[5:-5, 5:-5]
329

330
        # The LBP variance is biased (ddof=0), correct for that.
331
        expected = target_std**2 * (P - 1) / P
332

333
        np.testing.assert_almost_equal(lbp.mean(), expected, 4)
334

335
    def test_nri_uniform(self):
336
        lbp = local_binary_pattern(self.image, 8, 1, 'nri_uniform')
337
        ref = np.array(
338
            [
339
                [0, 54, 0, 57, 12, 57],
340
                [34, 0, 58, 58, 3, 22],
341
                [58, 57, 15, 50, 0, 47],
342
                [10, 3, 40, 42, 35, 0],
343
                [57, 7, 57, 58, 0, 56],
344
                [9, 58, 0, 57, 7, 14],
345
            ]
346
        )
347
        np.testing.assert_array_almost_equal(lbp, ref)
348

349

350
class TestMBLBP:
351
    def test_single_mblbp(self):
352
        # Create dummy matrix where first and fifth rectangles have greater
353
        # value than the central one. Therefore, the following bits
354
        # should be 1.
355
        test_img = np.zeros((9, 9), dtype='uint8')
356
        test_img[3:6, 3:6] = 1
357
        test_img[:3, :3] = 255
358
        test_img[6:, 6:] = 255
359

360
        # MB-LBP is filled in reverse order. So the first and fifth bits from
361
        # the end should be filled.
362
        correct_answer = 0b10001000
363

364
        int_img = integral_image(test_img)
365

366
        lbp_code = multiblock_lbp(int_img, 0, 0, 3, 3)
367

368
        np.testing.assert_equal(lbp_code, correct_answer)
369

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

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

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

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