Spaces:
Build error
Build error
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 | |