test_image.py 15.2 KB
Newer Older
1
2
3
4
import os
import os.path as osp
import tempfile

5
import cv2
6
7
import numpy as np
import pytest
Kai Chen's avatar
Kai Chen committed
8
9
10
from numpy.testing import assert_array_almost_equal, assert_array_equal

import mmcv
11
12
13
14
15
16
17
18
19
20


class TestImage(object):

    @classmethod
    def setup_class(cls):
        # the test img resolution is 400x300
        cls.img_path = osp.join(osp.dirname(__file__), 'data/color.jpg')
        cls.gray_img_path = osp.join(
            osp.dirname(__file__), 'data/grayscale.jpg')
21
        cls.img = cv2.imread(cls.img_path)
22
23
24
25
26
27
28
29

    def assert_img_equal(self, img, ref_img, ratio_thr=0.999):
        assert img.shape == ref_img.shape
        assert img.dtype == ref_img.dtype
        area = ref_img.shape[0] * ref_img.shape[1]
        diff = np.abs(img.astype('int32') - ref_img.astype('int32'))
        assert np.sum(diff <= 1) / float(area) > ratio_thr

30
31
    def test_imread(self):
        img = mmcv.imread(self.img_path)
32
        assert img.shape == (300, 400, 3)
33
        img = mmcv.imread(self.img_path, 'grayscale')
34
        assert img.shape == (300, 400)
35
        img = mmcv.imread(self.gray_img_path)
36
        assert img.shape == (300, 400, 3)
37
        img = mmcv.imread(self.gray_img_path, 'unchanged')
38
        assert img.shape == (300, 400)
39
40
        img = mmcv.imread(img)
        assert_array_equal(img, mmcv.imread(img))
41
        with pytest.raises(TypeError):
42
            mmcv.imread(1)
43

44
    def test_imfrombytes(self):
45
46
        with open(self.img_path, 'rb') as f:
            img_bytes = f.read()
47
        img = mmcv.imfrombytes(img_bytes)
48
49
        assert img.shape == (300, 400, 3)

50
51
    def test_imwrite(self):
        img = mmcv.imread(self.img_path)
52
        out_file = osp.join(tempfile.gettempdir(), 'mmcv_test.jpg')
53
54
        mmcv.imwrite(img, out_file)
        rewrite_img = mmcv.imread(out_file)
55
56
57
58
59
60
        os.remove(out_file)
        self.assert_img_equal(img, rewrite_img)

    def test_bgr2gray(self):
        in_img = np.random.rand(10, 10, 3).astype(np.float32)
        out_img = mmcv.bgr2gray(in_img)
Kai Chen's avatar
Kai Chen committed
61
62
63
        computed_gray = (
            in_img[:, :, 0] * 0.114 + in_img[:, :, 1] * 0.587 +
            in_img[:, :, 2] * 0.299)
64
65
66
67
68
        assert_array_almost_equal(out_img, computed_gray, decimal=4)
        out_img_3d = mmcv.bgr2gray(in_img, True)
        assert out_img_3d.shape == (10, 10, 1)
        assert_array_almost_equal(out_img_3d[..., 0], out_img, decimal=4)

Kai Chen's avatar
Kai Chen committed
69
70
71
72
73
74
75
76
77
78
79
    def test_rgb2gray(self):
        in_img = np.random.rand(10, 10, 3).astype(np.float32)
        out_img = mmcv.rgb2gray(in_img)
        computed_gray = (
            in_img[:, :, 0] * 0.299 + in_img[:, :, 1] * 0.587 +
            in_img[:, :, 2] * 0.114)
        assert_array_almost_equal(out_img, computed_gray, decimal=4)
        out_img_3d = mmcv.rgb2gray(in_img, True)
        assert out_img_3d.shape == (10, 10, 1)
        assert_array_almost_equal(out_img_3d[..., 0], out_img, decimal=4)

80
81
82
83
84
85
86
    def test_gray2bgr(self):
        in_img = np.random.rand(10, 10).astype(np.float32)
        out_img = mmcv.gray2bgr(in_img)
        assert out_img.shape == (10, 10, 3)
        for i in range(3):
            assert_array_almost_equal(out_img[..., i], in_img, decimal=4)

