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

5
import cv2
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import mmcv
import numpy as np
import pytest
from numpy.testing import assert_array_equal, assert_array_almost_equal


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')
20
        cls.img = cv2.imread(cls.img_path)
21
22
23
24
25
26
27
28

    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

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

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

49
50
    def test_imwrite(self):
        img = mmcv.imread(self.img_path)
51
        out_file = osp.join(tempfile.gettempdir(), 'mmcv_test.jpg')
52
53
        mmcv.imwrite(img, out_file)
        rewrite_img = mmcv.imread(out_file)
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
        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)
        computed_gray = (in_img[:, :, 0] * 0.114 + in_img[:, :, 1] * 0.587 +
                         in_img[:, :, 2] * 0.299)
        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)

    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)

    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)

    def test_scale_size(self):
        assert mmcv.scale_size((300, 200), 0.5) == (150, 100)
        assert mmcv.scale_size((11, 22), 0.7) == (8, 15)

117
118
    def test_imresize(self):
        resized_img = mmcv.imresize(self.img, (1000, 600))
119
        assert resized_img.shape == (600, 1000, 3)
120
121
        resized_img, w_scale, h_scale = mmcv.imresize(self.img, (1000, 600),
                                                      True)
122
123
124
        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']:
125
126
            resized_img = mmcv.imresize(
                self.img, (1000, 600), interpolation=mode)
127
128
            assert resized_img.shape == (600, 1000, 3)

129
    def test_imresize_like(self):
130
        a = np.zeros((100, 200, 3))
131
        resized_img = mmcv.imresize_like(self.img, a)
132
133
        assert resized_img.shape == (100, 200, 3)

134
135
136
    def test_imrescale(self):
        # rescale by a certain factor
        resized_img = mmcv.imrescale(self.img, 1.5)
137
        assert resized_img.shape == (450, 600, 3)
138
        resized_img = mmcv.imrescale(self.img, 0.934)
139
140
        assert resized_img.shape == (280, 374, 3)

141
        # rescale by a certain max_size
142
        # resize (400, 300) to (max_1000, max_600)
143
        resized_img = mmcv.imrescale(self.img, (1000, 600))
144
        assert resized_img.shape == (600, 800, 3)
145
146
        resized_img, scale = mmcv.imrescale(
            self.img, (1000, 600), return_scale=True)
147
148
        assert resized_img.shape == (600, 800, 3) and scale == 2.0
        # resize (400, 300) to (max_200, max_180)
149
        resized_img = mmcv.imrescale(self.img, (180, 200))
150
        assert resized_img.shape == (150, 200, 3)
151
152
        resized_img, scale = mmcv.imrescale(
            self.img, (180, 200), return_scale=True)
153
        assert resized_img.shape == (150, 200, 3) and scale == 0.5
154
155

        # test exceptions
156
        with pytest.raises(ValueError):
157
158
159
            mmcv.imrescale(self.img, -0.5)
        with pytest.raises(TypeError):
            mmcv.imrescale(self.img, [100, 100])
160
161
162

    def test_limit_size(self):
        # limit to 800
163
        resized_img = mmcv.limit_size(self.img, 800)
164
        assert resized_img.shape == (300, 400, 3)
165
        resized_img, scale = mmcv.limit_size(self.img, 800, True)
166
        assert resized_img.shape == (300, 400, 3) and scale == 1
167

168
        # limit to 200
169
        resized_img = mmcv.limit_size(self.img, 200)
170
        assert resized_img.shape == (150, 200, 3)
171
        resized_img, scale = mmcv.limit_size(self.img, 200, True)
172
        assert resized_img.shape == (150, 200, 3) and scale == 0.5
173

174
        # test with img rather than img path
175
        img = mmcv.imread(self.img)
176
177
178
179
180
        resized_img = mmcv.limit_size(img, 200)
        assert resized_img.shape == (150, 200, 3)
        resized_img, scale = mmcv.limit_size(img, 200, True)
        assert resized_img.shape == (150, 200, 3) and scale == 0.5

