|
- import copy
-
- import numpy as np
- import pytest
- import torch
-
- from mmdet.core import GeneralData, InstanceData
-
-
- def _equal(a, b):
- if isinstance(a, (torch.Tensor, np.ndarray)):
- return (a == b).all()
- else:
- return a == b
-
-
- def test_general_data():
-
- # test init
- meta_info = dict(
- img_size=[256, 256],
- path='dadfaff',
- scale_factor=np.array([1.5, 1.5]),
- img_shape=torch.rand(4))
-
- data = dict(
- bboxes=torch.rand(4, 4),
- labels=torch.rand(4),
- masks=np.random.rand(4, 2, 2))
-
- instance_data = GeneralData(meta_info=meta_info)
- assert 'img_size' in instance_data
- assert instance_data.img_size == [256, 256]
- assert instance_data['img_size'] == [256, 256]
- assert 'path' in instance_data
- assert instance_data.path == 'dadfaff'
-
- # test nice_repr
- repr_instance_data = instance_data.new(data=data)
- nice_repr = str(repr_instance_data)
- for line in nice_repr.split('\n'):
- if 'masks' in line:
- assert 'shape' in line
- assert '(4, 2, 2)' in line
- if 'bboxes' in line:
- assert 'shape' in line
- assert 'torch.Size([4, 4])' in line
- if 'path' in line:
- assert 'dadfaff' in line
- if 'scale_factor' in line:
- assert '[1.5 1.5]' in line
-
- instance_data = GeneralData(
- meta_info=meta_info, data=dict(bboxes=torch.rand(5)))
- assert 'bboxes' in instance_data
- assert len(instance_data.bboxes) == 5
-
- # data should be a dict
- with pytest.raises(AssertionError):
- GeneralData(data=1)
-
- # test set data
- instance_data = GeneralData()
- instance_data.set_data(data)
- assert 'bboxes' in instance_data
- assert len(instance_data.bboxes) == 4
- assert 'masks' in instance_data
- assert len(instance_data.masks) == 4
- # data should be a dict
- with pytest.raises(AssertionError):
- instance_data.set_data(data=1)
-
- # test set_meta
- instance_data = GeneralData()
- instance_data.set_meta_info(meta_info)
- assert 'img_size' in instance_data
- assert instance_data.img_size == [256, 256]
- assert instance_data['img_size'] == [256, 256]
- assert 'path' in instance_data
- assert instance_data.path == 'dadfaff'
- # can skip same value when overwrite
- instance_data.set_meta_info(meta_info)
-
- # meta should be a dict
- with pytest.raises(AssertionError):
- instance_data.set_meta_info(meta_info='fjhka')
-
- # attribute in `_meta_info_field` is immutable once initialized
- instance_data.set_meta_info(meta_info)
- # meta should be immutable
- with pytest.raises(KeyError):
- instance_data.set_meta_info(dict(img_size=[254, 251]))
- with pytest.raises(KeyError):
- duplicate_meta_info = copy.deepcopy(meta_info)
- duplicate_meta_info['path'] = 'dada'
- instance_data.set_meta_info(duplicate_meta_info)
- with pytest.raises(KeyError):
- duplicate_meta_info = copy.deepcopy(meta_info)
- duplicate_meta_info['scale_factor'] = np.array([1.5, 1.6])
- instance_data.set_meta_info(duplicate_meta_info)
-
- # test new_instance_data
- instance_data = GeneralData(meta_info)
- new_instance_data = instance_data.new()
- for k, v in instance_data.meta_info_items():
- assert k in new_instance_data
- _equal(v, new_instance_data[k])
-
- instance_data = GeneralData(meta_info, data=data)
- temp_meta = copy.deepcopy(meta_info)
- temp_data = copy.deepcopy(data)
- temp_data['time'] = '12212'
- temp_meta['img_norm'] = np.random.random(3)
-
- new_instance_data = instance_data.new(meta_info=temp_meta, data=temp_data)
- for k, v in new_instance_data.meta_info_items():
- if k in instance_data:
- _equal(v, instance_data[k])
- else:
- assert _equal(v, temp_meta[k])
- assert k == 'img_norm'
-
- for k, v in new_instance_data.items():
- if k in instance_data:
- _equal(v, instance_data[k])
- else:
- assert k == 'time'
- assert _equal(v, temp_data[k])
-
- # test keys
- instance_data = GeneralData(meta_info, data=dict(bboxes=10))
- assert 'bboxes' in instance_data.keys()
- instance_data.b = 10
- assert 'b' in instance_data
-
- # test meta keys
- instance_data = GeneralData(meta_info, data=dict(bboxes=10))
- assert 'path' in instance_data.meta_info_keys()
- assert len(instance_data.meta_info_keys()) == len(meta_info)
- instance_data.set_meta_info(dict(workdir='fafaf'))
- assert 'workdir' in instance_data
- assert len(instance_data.meta_info_keys()) == len(meta_info) + 1
-
- # test values
- instance_data = GeneralData(meta_info, data=dict(bboxes=10))
- assert 10 in instance_data.values()
- assert len(instance_data.values()) == 1
-
- # test meta values
- instance_data = GeneralData(meta_info, data=dict(bboxes=10))
- # torch 1.3 eq() can not compare str and tensor
- from mmdet import digit_version
- if digit_version(torch.__version__) >= [1, 4]:
- assert 'dadfaff' in instance_data.meta_info_values()
- assert len(instance_data.meta_info_values()) == len(meta_info)
-
- # test items
- instance_data = GeneralData(data=data)
- for k, v in instance_data.items():
- assert k in data
- assert _equal(v, data[k])
-
- # test meta_info_items
- instance_data = GeneralData(meta_info=meta_info)
- for k, v in instance_data.meta_info_items():
- assert k in meta_info
- assert _equal(v, meta_info[k])
-
- # test __setattr__
- new_instance_data = GeneralData(data=data)
- new_instance_data.mask = torch.rand(3, 4, 5)
- new_instance_data.bboxes = torch.rand(2, 4)
- assert 'mask' in new_instance_data
- assert len(new_instance_data.mask) == 3
- assert len(new_instance_data.bboxes) == 2
-
- # test instance_data_field has been updated
- assert 'mask' in new_instance_data._data_fields
- assert 'bboxes' in new_instance_data._data_fields
-
- for k in data:
- assert k in new_instance_data._data_fields
-
- # '_meta_info_field', '_data_fields' is immutable.
- with pytest.raises(AttributeError):
- new_instance_data._data_fields = None
- with pytest.raises(AttributeError):
- new_instance_data._meta_info_fields = None
- with pytest.raises(AttributeError):
- del new_instance_data._data_fields
- with pytest.raises(AttributeError):
- del new_instance_data._meta_info_fields
-
- # key in _meta_info_field is immutable
- new_instance_data.set_meta_info(meta_info)
- with pytest.raises(KeyError):
- del new_instance_data.img_size
- with pytest.raises(KeyError):
- del new_instance_data.scale_factor
- for k in new_instance_data.meta_info_keys():
- with pytest.raises(AttributeError):
- new_instance_data[k] = None
-
- # test __delattr__
- # test key can be removed in instance_data_field
- assert 'mask' in new_instance_data._data_fields
- assert 'mask' in new_instance_data.keys()
- assert 'mask' in new_instance_data
- assert hasattr(new_instance_data, 'mask')
- del new_instance_data.mask
- assert 'mask' not in new_instance_data.keys()
- assert 'mask' not in new_instance_data
- assert 'mask' not in new_instance_data._data_fields
- assert not hasattr(new_instance_data, 'mask')
-
- # tset __delitem__
- new_instance_data.mask = torch.rand(1, 2, 3)
- assert 'mask' in new_instance_data._data_fields
- assert 'mask' in new_instance_data
- assert hasattr(new_instance_data, 'mask')
- del new_instance_data['mask']
- assert 'mask' not in new_instance_data
- assert 'mask' not in new_instance_data._data_fields
- assert 'mask' not in new_instance_data
- assert not hasattr(new_instance_data, 'mask')
-
- # test __setitem__
- new_instance_data['mask'] = torch.rand(1, 2, 3)
- assert 'mask' in new_instance_data._data_fields
- assert 'mask' in new_instance_data.keys()
- assert hasattr(new_instance_data, 'mask')
-
- # test data_fields has been updated
- assert 'mask' in new_instance_data.keys()
- assert 'mask' in new_instance_data._data_fields
-
- # '_meta_info_field', '_data_fields' is immutable.
- with pytest.raises(AttributeError):
- del new_instance_data['_data_fields']
- with pytest.raises(AttributeError):
- del new_instance_data['_meta_info_field']
-
- # test __getitem__
- new_instance_data.mask is new_instance_data['mask']
-
- # test get
- assert new_instance_data.get('mask') is new_instance_data.mask
- assert new_instance_data.get('none_attribute', None) is None
- assert new_instance_data.get('none_attribute', 1) == 1
-
- # test pop
- mask = new_instance_data.mask
- assert new_instance_data.pop('mask') is mask
- assert new_instance_data.pop('mask', None) is None
- assert new_instance_data.pop('mask', 1) == 1
-
- # '_meta_info_field', '_data_fields' is immutable.
- with pytest.raises(KeyError):
- new_instance_data.pop('_data_fields')
- with pytest.raises(KeyError):
- new_instance_data.pop('_meta_info_field')
- # attribute in `_meta_info_field` is immutable
- with pytest.raises(KeyError):
- new_instance_data.pop('img_size')
- # test pop attribute in instance_data_filed
- new_instance_data['mask'] = torch.rand(1, 2, 3)
- new_instance_data.pop('mask')
- # test data_field has been updated
- assert 'mask' not in new_instance_data
- assert 'mask' not in new_instance_data._data_fields
- assert 'mask' not in new_instance_data
-
- # test_keys
- new_instance_data.mask = torch.ones(1, 2, 3)
- 'mask' in new_instance_data.keys()
- has_flag = False
- for key in new_instance_data.keys():
- if key == 'mask':
- has_flag = True
- assert has_flag
-
- # test values
- assert len(list(new_instance_data.keys())) == len(
- list(new_instance_data.values()))
- mask = new_instance_data.mask
- has_flag = False
- for value in new_instance_data.values():
- if value is mask:
- has_flag = True
- assert has_flag
-
- # test items
- assert len(list(new_instance_data.keys())) == len(
- list(new_instance_data.items()))
- mask = new_instance_data.mask
- has_flag = False
- for key, value in new_instance_data.items():
- if value is mask:
- assert key == 'mask'
- has_flag = True
- assert has_flag
-
- # test device
- new_instance_data = GeneralData()
- if torch.cuda.is_available():
- newnew_instance_data = new_instance_data.new()
- devices = ('cpu', 'cuda')
- for i in range(10):
- device = devices[i % 2]
- newnew_instance_data[f'{i}'] = torch.rand(1, 2, 3, device=device)
- newnew_instance_data = newnew_instance_data.cpu()
- for value in newnew_instance_data.values():
- assert not value.is_cuda
- newnew_instance_data = new_instance_data.new()
- devices = ('cuda', 'cpu')
- for i in range(10):
- device = devices[i % 2]
- newnew_instance_data[f'{i}'] = torch.rand(1, 2, 3, device=device)
- newnew_instance_data = newnew_instance_data.cuda()
- for value in newnew_instance_data.values():
- assert value.is_cuda
- # test to
- double_instance_data = instance_data.new()
- double_instance_data.long = torch.LongTensor(1, 2, 3, 4)
- double_instance_data.bool = torch.BoolTensor(1, 2, 3, 4)
- double_instance_data = instance_data.to(torch.double)
- for k, v in double_instance_data.items():
- if isinstance(v, torch.Tensor):
- assert v.dtype is torch.double
-
- # test .cpu() .cuda()
- if torch.cuda.is_available():
- cpu_instance_data = double_instance_data.new()
- cpu_instance_data.mask = torch.rand(1)
- cuda_tensor = torch.rand(1, 2, 3).cuda()
- cuda_instance_data = cpu_instance_data.to(cuda_tensor.device)
- for value in cuda_instance_data.values():
- assert value.is_cuda
- cpu_instance_data = cuda_instance_data.cpu()
- for value in cpu_instance_data.values():
- assert not value.is_cuda
- cuda_instance_data = cpu_instance_data.cuda()
- for value in cuda_instance_data.values():
- assert value.is_cuda
-
- # test detach
- grad_instance_data = double_instance_data.new()
- grad_instance_data.mask = torch.rand(2, requires_grad=True)
- grad_instance_data.mask_1 = torch.rand(2, requires_grad=True)
- detach_instance_data = grad_instance_data.detach()
- for value in detach_instance_data.values():
- assert not value.requires_grad
-
- # test numpy
- tensor_instance_data = double_instance_data.new()
- tensor_instance_data.mask = torch.rand(2, requires_grad=True)
- tensor_instance_data.mask_1 = torch.rand(2, requires_grad=True)
- numpy_instance_data = tensor_instance_data.numpy()
- for value in numpy_instance_data.values():
- assert isinstance(value, np.ndarray)
- if torch.cuda.is_available():
- tensor_instance_data = double_instance_data.new()
- tensor_instance_data.mask = torch.rand(2)
- tensor_instance_data.mask_1 = torch.rand(2)
- tensor_instance_data = tensor_instance_data.cuda()
- numpy_instance_data = tensor_instance_data.numpy()
- for value in numpy_instance_data.values():
- assert isinstance(value, np.ndarray)
-
- instance_data['_c'] = 10000
- instance_data.get('dad', None) is None
- assert hasattr(instance_data, '_c')
- del instance_data['_c']
- assert not hasattr(instance_data, '_c')
- instance_data.a = 1000
- instance_data['a'] = 2000
- assert instance_data['a'] == 2000
- assert instance_data.a == 2000
- assert instance_data.get('a') == instance_data['a'] == instance_data.a
- instance_data._meta = 1000
- assert '_meta' in instance_data.keys()
- if torch.cuda.is_available():
- instance_data.bbox = torch.ones(2, 3, 4, 5).cuda()
- instance_data.score = torch.ones(2, 3, 4, 4)
- else:
- instance_data.bbox = torch.ones(2, 3, 4, 5)
-
- assert len(instance_data.new().keys()) == 0
- with pytest.raises(AttributeError):
- instance_data.img_size = 100
-
- for k, v in instance_data.items():
- if k == 'bbox':
- assert isinstance(v, torch.Tensor)
- assert 'a' in instance_data
- instance_data.pop('a')
- assert 'a' not in instance_data
-
- cpu_instance_data = instance_data.cpu()
- for k, v in cpu_instance_data.items():
- if isinstance(v, torch.Tensor):
- assert not v.is_cuda
-
- assert isinstance(cpu_instance_data.numpy().bbox, np.ndarray)
-
- if torch.cuda.is_available():
- cuda_resutls = instance_data.cuda()
- for k, v in cuda_resutls.items():
- if isinstance(v, torch.Tensor):
- assert v.is_cuda
-
-
- def test_instance_data():
- meta_info = dict(
- img_size=(256, 256),
- path='dadfaff',
- scale_factor=np.array([1.5, 1.5, 1, 1]))
-
- data = dict(
- bboxes=torch.rand(4, 4),
- masks=torch.rand(4, 2, 2),
- labels=np.random.rand(4),
- size=[(i, i) for i in range(4)])
-
- # test init
- instance_data = InstanceData(meta_info)
- assert 'path' in instance_data
- instance_data = InstanceData(meta_info, data=data)
- assert len(instance_data) == 4
- instance_data.set_data(data)
- assert len(instance_data) == 4
-
- meta_info = copy.deepcopy(meta_info)
- meta_info['img_name'] = 'flag'
-
- # test newinstance_data
- new_instance_data = instance_data.new(meta_info=meta_info)
- for k, v in new_instance_data.meta_info_items():
- if k in instance_data:
- _equal(v, instance_data[k])
- else:
- assert _equal(v, meta_info[k])
- assert k == 'img_name'
- # meta info is immutable
- with pytest.raises(KeyError):
- meta_info = copy.deepcopy(meta_info)
- meta_info['path'] = 'fdasfdsd'
- instance_data.new(meta_info=meta_info)
-
- # data fields should have same length
- with pytest.raises(AssertionError):
- temp_data = copy.deepcopy(data)
- temp_data['bboxes'] = torch.rand(5, 4)
- instance_data.new(data=temp_data)
-
- temp_data = copy.deepcopy(data)
- temp_data['scores'] = torch.rand(4)
- new_instance_data = instance_data.new(data=temp_data)
- for k, v in new_instance_data.items():
- if k in instance_data:
- _equal(v, instance_data[k])
- else:
- assert k == 'scores'
- assert _equal(v, temp_data[k])
-
- instance_data = instance_data.new()
-
- # test __setattr__
- # '_meta_info_field', '_data_fields' is immutable.
- with pytest.raises(AttributeError):
- instance_data._data_fields = dict()
- with pytest.raises(AttributeError):
- instance_data._data_fields = dict()
-
- # all attribute in instance_data_field should be
- # (torch.Tensor, np.ndarray, list))
- with pytest.raises(AssertionError):
- instance_data.a = 1000
-
- # instance_data field should has same length
- new_instance_data = instance_data.new()
- new_instance_data.det_bbox = torch.rand(100, 4)
- new_instance_data.det_label = torch.arange(100)
- with pytest.raises(AssertionError):
- new_instance_data.scores = torch.rand(101, 1)
- new_instance_data.none = [None] * 100
- with pytest.raises(AssertionError):
- new_instance_data.scores = [None] * 101
- new_instance_data.numpy_det = np.random.random([100, 1])
- with pytest.raises(AssertionError):
- new_instance_data.scores = np.random.random([101, 1])
-
- # isinstance(str, slice, int, torch.LongTensor, torch.BoolTensor)
- item = torch.Tensor([1, 2, 3, 4])
- with pytest.raises(AssertionError):
- new_instance_data[item]
- len(new_instance_data[item.long()]) == 1
-
- # when input is a bool tensor, The shape of
- # the input at index 0 should equal to
- # the value length in instance_data_field
- with pytest.raises(AssertionError):
- new_instance_data[item.bool()]
-
- for i in range(len(new_instance_data)):
- assert new_instance_data[i].det_label == i
- assert len(new_instance_data[i]) == 1
-
- # assert the index should in 0 ~ len(instance_data) -1
- with pytest.raises(IndexError):
- new_instance_data[101]
-
- # assert the index should not be an empty tensor
- new_new_instance_data = new_instance_data.new()
- with pytest.raises(AssertionError):
- new_new_instance_data[0]
-
- # test str
- with pytest.raises(AssertionError):
- instance_data.img_size_dummmy = meta_info['img_size']
-
- # test slice
- ten_ressults = new_instance_data[:10]
- len(ten_ressults) == 10
- for v in ten_ressults.values():
- assert len(v) == 10
-
- # test Longtensor
- long_tensor = torch.randint(100, (50, ))
- long_index_instance_data = new_instance_data[long_tensor]
- assert len(long_index_instance_data) == len(long_tensor)
- for key, value in long_index_instance_data.items():
- if not isinstance(value, list):
- assert (long_index_instance_data[key] == new_instance_data[key]
- [long_tensor]).all()
- else:
- len(long_tensor) == len(value)
-
- # test bool tensor
- bool_tensor = torch.rand(100) > 0.5
- bool_index_instance_data = new_instance_data[bool_tensor]
- assert len(bool_index_instance_data) == bool_tensor.sum()
- for key, value in bool_index_instance_data.items():
- if not isinstance(value, list):
- assert (bool_index_instance_data[key] == new_instance_data[key]
- [bool_tensor]).all()
- else:
- assert len(value) == bool_tensor.sum()
-
- num_instance = 1000
- instance_data_list = []
-
- # assert len(instance_lists) > 0
- with pytest.raises(AssertionError):
- instance_data.cat(instance_data_list)
-
- for _ in range(2):
- instance_data['bbox'] = torch.rand(num_instance, 4)
- instance_data['label'] = torch.rand(num_instance, 1)
- instance_data['mask'] = torch.rand(num_instance, 224, 224)
- instance_data['instances_infos'] = [1] * num_instance
- instance_data['cpu_bbox'] = np.random.random((num_instance, 4))
- if torch.cuda.is_available():
- instance_data.cuda_tensor = torch.rand(num_instance).cuda()
- assert instance_data.cuda_tensor.is_cuda
- cuda_instance_data = instance_data.cuda()
- assert cuda_instance_data.cuda_tensor.is_cuda
-
- assert len(instance_data[0]) == 1
- with pytest.raises(IndexError):
- return instance_data[num_instance + 1]
- with pytest.raises(AssertionError):
- instance_data.centerness = torch.rand(num_instance + 1, 1)
-
- mask_tensor = torch.rand(num_instance) > 0.5
- length = mask_tensor.sum()
- assert len(instance_data[mask_tensor]) == length
-
- index_tensor = torch.LongTensor([1, 5, 8, 110, 399])
- length = len(index_tensor)
-
- assert len(instance_data[index_tensor]) == length
-
- instance_data_list.append(instance_data)
-
- cat_resutls = InstanceData.cat(instance_data_list)
- assert len(cat_resutls) == num_instance * 2
-
- instances = InstanceData(data=dict(bboxes=torch.rand(4, 4)))
- # cat only single instance
- assert len(InstanceData.cat([instances])) == 4
|