Kai Chen's avatar
Kai Chen committed
87
88
89
90
91
92
93
    def test_gray2rgb(self):
        in_img = np.random.rand(10, 10).astype(np.float32)
        out_img = mmcv.gray2rgb(in_img)
        assert out_img.shape == (10, 10, 3)
        for i in range(3):
            assert_array_almost_equal(out_img[..., i], in_img, decimal=4)

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    def test_bgr2rgb(self):
        in_img = np.random.rand(10, 10, 3).astype(np.float32)
        out_img = mmcv.bgr2rgb(in_img)
        assert out_img.shape == in_img.shape
        assert_array_equal(out_img[..., 0], in_img[..., 2])
        assert_array_equal(out_img[..., 1], in_img[..., 1])
        assert_array_equal(out_img[..., 2], in_img[..., 0])

    def test_rgb2bgr(self):
        in_img = np.random.rand(10, 10, 3).astype(np.float32)
        out_img = mmcv.rgb2bgr(in_img)
        assert out_img.shape == in_img.shape
        assert_array_equal(out_img[..., 0], in_img[..., 2])
        assert_array_equal(out_img[..., 1], in_img[..., 1])
        assert_array_equal(out_img[..., 2], in_img[..., 0])

    def test_bgr2hsv(self):
        in_img = np.random.rand(10, 10, 3).astype(np.float32)
        out_img = mmcv.bgr2hsv(in_img)
        argmax = in_img.argmax(axis=2)
        computed_hsv = np.empty_like(in_img, dtype=in_img.dtype)
        for i in range(in_img.shape[0]):
            for j in range(in_img.shape[1]):
                b = in_img[i, j, 0]
                g = in_img[i, j, 1]
                r = in_img[i, j, 2]
                v = max(r, g, b)
                s = (v - min(r, g, b)) / v if v != 0 else 0
                if argmax[i, j] == 0:
                    h = 240 + 60 * (r - g) / (v - min(r, g, b))
                elif argmax[i, j] == 1:
                    h = 120 + 60 * (b - r) / (v - min(r, g, b))
                else:
                    h = 60 * (g - b) / (v - min(r, g, b))
                if h < 0:
                    h += 360
                computed_hsv[i, j, :] = [h, s, v]
        assert_array_almost_equal(out_img, computed_hsv, decimal=2)

Gu Wang's avatar
Gu Wang committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    def test_bgr2hls(self):
        in_img = np.random.rand(10, 10, 3).astype(np.float32)
        out_img = mmcv.bgr2hls(in_img)
        argmax = in_img.argmax(axis=2)
        computed_hls = np.empty_like(in_img, dtype=in_img.dtype)
        for i in range(in_img.shape[0]):
            for j in range(in_img.shape[1]):
                b = in_img[i, j, 0]
                g = in_img[i, j, 1]
                r = in_img[i, j, 2]
                maxc = max(r, g, b)
                minc = min(r, g, b)
                _l = (minc + maxc) / 2.0
                if minc == maxc:
                    h = 0.0
                    s = 0.0
                if _l <= 0.5:
                    s = (maxc - minc) / (maxc + minc)
                else:
                    s = (maxc - minc) / (2.0 - maxc - minc)
                if argmax[i, j] == 2:
                    h = 60 * (g - b) / (maxc - minc)
                elif argmax[i, j] == 1:
                    h = 60 * (2.0 + (b - r) / (maxc - minc))
                else:
                    h = 60 * (4.0 + (r - g) / (maxc - minc))
                if h < 0:
                    h += 360
                computed_hls[i, j, :] = [h, _l, s]
        assert_array_almost_equal(out_img, computed_hls, decimal=2)

164
165
    def test_imresize(self):
        resized_img = mmcv.imresize(self.img, (1000, 600))
166
        assert resized_img.shape == (600, 1000, 3)
167
168
        resized_img, w_scale, h_scale = mmcv.imresize(self.img, (1000, 600),
                                                      True)
169
170
171
        assert (resized_img.shape == (600, 1000, 3) and w_scale == 2.5
                and h_scale == 2.0)
        for mode in ['nearest', 'bilinear', 'bicubic', 'area', 'lanczos']:
172
173
            resized_img = mmcv.imresize(
                self.img, (1000, 600), interpolation=mode)
174
175
            assert resized_img.shape == (600, 1000, 3)

176
    def test_imresize_like(self):
177
        a = np.zeros((100, 200, 3))
178
        resized_img = mmcv.imresize_like(self.img, a)
179
180
        assert resized_img.shape == (100, 200, 3)

181
182
183
    def test_imrescale(self):
        # rescale by a certain factor
        resized_img = mmcv.imrescale(self.img, 1.5)
184
        assert resized_img.shape == (450, 600, 3)
185
        resized_img = mmcv.imrescale(self.img, 0.934)
186
187
        assert resized_img.shape == (280, 374, 3)

188
        # rescale by a certain max_size
189
        # resize (400, 300) to (max_1000, max_600)
190
        resized_img = mmcv.imrescale(self.img, (1000, 600))
191
        assert resized_img.shape == (600, 800, 3)
192
193
        resized_img, scale = mmcv.imrescale(
            self.img, (1000, 600), return_scale=True)
