mirror of https://github.com/open-mmlab/mmcv.git
910 lines
37 KiB
Python
910 lines
37 KiB
Python
# Copyright (c) OpenMMLab. All rights reserved.
|
|
import copy
|
|
import os.path as osp
|
|
from unittest.mock import Mock
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
import mmcv
|
|
from mmcv.transforms import (TRANSFORMS, Normalize, Pad, RandomFlip,
|
|
RandomResize, Resize)
|
|
from mmcv.transforms.base import BaseTransform
|
|
|
|
try:
|
|
import torch
|
|
except ModuleNotFoundError:
|
|
torch = None
|
|
else:
|
|
import torchvision
|
|
|
|
from numpy.testing import assert_array_almost_equal, assert_array_equal
|
|
from PIL import Image
|
|
|
|
|
|
class TestNormalize:
|
|
|
|
def test_normalize(self):
|
|
img_norm_cfg = dict(
|
|
mean=[123.675, 116.28, 103.53],
|
|
std=[58.395, 57.12, 57.375],
|
|
to_rgb=True)
|
|
transform = Normalize(**img_norm_cfg)
|
|
results = dict()
|
|
img = mmcv.imread(
|
|
osp.join(osp.dirname(__file__), '../data/color.jpg'), 'color')
|
|
original_img = copy.deepcopy(img)
|
|
results['img'] = img
|
|
results = transform(results)
|
|
mean = np.array(img_norm_cfg['mean'])
|
|
std = np.array(img_norm_cfg['std'])
|
|
converted_img = (original_img[..., ::-1] - mean) / std
|
|
assert np.allclose(results['img'], converted_img)
|
|
|
|
def test_repr(self):
|
|
img_norm_cfg = dict(
|
|
mean=[123.675, 116.28, 103.53],
|
|
std=[58.395, 57.12, 57.375],
|
|
to_rgb=True)
|
|
transform = Normalize(**img_norm_cfg)
|
|
assert repr(transform) == ('Normalize(mean=[123.675 116.28 103.53 ], '
|
|
'std=[58.395 57.12 57.375], to_rgb=True)')
|
|
|
|
|
|
class TestResize:
|
|
|
|
def test_resize(self):
|
|
data_info = dict(
|
|
img=np.random.random((1333, 800, 3)),
|
|
gt_seg_map=np.random.random((1333, 800, 3)),
|
|
gt_bboxes=np.array([[0, 0, 112, 112]]),
|
|
gt_keypoints=np.array([[[20, 50, 1]]]))
|
|
|
|
with pytest.raises(AssertionError):
|
|
transform = Resize(scale=None, scale_factor=None)
|
|
with pytest.raises(TypeError):
|
|
transform = Resize(scale_factor=[])
|
|
# test scale is int
|
|
transform = Resize(scale=2000)
|
|
results = transform(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (2000, 2000)
|
|
assert results['scale_factor'] == (2000 / 800, 2000 / 1333)
|
|
|
|
# test scale is tuple
|
|
transform = Resize(scale=(2000, 2000))
|
|
results = transform(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (2000, 2000)
|
|
assert results['scale_factor'] == (2000 / 800, 2000 / 1333)
|
|
|
|
# test scale_factor is float
|
|
transform = Resize(scale_factor=2.0)
|
|
results = transform(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (2666, 1600)
|
|
assert results['scale_factor'] == (2.0, 2.0)
|
|
|
|
# test scale_factor is tuple
|
|
transform = Resize(scale_factor=(1.5, 2))
|
|
results = transform(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (2666, 1200)
|
|
assert results['scale_factor'] == (1.5, 2)
|
|
|
|
# test keep_ratio is True
|
|
transform = Resize(scale=(2000, 2000), keep_ratio=True)
|
|
results = transform(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (2000, 1200)
|
|
assert results['scale'] == (1200, 2000)
|
|
assert results['scale_factor'] == (1200 / 800, 2000 / 1333)
|
|
|
|
# test resize_bboxes/seg/kps
|
|
transform = Resize(scale_factor=(1.5, 2))
|
|
results = transform(copy.deepcopy(data_info))
|
|
assert (results['gt_bboxes'] == np.array([[0, 0, 168, 224]])).all()
|
|
assert (results['gt_keypoints'] == np.array([[[30, 100, 1]]])).all()
|
|
assert results['gt_seg_map'].shape[:2] == (2666, 1200)
|
|
|
|
# test clip_object_border = False
|
|
data_info = dict(
|
|
img=np.random.random((300, 400, 3)),
|
|
gt_bboxes=np.array([[200, 150, 600, 450]]))
|
|
transform = Resize(scale=(200, 150), clip_object_border=False)
|
|
results = transform(data_info)
|
|
assert (results['gt_bboxes'] == np.array([100, 75, 300, 225])).all()
|
|
|
|
def test_repr(self):
|
|
transform = Resize(scale=(2000, 2000), keep_ratio=True)
|
|
assert repr(transform) == ('Resize(scale=(2000, 2000), '
|
|
'scale_factor=None, keep_ratio=True, '
|
|
'clip_object_border=True), backend=cv2), '
|
|
'interpolation=bilinear)')
|
|
|
|
|
|
class TestPad:
|
|
|
|
def test_pad(self):
|
|
# test size and size_divisor are both set
|
|
with pytest.raises(AssertionError):
|
|
Pad(size=(10, 10), size_divisor=2)
|
|
|
|
# test size and size_divisor are both None
|
|
with pytest.raises(AssertionError):
|
|
Pad(size=None, size_divisor=None)
|
|
|
|
# test size and pad_to_square are both None
|
|
with pytest.raises(AssertionError):
|
|
Pad(size=(10, 10), pad_to_square=True)
|
|
|
|
# test pad_val is not int or tuple
|
|
with pytest.raises(AssertionError):
|
|
Pad(size=(10, 10), pad_val=[])
|
|
|
|
# test padding_mode is not 'constant', 'edge', 'reflect' or 'symmetric'
|
|
with pytest.raises(AssertionError):
|
|
Pad(size=(10, 10), padding_mode='edg')
|
|
|
|
data_info = dict(
|
|
img=np.random.random((1333, 800, 3)),
|
|
gt_seg_map=np.random.random((1333, 800, 3)),
|
|
gt_bboxes=np.array([[0, 0, 112, 112]]),
|
|
gt_keypoints=np.array([[[20, 50, 1]]]))
|
|
|
|
# test pad img / gt_seg_map with size
|
|
trans = Pad(size=(1200, 2000))
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (2000, 1200)
|
|
assert results['gt_seg_map'].shape[:2] == (2000, 1200)
|
|
|
|
# test pad img/gt_seg_map with size_divisor
|
|
trans = Pad(size_divisor=11)
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (1342, 803)
|
|
assert results['gt_seg_map'].shape[:2] == (1342, 803)
|
|
|
|
# test pad img/gt_seg_map with pad_to_square
|
|
trans = Pad(pad_to_square=True)
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (1333, 1333)
|
|
assert results['gt_seg_map'].shape[:2] == (1333, 1333)
|
|
|
|
# test pad img/gt_seg_map with pad_to_square and size_divisor
|
|
trans = Pad(pad_to_square=True, size_divisor=11)
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (1342, 1342)
|
|
assert results['gt_seg_map'].shape[:2] == (1342, 1342)
|
|
|
|
# test pad img/gt_seg_map with pad_to_square and size_divisor
|
|
trans = Pad(pad_to_square=True, size_divisor=11)
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert results['img'].shape[:2] == (1342, 1342)
|
|
assert results['gt_seg_map'].shape[:2] == (1342, 1342)
|
|
|
|
# test padding_mode
|
|
new_img = np.ones((1333, 800, 3))
|
|
data_info['img'] = new_img
|
|
trans = Pad(pad_to_square=True, padding_mode='edge')
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert (results['img'] == np.ones((1333, 1333, 3))).all()
|
|
|
|
# test pad_val is dict
|
|
# test rgb image, size=(2000, 2000)
|
|
trans = Pad(
|
|
size=(2000, 2000),
|
|
pad_val=dict(img=(12, 12, 12), seg=(10, 10, 10)))
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert (results['img'][1333:2000, 800:2000, :] == 12).all()
|
|
assert (results['gt_seg_map'][1333:2000, 800:2000, :] == 10).all()
|
|
|
|
trans = Pad(size=(2000, 2000), pad_val=dict(img=(12, 12, 12)))
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert (results['img'][1333:2000, 800:2000, :] == 12).all()
|
|
assert (results['gt_seg_map'][1333:2000, 800:2000, :] == 255).all()
|
|
|
|
# test rgb image, pad_to_square=True
|
|
trans = Pad(
|
|
pad_to_square=True,
|
|
pad_val=dict(img=(12, 12, 12), seg=(10, 10, 10)))
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert (results['img'][:, 800:1333, :] == 12).all()
|
|
assert (results['gt_seg_map'][:, 800:1333, :] == 10).all()
|
|
|
|
trans = Pad(pad_to_square=True, pad_val=dict(img=(12, 12, 12)))
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert (results['img'][:, 800:1333, :] == 12).all()
|
|
assert (results['gt_seg_map'][:, 800:1333, :] == 255).all()
|
|
|
|
# test pad_val is int
|
|
# test rgb image
|
|
trans = Pad(size=(2000, 2000), pad_val=12)
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert (results['img'][1333:2000, 800:2000, :] == 12).all()
|
|
assert (results['gt_seg_map'][1333:2000, 800:2000, :] == 255).all()
|
|
# test gray image
|
|
new_img = np.random.random((1333, 800))
|
|
data_info['img'] = new_img
|
|
new_semantic_seg = np.random.random((1333, 800))
|
|
data_info['gt_seg_map'] = new_semantic_seg
|
|
trans = Pad(size=(2000, 2000), pad_val=12)
|
|
results = trans(copy.deepcopy(data_info))
|
|
assert (results['img'][1333:2000, 800:2000] == 12).all()
|
|
assert (results['gt_seg_map'][1333:2000, 800:2000] == 255).all()
|
|
|
|
def test_repr(self):
|
|
trans = Pad(pad_to_square=True, size_divisor=11, padding_mode='edge')
|
|
assert repr(trans) == (
|
|
'Pad(size=None, size_divisor=11, pad_to_square=True, '
|
|
"pad_val={'img': 0, 'seg': 255}), padding_mode=edge)")
|
|
|
|
|
|
class TestCenterCrop:
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
img = mmcv.imread(
|
|
osp.join(osp.dirname(__file__), '../data/color.jpg'), 'color')
|
|
cls.original_img = copy.deepcopy(img)
|
|
seg = np.random.randint(0, 19, (300, 400)).astype(np.uint8)
|
|
cls.gt_semantic_map = copy.deepcopy(seg)
|
|
|
|
@staticmethod
|
|
def reset_results(results, original_img, gt_semantic_map):
|
|
results['img'] = copy.deepcopy(original_img)
|
|
results['gt_seg_map'] = copy.deepcopy(gt_semantic_map)
|
|
results['gt_bboxes'] = np.array([[0, 0, 210, 160],
|
|
[200, 150, 400, 300]])
|
|
results['gt_keypoints'] = np.array([[[20, 50, 1]], [[200, 150, 1]],
|
|
[[300, 225, 1]]])
|
|
return results
|
|
|
|
@pytest.mark.skipif(
|
|
condition=torch is None, reason='No torch in current env')
|
|
def test_error(self):
|
|
# test assertion if size is smaller than 0
|
|
with pytest.raises(AssertionError):
|
|
transform = dict(type='CenterCrop', crop_size=-1)
|
|
TRANSFORMS.build(transform)
|
|
|
|
# test assertion if size is tuple but one value is smaller than 0
|
|
with pytest.raises(AssertionError):
|
|
transform = dict(type='CenterCrop', crop_size=(224, -1))
|
|
TRANSFORMS.build(transform)
|
|
|
|
# test assertion if size is tuple and len(size) < 2
|
|
with pytest.raises(AssertionError):
|
|
transform = dict(type='CenterCrop', crop_size=(224, ))
|
|
TRANSFORMS.build(transform)
|
|
|
|
# test assertion if size is tuple len(size) > 2
|
|
with pytest.raises(AssertionError):
|
|
transform = dict(type='CenterCrop', crop_size=(224, 224, 3))
|
|
TRANSFORMS.build(transform)
|
|
|
|
def test_repr(self):
|
|
# test repr
|
|
transform = dict(type='CenterCrop', crop_size=224)
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
assert isinstance(repr(center_crop_module), str)
|
|
|
|
def test_transform(self):
|
|
results = {}
|
|
self.reset_results(results, self.original_img, self.gt_semantic_map)
|
|
|
|
# test CenterCrop when size is int
|
|
transform = dict(type='CenterCrop', crop_size=224)
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == 224
|
|
assert results['width'] == 224
|
|
assert (results['img'] == self.original_img[38:262, 88:312, ...]).all()
|
|
assert (results['gt_seg_map'] == self.gt_semantic_map[38:262,
|
|
88:312]).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 122, 122], [112, 112, 224,
|
|
224]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[0, 12, 0]], [[112, 112, 1]], [[212, 187, 1]]])).all()
|
|
|
|
# test CenterCrop when size is tuple
|
|
transform = dict(type='CenterCrop', crop_size=(224, 224))
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == 224
|
|
assert results['width'] == 224
|
|
assert (results['img'] == self.original_img[38:262, 88:312, ...]).all()
|
|
assert (results['gt_seg_map'] == self.gt_semantic_map[38:262,
|
|
88:312]).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 122, 122], [112, 112, 224,
|
|
224]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[0, 12, 0]], [[112, 112, 1]], [[212, 187, 1]]])).all()
|
|
|
|
# test CenterCrop when crop_height != crop_width
|
|
transform = dict(type='CenterCrop', crop_size=(224, 256))
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == 256
|
|
assert results['width'] == 224
|
|
assert (results['img'] == self.original_img[22:278, 88:312, ...]).all()
|
|
assert (results['gt_seg_map'] == self.gt_semantic_map[22:278,
|
|
88:312]).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 122, 138], [112, 128, 224,
|
|
256]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[0, 28, 0]], [[112, 128, 1]], [[212, 203, 1]]])).all()
|
|
|
|
# test CenterCrop when crop_size is equal to img.shape
|
|
img_height, img_width, _ = self.original_img.shape
|
|
transform = dict(type='CenterCrop', crop_size=(img_width, img_height))
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == 300
|
|
assert results['width'] == 400
|
|
assert (results['img'] == self.original_img).all()
|
|
assert (results['gt_seg_map'] == self.gt_semantic_map).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 210, 160], [200, 150, 400,
|
|
300]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[20, 50, 1]], [[200, 150, 1]], [[300, 225, 1]]])).all()
|
|
|
|
# test CenterCrop when crop_size is larger than img.shape
|
|
transform = dict(
|
|
type='CenterCrop', crop_size=(img_width * 2, img_height * 2))
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == 300
|
|
assert results['width'] == 400
|
|
assert (results['img'] == self.original_img).all()
|
|
assert (results['gt_seg_map'] == self.gt_semantic_map).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 210, 160], [200, 150, 400,
|
|
300]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[20, 50, 1]], [[200, 150, 1]], [[300, 225, 1]]])).all()
|
|
|
|
# test with padding
|
|
transform = dict(
|
|
type='CenterCrop',
|
|
crop_size=(img_width // 2, img_height * 2),
|
|
auto_pad=True,
|
|
pad_cfg=dict(type='Pad', padding_mode='constant', pad_val=12))
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == 600
|
|
assert results['width'] == 200
|
|
assert results['img'].shape[:2] == results['gt_seg_map'].shape
|
|
assert (results['img'][300:600, 100:300, ...] == 12).all()
|
|
assert (results['gt_seg_map'][300:600, 100:300] == 255).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 110, 160], [100, 150, 200,
|
|
300]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[0, 50, 0]], [[100, 150, 1]], [[200, 225, 0]]])).all()
|
|
|
|
transform = dict(
|
|
type='CenterCrop',
|
|
crop_size=(img_width // 2, img_height * 2),
|
|
auto_pad=True,
|
|
pad_cfg=dict(
|
|
type='Pad',
|
|
padding_mode='constant',
|
|
pad_val=dict(img=13, seg=33)))
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == 600
|
|
assert results['width'] == 200
|
|
assert (results['img'][300:600, 100:300, ...] == 13).all()
|
|
assert (results['gt_seg_map'][300:600, 100:300] == 33).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 110, 160], [100, 150, 200,
|
|
300]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[0, 50, 0]], [[100, 150, 1]], [[200, 225, 0]]])).all()
|
|
|
|
# test CenterCrop when crop_width is smaller than img_width
|
|
transform = dict(
|
|
type='CenterCrop', crop_size=(img_width // 2, img_height))
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == img_height
|
|
assert results['width'] == img_width // 2
|
|
assert (results['img'] == self.original_img[:, 100:300, ...]).all()
|
|
assert (results['gt_seg_map'] == self.gt_semantic_map[:,
|
|
100:300]).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 110, 160], [100, 150, 200,
|
|
300]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[0, 50, 0]], [[100, 150, 1]], [[200, 225, 0]]])).all()
|
|
|
|
# test CenterCrop when crop_height is smaller than img_height
|
|
transform = dict(
|
|
type='CenterCrop', crop_size=(img_width, img_height // 2))
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
assert results['height'] == img_height // 2
|
|
assert results['width'] == img_width
|
|
assert (results['img'] == self.original_img[75:225, ...]).all()
|
|
assert (results['gt_seg_map'] == self.gt_semantic_map[75:225,
|
|
...]).all()
|
|
assert np.equal(results['gt_bboxes'],
|
|
np.array([[0, 0, 210, 85], [200, 75, 400,
|
|
150]])).all()
|
|
assert np.equal(
|
|
results['gt_keypoints'],
|
|
np.array([[[20, 0, 0]], [[200, 75, 1]], [[300, 150, 0]]])).all()
|
|
|
|
@pytest.mark.skipif(
|
|
condition=torch is None, reason='No torch in current env')
|
|
def test_torchvision_compare(self):
|
|
# compare results with torchvision
|
|
results = {}
|
|
transform = dict(type='CenterCrop', crop_size=224)
|
|
center_crop_module = TRANSFORMS.build(transform)
|
|
results = self.reset_results(results, self.original_img,
|
|
self.gt_semantic_map)
|
|
results = center_crop_module(results)
|
|
center_crop_module = torchvision.transforms.CenterCrop(size=224)
|
|
pil_img = Image.fromarray(self.original_img)
|
|
pil_seg = Image.fromarray(self.gt_semantic_map)
|
|
cropped_img = center_crop_module(pil_img)
|
|
cropped_img = np.array(cropped_img)
|
|
cropped_seg = center_crop_module(pil_seg)
|
|
cropped_seg = np.array(cropped_seg)
|
|
assert np.equal(results['img'], cropped_img).all()
|
|
assert np.equal(results['gt_seg_map'], cropped_seg).all()
|
|
|
|
|
|
class TestRandomGrayscale:
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
cls.img = np.random.rand(10, 10, 3).astype(np.float32)
|
|
|
|
def test_repr(self):
|
|
# test repr
|
|
transform = dict(
|
|
type='RandomGrayscale',
|
|
prob=1.,
|
|
channel_weights=(0.299, 0.587, 0.114),
|
|
keep_channels=True)
|
|
random_gray_scale_module = TRANSFORMS.build(transform)
|
|
assert isinstance(repr(random_gray_scale_module), str)
|
|
|
|
def test_error(self):
|
|
# test invalid argument
|
|
transform = dict(type='RandomGrayscale', prob=2)
|
|
with pytest.raises(AssertionError):
|
|
TRANSFORMS.build(transform)
|
|
|
|
def test_transform(self):
|
|
results = dict()
|
|
# test rgb2gray, return the grayscale image with prob = 1.
|
|
transform = dict(
|
|
type='RandomGrayscale',
|
|
prob=1.,
|
|
channel_weights=(0.299, 0.587, 0.114),
|
|
keep_channels=True)
|
|
|
|
random_gray_scale_module = TRANSFORMS.build(transform)
|
|
results['img'] = copy.deepcopy(self.img)
|
|
img = random_gray_scale_module(results)['img']
|
|
computed_gray = (
|
|
self.img[:, :, 0] * 0.299 + self.img[:, :, 1] * 0.587 +
|
|
self.img[:, :, 2] * 0.114)
|
|
for i in range(img.shape[2]):
|
|
assert_array_almost_equal(img[:, :, i], computed_gray, decimal=4)
|
|
assert img.shape == (10, 10, 3)
|
|
|
|
# test rgb2gray, return the original image with p=0.
|
|
transform = dict(type='RandomGrayscale', prob=0.)
|
|
random_gray_scale_module = TRANSFORMS.build(transform)
|
|
results['img'] = copy.deepcopy(self.img)
|
|
img = random_gray_scale_module(results)['img']
|
|
assert_array_equal(img, self.img)
|
|
assert img.shape == (10, 10, 3)
|
|
|
|
# test image with one channel
|
|
transform = dict(type='RandomGrayscale', prob=1.)
|
|
results['img'] = self.img[:, :, 0:1]
|
|
random_gray_scale_module = TRANSFORMS.build(transform)
|
|
img = random_gray_scale_module(results)['img']
|
|
assert_array_equal(img, self.img[:, :, 0:1])
|
|
assert img.shape == (10, 10, 1)
|
|
|
|
|
|
@TRANSFORMS.register_module()
|
|
class MockPackTaskInputs(BaseTransform):
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__()
|
|
|
|
def transform(self, results):
|
|
packed_results = dict(inputs=results['img'], data_sample=Mock())
|
|
return packed_results
|
|
|
|
|
|
class TestMultiScaleFlipAug:
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
cls.img = mmcv.imread(
|
|
osp.join(osp.dirname(__file__), '../data/color.jpg'), 'color')
|
|
cls.original_img = copy.deepcopy(cls.img)
|
|
|
|
def test_error(self):
|
|
# test assertion if img_scale is not tuple or list of tuple
|
|
with pytest.raises(AssertionError):
|
|
transform = dict(
|
|
type='MultiScaleFlipAug', img_scale=[1333, 800], transforms=[])
|
|
TRANSFORMS.build(transform)
|
|
|
|
# test assertion if flip_direction is not str or list of str
|
|
with pytest.raises(AssertionError):
|
|
transform = dict(
|
|
type='MultiScaleFlipAug',
|
|
img_scale=[(1333, 800)],
|
|
flip_direction=1,
|
|
transforms=[])
|
|
TRANSFORMS.build(transform)
|
|
|
|
@pytest.mark.skipif(
|
|
condition=torch is None, reason='No torch in current env')
|
|
def test_multi_scale_flip_aug(self):
|
|
# test with empty transforms
|
|
transform = dict(
|
|
type='MultiScaleFlipAug',
|
|
transforms=[dict(type='MockPackTaskInputs')],
|
|
img_scale=[(1333, 800), (800, 600), (640, 480)],
|
|
allow_flip=True,
|
|
flip_direction=['horizontal', 'vertical', 'diagonal'])
|
|
multi_scale_flip_aug_module = TRANSFORMS.build(transform)
|
|
results = dict()
|
|
results['img'] = copy.deepcopy(self.original_img)
|
|
packed_results = multi_scale_flip_aug_module(results)
|
|
assert len(packed_results['inputs']) == 12
|
|
|
|
# test with allow_flip=False
|
|
transform = dict(
|
|
type='MultiScaleFlipAug',
|
|
transforms=[dict(type='MockPackTaskInputs')],
|
|
img_scale=[(1333, 800), (800, 600), (640, 480)],
|
|
allow_flip=False,
|
|
flip_direction=['horizontal', 'vertical', 'diagonal'])
|
|
multi_scale_flip_aug_module = TRANSFORMS.build(transform)
|
|
results = dict()
|
|
results['img'] = copy.deepcopy(self.original_img)
|
|
packed_results = multi_scale_flip_aug_module(results)
|
|
assert len(packed_results['inputs']) == 3
|
|
|
|
# test with transforms
|
|
img_norm_cfg = dict(
|
|
mean=[123.675, 116.28, 103.53],
|
|
std=[58.395, 57.12, 57.375],
|
|
to_rgb=True)
|
|
transforms_cfg = [
|
|
dict(type='Normalize', **img_norm_cfg),
|
|
dict(type='Pad', size_divisor=32),
|
|
dict(type='ImageToTensor', keys=['img']),
|
|
dict(type='MockPackTaskInputs')
|
|
]
|
|
transform = dict(
|
|
type='MultiScaleFlipAug',
|
|
transforms=transforms_cfg,
|
|
img_scale=[(1333, 800), (800, 600), (640, 480)],
|
|
allow_flip=True,
|
|
flip_direction=['horizontal', 'vertical', 'diagonal'])
|
|
multi_scale_flip_aug_module = TRANSFORMS.build(transform)
|
|
results = dict()
|
|
results['img'] = copy.deepcopy(self.original_img)
|
|
packed_results = multi_scale_flip_aug_module(results)
|
|
assert len(packed_results['inputs']) == 12
|
|
|
|
# test with scale_factor
|
|
img_norm_cfg = dict(
|
|
mean=[123.675, 116.28, 103.53],
|
|
std=[58.395, 57.12, 57.375],
|
|
to_rgb=True)
|
|
transforms_cfg = [
|
|
dict(type='Normalize', **img_norm_cfg),
|
|
dict(type='Pad', size_divisor=32),
|
|
dict(type='ImageToTensor', keys=['img']),
|
|
dict(type='MockPackTaskInputs')
|
|
]
|
|
transform = dict(
|
|
type='MultiScaleFlipAug',
|
|
transforms=transforms_cfg,
|
|
scale_factor=[0.5, 1., 2.],
|
|
allow_flip=True,
|
|
flip_direction=['horizontal', 'vertical', 'diagonal'])
|
|
multi_scale_flip_aug_module = TRANSFORMS.build(transform)
|
|
results = dict()
|
|
results['img'] = copy.deepcopy(self.original_img)
|
|
packed_results = multi_scale_flip_aug_module(results)
|
|
assert len(packed_results['inputs']) == 12
|
|
|
|
# test no resize
|
|
img_norm_cfg = dict(
|
|
mean=[123.675, 116.28, 103.53],
|
|
std=[58.395, 57.12, 57.375],
|
|
to_rgb=True)
|
|
transforms_cfg = [
|
|
dict(type='Normalize', **img_norm_cfg),
|
|
dict(type='Pad', size_divisor=32),
|
|
dict(type='ImageToTensor', keys=['img']),
|
|
dict(type='MockPackTaskInputs')
|
|
]
|
|
transform = dict(
|
|
type='MultiScaleFlipAug',
|
|
transforms=transforms_cfg,
|
|
allow_flip=True,
|
|
flip_direction=['horizontal', 'vertical', 'diagonal'])
|
|
multi_scale_flip_aug_module = TRANSFORMS.build(transform)
|
|
results = dict()
|
|
results['img'] = copy.deepcopy(self.original_img)
|
|
packed_results = multi_scale_flip_aug_module(results)
|
|
assert len(packed_results['inputs']) == 4
|
|
|
|
|
|
class TestRandomChoiceResize:
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
cls.img = mmcv.imread(
|
|
osp.join(osp.dirname(__file__), '../data/color.jpg'), 'color')
|
|
cls.original_img = copy.deepcopy(cls.img)
|
|
|
|
def reset_results(self, results):
|
|
results['img'] = copy.deepcopy(self.original_img)
|
|
results['gt_seg_map'] = copy.deepcopy(self.original_img)
|
|
|
|
def test_repr(self):
|
|
# test repr
|
|
transform = dict(
|
|
type='RandomChoiceResize', scales=[(1333, 800), (1333, 600)])
|
|
random_multiscale_resize = TRANSFORMS.build(transform)
|
|
assert isinstance(repr(random_multiscale_resize), str)
|
|
|
|
def test_error(self):
|
|
# test assertion if size is smaller than 0
|
|
with pytest.raises(AssertionError):
|
|
transform = dict(type='RandomChoiceResize', scales=[0.5, 1, 2])
|
|
TRANSFORMS.build(transform)
|
|
|
|
def test_random_multiscale_resize(self):
|
|
results = dict()
|
|
# test with one scale
|
|
transform = dict(type='RandomChoiceResize', scales=[(1333, 800)])
|
|
random_multiscale_resize = TRANSFORMS.build(transform)
|
|
self.reset_results(results)
|
|
results = random_multiscale_resize(results)
|
|
assert results['img'].shape == (800, 1333, 3)
|
|
|
|
# test with multi scales
|
|
_scale_choice = [(1333, 800), (1333, 600)]
|
|
transform = dict(type='RandomChoiceResize', scales=_scale_choice)
|
|
random_multiscale_resize = TRANSFORMS.build(transform)
|
|
self.reset_results(results)
|
|
results = random_multiscale_resize(results)
|
|
assert (results['img'].shape[1],
|
|
results['img'].shape[0]) in _scale_choice
|
|
|
|
# test keep_ratio
|
|
transform = dict(
|
|
type='RandomChoiceResize',
|
|
scales=[(900, 600)],
|
|
resize_cfg=dict(type='Resize', keep_ratio=True))
|
|
random_multiscale_resize = TRANSFORMS.build(transform)
|
|
self.reset_results(results)
|
|
_input_ratio = results['img'].shape[0] / results['img'].shape[1]
|
|
results = random_multiscale_resize(results)
|
|
_output_ratio = results['img'].shape[0] / results['img'].shape[1]
|
|
assert_array_almost_equal(_input_ratio, _output_ratio)
|
|
|
|
# test clip_object_border
|
|
gt_bboxes = [[200, 150, 600, 450]]
|
|
transform = dict(
|
|
type='RandomChoiceResize',
|
|
scales=[(200, 150)],
|
|
resize_cfg=dict(type='Resize', clip_object_border=True))
|
|
random_multiscale_resize = TRANSFORMS.build(transform)
|
|
self.reset_results(results)
|
|
results['gt_bboxes'] = np.array(gt_bboxes)
|
|
results = random_multiscale_resize(results)
|
|
assert results['img'].shape == (150, 200, 3)
|
|
assert np.equal(results['gt_bboxes'], np.array([[100, 75, 200,
|
|
150]])).all()
|
|
|
|
transform = dict(
|
|
type='RandomChoiceResize',
|
|
scales=[(200, 150)],
|
|
resize_cfg=dict(type='Resize', clip_object_border=False))
|
|
random_multiscale_resize = TRANSFORMS.build(transform)
|
|
self.reset_results(results)
|
|
results['gt_bboxes'] = np.array(gt_bboxes)
|
|
results = random_multiscale_resize(results)
|
|
assert results['img'].shape == (150, 200, 3)
|
|
assert np.equal(results['gt_bboxes'], np.array([[100, 75, 300,
|
|
225]])).all()
|
|
|
|
|
|
class TestRandomFlip:
|
|
|
|
def test_init(self):
|
|
|
|
# prob is float
|
|
TRANSFORMS = RandomFlip(0.1)
|
|
assert TRANSFORMS.prob == 0.1
|
|
|
|
# prob is None
|
|
with pytest.raises(ValueError):
|
|
TRANSFORMS = RandomFlip(None)
|
|
assert TRANSFORMS.prob is None
|
|
|
|
# prob is a list
|
|
TRANSFORMS = RandomFlip([0.1, 0.2], ['horizontal', 'vertical'])
|
|
assert len(TRANSFORMS.prob) == 2
|
|
assert len(TRANSFORMS.direction) == 2
|
|
|
|
# direction is an invalid type
|
|
with pytest.raises(ValueError):
|
|
TRANSFORMS = RandomFlip(0.1, 1)
|
|
|
|
# prob is an invalid type
|
|
with pytest.raises(ValueError):
|
|
TRANSFORMS = RandomFlip('0.1')
|
|
|
|
def test_transform(self):
|
|
|
|
results = {
|
|
'img': np.random.random((224, 224, 3)),
|
|
'gt_bboxes': np.array([[0, 1, 100, 101]]),
|
|
'gt_keypoints': np.array([[[100, 100, 1.0]]]),
|
|
'gt_seg_map': np.random.random((224, 224, 3))
|
|
}
|
|
|
|
# horizontal flip
|
|
TRANSFORMS = RandomFlip([1.0], ['horizontal'])
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
assert (results_update['gt_bboxes'] == np.array([[124, 1, 224,
|
|
101]])).all()
|
|
|
|
# diagnal flip
|
|
TRANSFORMS = RandomFlip([1.0], ['diagonal'])
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
assert (results_update['gt_bboxes'] == np.array([[124, 123, 224,
|
|
223]])).all()
|
|
|
|
# vertical flip
|
|
TRANSFORMS = RandomFlip([1.0], ['vertical'])
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
assert (results_update['gt_bboxes'] == np.array([[0, 123, 100,
|
|
223]])).all()
|
|
|
|
# horizontal flip when direction is None
|
|
TRANSFORMS = RandomFlip(1.0)
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
assert (results_update['gt_bboxes'] == np.array([[124, 1, 224,
|
|
101]])).all()
|
|
|
|
TRANSFORMS = RandomFlip(0.0)
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
assert (results_update['gt_bboxes'] == np.array([[0, 1, 100,
|
|
101]])).all()
|
|
|
|
# flip direction is invalid in bbox flip
|
|
with pytest.raises(ValueError):
|
|
TRANSFORMS = RandomFlip(1.0)
|
|
results_update = TRANSFORMS.flip_bbox(results['gt_bboxes'],
|
|
(224, 224), 'invalid')
|
|
|
|
# flip direction is invalid in keypoints flip
|
|
with pytest.raises(ValueError):
|
|
TRANSFORMS = RandomFlip(1.0)
|
|
results_update = TRANSFORMS.flip_keypoints(results['gt_keypoints'],
|
|
(224, 224), 'invalid')
|
|
|
|
def test_repr(self):
|
|
TRANSFORMS = RandomFlip(0.1)
|
|
TRANSFORMS_str = str(TRANSFORMS)
|
|
assert isinstance(TRANSFORMS_str, str)
|
|
|
|
|
|
class TestRandomResize:
|
|
|
|
def test_init(self):
|
|
TRANSFORMS = RandomResize(
|
|
(224, 224),
|
|
(1.0, 2.0),
|
|
)
|
|
assert TRANSFORMS.scale == (224, 224)
|
|
|
|
def test_repr(self):
|
|
TRANSFORMS = RandomResize(
|
|
(224, 224),
|
|
(1.0, 2.0),
|
|
)
|
|
TRANSFORMS_str = str(TRANSFORMS)
|
|
assert isinstance(TRANSFORMS_str, str)
|
|
|
|
def test_transform(self):
|
|
|
|
# choose target scale from init when override is True
|
|
results = {}
|
|
TRANSFORMS = RandomResize((224, 224), (1.0, 2.0))
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
assert results_update['scale'][0] >= 224 and results_update['scale'][
|
|
0] <= 448
|
|
assert results_update['scale'][1] >= 224 and results_update['scale'][
|
|
1] <= 448
|
|
|
|
# keep ratio is True
|
|
results = {
|
|
'img': np.random.random((224, 224, 3)),
|
|
'gt_seg_map': np.random.random((224, 224, 3)),
|
|
'gt_bboxes': np.array([[0, 0, 112, 112]]),
|
|
'gt_keypoints': np.array([[[112, 112]]])
|
|
}
|
|
|
|
TRANSFORMS = RandomResize(
|
|
(224, 224), (1.0, 2.0),
|
|
resize_cfg=dict(type='Resize', keep_ratio=True))
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
assert 224 <= results_update['img_shape'][0]
|
|
assert 448 >= results_update['img_shape'][0]
|
|
assert 224 <= results_update['img_shape'][1]
|
|
assert 448 >= results_update['img_shape'][1]
|
|
assert results_update['keep_ratio']
|
|
assert results['gt_bboxes'][0][2] >= 112
|
|
assert results['gt_bboxes'][0][2] <= 112
|
|
|
|
# keep ratio is False
|
|
TRANSFORMS = RandomResize(
|
|
(224, 224), (1.0, 2.0),
|
|
resize_cfg=dict(type='Resize', keep_ratio=False))
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
|
|
# choose target scale from init when override is False and scale is a
|
|
# list of tuples
|
|
results = {}
|
|
TRANSFORMS = RandomResize([(224, 448), (112, 224)],
|
|
resize_cfg=dict(
|
|
type='Resize', keep_ratio=True))
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|
|
assert results_update['scale'][0] >= 224 and results_update['scale'][
|
|
0] <= 448
|
|
assert results_update['scale'][1] >= 112 and results_update['scale'][
|
|
1] <= 224
|
|
|
|
# the type of scale is invalid in init
|
|
with pytest.raises(NotImplementedError):
|
|
results = {}
|
|
TRANSFORMS = RandomResize([(224, 448), [112, 224]],
|
|
resize_cfg=dict(
|
|
type='Resize', keep_ratio=True))
|
|
results_update = TRANSFORMS.transform(copy.deepcopy(results))
|