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

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

125
    def test_imresize_like(self):
126
        a = np.zeros((100, 200, 3))
127
        resized_img = mmcv.imresize_like(self.img, a)
128
129
        assert resized_img.shape == (100, 200, 3)

130
131
132
    def test_imrescale(self):
        # rescale by a certain factor
        resized_img = mmcv.imrescale(self.img, 1.5)
133
        assert resized_img.shape == (450, 600, 3)
134
        resized_img = mmcv.imrescale(self.img, 0.934)
135
136
        assert resized_img.shape == (280, 374, 3)

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

        # test exceptions
152
        with pytest.raises(ValueError):
153
154
155
            mmcv.imrescale(self.img, -0.5)
        with pytest.raises(TypeError):
            mmcv.imrescale(self.img, [100, 100])
156

Kai Chen's avatar
Kai Chen committed
157
    def test_imflip(self):
Kai Chen's avatar
Kai Chen committed
158
        # test horizontal flip (color image)
Kai Chen's avatar
Kai Chen committed
159
160
        img = np.random.rand(80, 60, 3)
        h, w, c = img.shape
Kai Chen's avatar
Kai Chen committed
161
162
        flipped_img = mmcv.imflip(img)
        assert flipped_img.shape == img.shape
Kai Chen's avatar
Kai Chen committed
163
164
165
        for i in range(h):
            for j in range(w):
                for k in range(c):
Kai Chen's avatar
Kai Chen committed
166
167
168
169
                    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
170
171
172
        for i in range(h):
            for j in range(w):
                for k in range(c):
Kai Chen's avatar
Kai Chen committed
173
174
                    assert flipped_img[i, j, k] == img[h - 1 - i, j, k]
        # test horizontal flip (grayscale image)
Kai Chen's avatar
Kai Chen committed
175
        img = np.random.rand(80, 60)
Kai Chen's avatar
Kai Chen committed
176
177
178
        h, w = img.shape
        flipped_img = mmcv.imflip(img)
        assert flipped_img.shape == img.shape
Kai Chen's avatar
Kai Chen committed
179
180
        for i in range(h):
            for j in range(w):
Kai Chen's avatar
Kai Chen committed
181
182
183
184
                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
185
186
        for i in range(h):
            for j in range(w):
Kai Chen's avatar
Kai Chen committed
187
                assert flipped_img[i, j] == img[h - 1 - i, j]
Kai Chen's avatar
Kai Chen committed
188

189
    def test_imcrop(self):
190
191
192
193
194
195
196
        # 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
197

198
        # crop one bbox
199
200
        patch = mmcv.imcrop(self.img, bboxes[0, :])
        patches = mmcv.imcrop(self.img, bboxes[[0], :])
201
202
203
204
205
206
        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)
207

208
        # crop with no scaling and padding
209
        patches = mmcv.imcrop(self.img, bboxes)
210
211
212
213
        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)
214

215
        # crop with scaling and no padding
216
        patches = mmcv.imcrop(self.img, bboxes, 1.2)
217
218
219
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/scale_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)
220

221
        # crop with scaling and padding
222
        patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=[255, 255, 0])
223
224
225
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/pad_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)
226
        patches = mmcv.imcrop(self.img, bboxes, 1.2, pad_fill=0)
227
228
229
230
        for i in range(len(patches)):
            ref_patch = np.load(patch_path + '/pad0_{}.npy'.format(i))
            self.assert_img_equal(patches[i], ref_patch)

231
    def test_impad(self):
232
        img = np.random.rand(10, 10, 3).astype(np.float32)
233
        padded_img = mmcv.impad(img, (15, 12), 0)
234
235
236
237
238
        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:, :])
239

240
        img = np.random.randint(256, size=(10, 10, 3)).astype('uint8')
241
        padded_img = mmcv.impad(img, (15, 12, 3), [100, 110, 120])
242
243
244
245
246
247
248
        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:, :])
249

250
        with pytest.raises(AssertionError):
251
            mmcv.impad(img, (15, ), 0)
252
        with pytest.raises(AssertionError):
253
            mmcv.impad(img, (5, 5), 0)
254
        with pytest.raises(AssertionError):
255
            mmcv.impad(img, (5, 5), [0, 1])
256

Kai Chen's avatar
Kai Chen committed
257
258
259
260
261
262
263
264
265
266
267
    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)

268
    def test_imrotate(self):
269
        img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8)
270
        assert_array_equal(mmcv.imrotate(img, 0), img)
271
        img_r = np.array([[7, 4, 1], [8, 5, 2], [9, 6, 3]])
272
        assert_array_equal(mmcv.imrotate(img, 90), img_r)
273
        img_r = np.array([[3, 6, 9], [2, 5, 8], [1, 4, 7]])
274
        assert_array_equal(mmcv.imrotate(img, -90), img_r)
275
276
277

        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]])
278
        assert_array_equal(mmcv.imrotate(img, 90), img_r)
279
        img_r = np.array([[1, 0, 0, 0], [2, 0, 0, 0]])
280
        assert_array_equal(mmcv.imrotate(img, 90, center=(0, 0)), img_r)
281
        img_r = np.array([[255, 6, 2, 255], [255, 7, 3, 255]])
282
        assert_array_equal(mmcv.imrotate(img, 90, border_value=255), img_r)
283
        img_r = np.array([[5, 1], [6, 2], [7, 3], [8, 4]])
284
285
286
287
        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
288
289
290
291
292
293
294

    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)