test_image.py 13.5 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
        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)

Gu Wang's avatar
Gu Wang committed
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    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)

144
145
    def test_imresize(self):
        resized_img = mmcv.imresize(self.img, (1000, 600))
146
        assert resized_img.shape == (600, 1000, 3)
147
148
        resized_img, w_scale, h_scale = mmcv.imresize(self.img, (1000, 600),
                                                      True)
149
150
151
        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']:
152
153
            resized_img = mmcv.imresize(
                self.img, (1000, 600), interpolation=mode)
154
155
            assert resized_img.shape == (600, 1000, 3)

156
    def test_imresize_like(self):
157
        a = np.zeros((100, 200, 3))
158
        resized_img = mmcv.imresize_like(self.img, a)
159
160
        assert resized_img.shape == (100, 200, 3)

161
162
163
    def test_imrescale(self):
        # rescale by a certain factor
        resized_img = mmcv.imrescale(self.img, 1.5)
164
        assert resized_img.shape == (450, 600, 3)
165
        resized_img = mmcv.imrescale(self.img, 0.934)
166
167
        assert resized_img.shape == (280, 374, 3)

168
        # rescale by a certain max_size
169
        # resize (400, 300) to (max_1000, max_600)
170
        resized_img = mmcv.imrescale(self.img, (1000, 600))
171
        assert resized_img.shape == (600, 800, 3)
172
173
        resized_img, scale = mmcv.imrescale(
            self.img, (1000, 600), return_scale=True)
174
175
        assert resized_img.shape == (600, 800, 3) and scale == 2.0
        # resize (400, 300) to (max_200, max_180)
176
        resized_img = mmcv.imrescale(self.img, (180, 200))
177
        assert resized_img.shape == (150, 200, 3)
178
179
        resized_img, scale = mmcv.imrescale(
            self.img, (180, 200), return_scale=True)
180
        assert resized_img.shape == (150, 200, 3) and scale == 0.5
181
182

        # test exceptions
183
        with pytest.raises(ValueError):
184
185
186
            mmcv.imrescale(self.img, -0.5)
        with pytest.raises(TypeError):
            mmcv.imrescale(self.img, [100, 100])
187

Kai Chen's avatar
Kai Chen committed
188
    def test_imflip(self):
Kai Chen's avatar
Kai Chen committed
189
        # test horizontal flip (color image)
Kai Chen's avatar
Kai Chen committed
190
191
        img = np.random.rand(80, 60, 3)
        h, w, c = img.shape
Kai Chen's avatar
Kai Chen committed
192
193
        flipped_img = mmcv.imflip(img)
        assert flipped_img.shape == img.shape
Kai Chen's avatar
Kai Chen committed
194
195
196
        for i in range(h):
            for j in range(w):
                for k in range(c):
Kai Chen's avatar
Kai Chen committed
197
198
199
200
                    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
201
202
203
        for i in range(h):
            for j in range(w):
                for k in range(c):
Kai Chen's avatar
Kai Chen committed
204
205
                    assert flipped_img[i, j, k] == img[h - 1 - i, j, k]
        # test horizontal flip (grayscale image)
Kai Chen's avatar
Kai Chen committed
206
        img = np.random.rand(80, 60)
Kai Chen's avatar
Kai Chen committed
207
208
209
        h, w = img.shape
        flipped_img = mmcv.imflip(img)
        assert flipped_img.shape == img.shape
Kai Chen's avatar
Kai Chen committed
210
211
        for i in range(h):
            for j in range(w):
Kai Chen's avatar
Kai Chen committed
212
213
214
215
                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
216
217
        for i in range(h):
            for j in range(w):
Kai Chen's avatar
Kai Chen committed
218
                assert flipped_img[i, j] == img[h - 1 - i, j]
Kai Chen's avatar
Kai Chen committed
219

220
    def test_imcrop(self):
221
222
223
224
225
226
227
        # 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
228

229
        # crop one bbox
230
231
        patch = mmcv.imcrop(self.img, bboxes[0, :])
        patches = mmcv.imcrop(self.img, bboxes[[0], :])
232
233
234
235
236
237
        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)
238

239
        # crop with no scaling and padding
240
        patches = mmcv.imcrop(self.img, bboxes)
241
242
243
244
        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)
245

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

252
        # crop with scaling and padding
253
        patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=[255, 255, 0])
254
255
256
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/pad_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)
257
        patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=0)
258
259
260
261
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/pad0_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)

262
    def test_impad(self):
263
        img = np.random.rand(10, 10, 3).astype(np.float32)
264
        padded_img = mmcv.impad(img, (15, 12), 0)
265
266
267
268
269
        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:, :])
270

271
        img = np.random.randint(256, size=(10, 10, 3)).astype('uint8')
272
        padded_img = mmcv.impad(img, (15, 12, 3), [100, 110, 120])
273
274
275
276
277
278
279
        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:, :])
280

281
        with pytest.raises(AssertionError):
282
            mmcv.impad(img, (15, ), 0)
283
        with pytest.raises(AssertionError):
284
            mmcv.impad(img, (5, 5), 0)
285
        with pytest.raises(AssertionError):
286
            mmcv.impad(img, (5, 5), [0, 1])
287

Kai Chen's avatar
Kai Chen committed
288
289
290
291
292
293
294
295
296
297
298
    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)

299
    def test_imrotate(self):
300
        img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8)
301
        assert_array_equal(mmcv.imrotate(img, 0), img)
302
        img_r = np.array([[7, 4, 1], [8, 5, 2], [9, 6, 3]])
303
        assert_array_equal(mmcv.imrotate(img, 90), img_r)
304
        img_r = np.array([[3, 6, 9], [2, 5, 8], [1, 4, 7]])
305
        assert_array_equal(mmcv.imrotate(img, -90), img_r)
306
307
308

        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]])
309
        assert_array_equal(mmcv.imrotate(img, 90), img_r)
310
        img_r = np.array([[1, 0, 0, 0], [2, 0, 0, 0]])
311
        assert_array_equal(mmcv.imrotate(img, 90, center=(0, 0)), img_r)
312
        img_r = np.array([[255, 6, 2, 255], [255, 7, 3, 255]])
313
        assert_array_equal(mmcv.imrotate(img, 90, border_value=255), img_r)
314
        img_r = np.array([[5, 1], [6, 2], [7, 3], [8, 4]])
315
316
317
318
        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
319
320
321
322
323
324
325

    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)