194
195
        assert resized_img.shape == (600, 800, 3) and scale == 2.0
        # resize (400, 300) to (max_200, max_180)
196
        resized_img = mmcv.imrescale(self.img, (180, 200))
197
        assert resized_img.shape == (150, 200, 3)
198
199
        resized_img, scale = mmcv.imrescale(
            self.img, (180, 200), return_scale=True)
200
        assert resized_img.shape == (150, 200, 3) and scale == 0.5
201
202

        # test exceptions
203
        with pytest.raises(ValueError):
204
205
206
            mmcv.imrescale(self.img, -0.5)
        with pytest.raises(TypeError):
            mmcv.imrescale(self.img, [100, 100])
207

Kai Chen's avatar
Kai Chen committed
208
    def test_imflip(self):
Kai Chen's avatar
Kai Chen committed
209
        # test horizontal flip (color image)
Kai Chen's avatar
Kai Chen committed
210
211
        img = np.random.rand(80, 60, 3)
        h, w, c = img.shape
Kai Chen's avatar
Kai Chen committed
212
213
        flipped_img = mmcv.imflip(img)
        assert flipped_img.shape == img.shape
Kai Chen's avatar
Kai Chen committed
214
215
216
        for i in range(h):
            for j in range(w):
                for k in range(c):
Kai Chen's avatar
Kai Chen committed
217
218
219
220
                    assert flipped_img[i, j, k] == img[i, w - 1 - j, k]
        # test vertical flip (color image)
        flipped_img = mmcv.imflip(img, direction='vertical')
        assert flipped_img.shape == img.shape
Kai Chen's avatar
Kai Chen committed
221
222
223
        for i in range(h):
            for j in range(w):
                for k in range(c):
Kai Chen's avatar
Kai Chen committed
224
225
                    assert flipped_img[i, j, k] == img[h - 1 - i, j, k]
        # test horizontal flip (grayscale image)
Kai Chen's avatar
Kai Chen committed
226
        img = np.random.rand(80, 60)
Kai Chen's avatar
Kai Chen committed
227
228
229
        h, w = img.shape
        flipped_img = mmcv.imflip(img)
        assert flipped_img.shape == img.shape
Kai Chen's avatar
Kai Chen committed
230
231
        for i in range(h):
            for j in range(w):
Kai Chen's avatar
Kai Chen committed
232
233
234
235
                assert flipped_img[i, j] == img[i, w - 1 - j]
        # test vertical flip (grayscale image)
        flipped_img = mmcv.imflip(img, direction='vertical')
        assert flipped_img.shape == img.shape
Kai Chen's avatar
Kai Chen committed
236
237
        for i in range(h):
            for j in range(w):
Kai Chen's avatar
Kai Chen committed
238
                assert flipped_img[i, j] == img[h - 1 - i, j]
Kai Chen's avatar
Kai Chen committed
239

240
    def test_imcrop(self):
241
242
243
244
245
246
247
        # yapf: disable
        bboxes = np.array([[100, 100, 199, 199],  # center
                           [0, 0, 150, 100],  # left-top corner
                           [250, 200, 399, 299],  # right-bottom corner
                           [0, 100, 399, 199],  # wide
                           [150, 0, 299, 299]])  # tall
        # yapf: enable
248

249
        # crop one bbox
250
251
        patch = mmcv.imcrop(self.img, bboxes[0, :])
        patches = mmcv.imcrop(self.img, bboxes[[0], :])
252
253
254
255
256
257
        assert patch.shape == (100, 100, 3)
        patch_path = osp.join(osp.dirname(__file__), 'data/patches')
        ref_patch = np.load(patch_path + '/0.npy')
        self.assert_img_equal(patch, ref_patch)
        assert isinstance(patches, list) and len(patches) == 1
        self.assert_img_equal(patches[0], ref_patch)
258

259
        # crop with no scaling and padding
260
        patches = mmcv.imcrop(self.img, bboxes)
261
262
263
264
        assert len(patches) == bboxes.shape[0]
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)
265

266
        # crop with scaling and no padding
267
        patches = mmcv.imcrop(self.img, bboxes, 1.2)
268
269
270
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/scale_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)
271

272
        # crop with scaling and padding
273
        patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=[255, 255, 0])
274
275
276
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/pad_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)
277
        patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=0)
278
279
280
281
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/pad0_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)

282
    def test_impad(self):
283
        img = np.random.rand(10, 10, 3).astype(np.float32)
284
        padded_img = mmcv.impad(img, (15, 12), 0)
285
286
287
288
289
        assert_array_equal(img, padded_img[:10, :10, :])
        assert_array_equal(
            np.zeros((5, 12, 3), dtype='float32'), padded_img[10:, :, :])
        assert_array_equal(
            np.zeros((15, 2, 3), dtype='float32'), padded_img[:, 10:, :])