Kai Chen's avatar
Kai Chen committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    def test_imflip(self):
        # test color image
        img = np.random.rand(80, 60, 3)
        h, w, c = img.shape
        hf_img = mmcv.imflip(img)
        assert hf_img.shape == (h, w, c)
        for i in range(h):
            for j in range(w):
                for k in range(c):
                    assert hf_img[i, j, k] == img[i, w - 1 - j, k]
        hf_img = mmcv.imflip(img, direction='vertical')
        assert hf_img.shape == (h, w, c)
        for i in range(h):
            for j in range(w):
                for k in range(c):
                    assert hf_img[i, j, k] == self.img[h - 1 - i, j, k]
        # test grayscale image
        img = np.random.rand(80, 60)
        h, w, c = img.shape
        hf_img = mmcv.imflip(img)
        assert hf_img.shape == (h, w, c)
        for i in range(h):
            for j in range(w):
                assert hf_img[i, j, k] == img[i, w - 1 - j]
        hf_img = mmcv.imflip(img, direction='vertical')
        assert hf_img.shape == (h, w, c)
        for i in range(h):
            for j in range(w):
                assert hf_img[i, j, k] == self.img[h - 1 - i, j]

211
    def test_imcrop(self):
212
213
214
215
216
217
218
        # 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
219

220
        # crop one bbox
221
222
        patch = mmcv.imcrop(self.img, bboxes[0, :])
        patches = mmcv.imcrop(self.img, bboxes[[0], :])
223
224
225
226
227
228
        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)
229

230
        # crop with no scaling and padding
231
        patches = mmcv.imcrop(self.img, bboxes)
232
233
234
235
        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)
236

237
        # crop with scaling and no padding
238
        patches = mmcv.imcrop(self.img, bboxes, 1.2)
239
240
241
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/scale_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)
242

243
        # crop with scaling and padding
244
        patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=[255, 255, 0])
245
246
247
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/pad_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)
248
        patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=0)
249
250
251
252
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/pad0_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)

253
    def test_impad(self):
254
        img = np.random.rand(10, 10, 3).astype(np.float32)
255
        padded_img = mmcv.impad(img, (15, 12), 0)
256
257
258
259
260
        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:, :])
261

262
        img = np.random.randint(256, size=(10, 10, 3)).astype('uint8')
263
        padded_img = mmcv.impad(img, (15, 12, 3), [100, 110, 120])
264
265
266
267
268
269
270
        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:, :])
271

272
        with pytest.raises(AssertionError):
273
            mmcv.impad(img, (15, ), 0)
274
        with pytest.raises(AssertionError):
275
            mmcv.impad(img, (5, 5), 0)
276
        with pytest.raises(AssertionError):
277
            mmcv.impad(img, (5, 5), [0, 1])
278

Kai Chen's avatar
Kai Chen committed
279
280
281
282
283
284
285
286
287
288
289
    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)

290
    def test_imrotate(self):
291
        img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8)
292
        assert_array_equal(mmcv.imrotate(img, 0), img)
293
        img_r = np.array([[7, 4, 1], [8, 5, 2], [9, 6, 3]])
294
        assert_array_equal(mmcv.imrotate(img, 90), img_r)
295
        img_r = np.array([[3, 6, 9], [2, 5, 8], [1, 4, 7]])
296
        assert_array_equal(mmcv.imrotate(img, -90), img_r)
297
298
299

        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]])
300
        assert_array_equal(mmcv.imrotate(img, 90), img_r)
301
        img_r = np.array([[1, 0, 0, 0], [2, 0, 0, 0]])
302
        assert_array_equal(mmcv.imrotate(img, 90, center=(0, 0)), img_r)
303
        img_r = np.array([[255, 6, 2, 255], [255, 7, 3, 255]])
304
        assert_array_equal(mmcv.imrotate(img, 90, border_value=255), img_r)
305
        img_r = np.array([[5, 1], [6, 2], [7, 3], [8, 4]])
306
307
308
309
        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)