290

291
        img = np.random.randint(256, size=(10, 10, 3)).astype('uint8')
292
        padded_img = mmcv.impad(img, (15, 12, 3), [100, 110, 120])
293
294
295
296
297
298
299
        assert_array_equal(img, padded_img[:10, :10, :])
        assert_array_equal(
            np.array([100, 110, 120], dtype='uint8') * np.ones(
                (5, 12, 3), dtype='uint8'), padded_img[10:, :, :])
        assert_array_equal(
            np.array([100, 110, 120], dtype='uint8') * np.ones(
                (15, 2, 3), dtype='uint8'), padded_img[:, 10:, :])
300

301
        with pytest.raises(AssertionError):
302
            mmcv.impad(img, (15, ), 0)
303
        with pytest.raises(AssertionError):
304
            mmcv.impad(img, (5, 5), 0)
305
        with pytest.raises(AssertionError):
306
            mmcv.impad(img, (5, 5), [0, 1])
307

Kai Chen's avatar
Kai Chen committed
308
309
310
311
312
313
314
315
316
317
318
    def test_impad_to_multiple(self):
        img = np.random.rand(11, 14, 3).astype(np.float32)
        padded_img = mmcv.impad_to_multiple(img, 4)
        assert padded_img.shape == (12, 16, 3)
        img = np.random.rand(20, 12).astype(np.float32)
        padded_img = mmcv.impad_to_multiple(img, 5)
        assert padded_img.shape == (20, 15)
        img = np.random.rand(20, 12).astype(np.float32)
        padded_img = mmcv.impad_to_multiple(img, 2)
        assert padded_img.shape == (20, 12)

319
    def test_imrotate(self):
320
        img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8)
321
        assert_array_equal(mmcv.imrotate(img, 0), img)
322
        img_r = np.array([[7, 4, 1], [8, 5, 2], [9, 6, 3]])
323
        assert_array_equal(mmcv.imrotate(img, 90), img_r)
324
        img_r = np.array([[3, 6, 9], [2, 5, 8], [1, 4, 7]])
325
        assert_array_equal(mmcv.imrotate(img, -90), img_r)
326
327
328

        img = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]).astype(np.uint8)
        img_r = np.array([[0, 6, 2, 0], [0, 7, 3, 0]])
329
        assert_array_equal(mmcv.imrotate(img, 90), img_r)
330
        img_r = np.array([[1, 0, 0, 0], [2, 0, 0, 0]])
331
        assert_array_equal(mmcv.imrotate(img, 90, center=(0, 0)), img_r)
332
        img_r = np.array([[255, 6, 2, 255], [255, 7, 3, 255]])
333
        assert_array_equal(mmcv.imrotate(img, 90, border_value=255), img_r)
334
        img_r = np.array([[5, 1], [6, 2], [7, 3], [8, 4]])
335
336
337
338
        assert_array_equal(mmcv.imrotate(img, 90, auto_bound=True), img_r)

        with pytest.raises(ValueError):
            mmcv.imrotate(img, 90, center=(0, 0), auto_bound=True)
Yue Zhao's avatar
Yue Zhao committed
339
340
341
342
343
344
345

    def test_iminvert(self):
        img = np.array([[0, 128, 255], [1, 127, 254], [2, 129, 253]],
                       dtype=np.uint8)
        img_r = np.array([[255, 127, 0], [254, 128, 1], [253, 126, 2]],
                         dtype=np.uint8)
        assert_array_equal(mmcv.iminvert(img), img_r)
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365

    def test_solarize(self):
        img = np.array([[0, 128, 255], [1, 127, 254], [2, 129, 253]],
                       dtype=np.uint8)
        img_r = np.array([[0, 127, 0], [1, 127, 1], [2, 126, 2]],
                         dtype=np.uint8)
        assert_array_equal(mmcv.solarize(img), img_r)
        img_r = np.array([[0, 127, 0], [1, 128, 1], [2, 126, 2]],
                         dtype=np.uint8)
        assert_array_equal(mmcv.solarize(img, 100), img_r)

    def test_posterize(self):
        img = np.array([[0, 128, 255], [1, 127, 254], [2, 129, 253]],
                       dtype=np.uint8)
        img_r = np.array([[0, 128, 128], [0, 0, 128], [0, 128, 128]],
                         dtype=np.uint8)
        assert_array_equal(mmcv.posterize(img, 1), img_r)
        img_r = np.array([[0, 128, 224], [0, 96, 224], [0, 128, 224]],
                         dtype=np.uint8)
        assert_array_equal(mmcv.posterize(img, 3), img_r)