123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474 |
- # Copyright (c) OpenMMLab. All rights reserved.
- import copy
- import os
- import os.path as osp
- import sys
- import unittest
- from unittest.mock import MagicMock, Mock, patch
- import mmcv
- import numpy as np
- from mmdet.datasets.transforms import (FilterAnnotations, LoadAnnotations,
- LoadEmptyAnnotations,
- LoadImageFromNDArray,
- LoadMultiChannelImageFromFiles,
- LoadProposals)
- from mmdet.evaluation import INSTANCE_OFFSET
- from mmdet.structures.mask import BitmapMasks, PolygonMasks
- try:
- import panopticapi
- except ImportError:
- panopticapi = None
- class TestLoadAnnotations(unittest.TestCase):
- def setUp(self):
- """Setup the model and optimizer which are used in every test method.
- TestCase calls functions in this order: setUp() -> testMethod() ->
- tearDown() -> cleanUp()
- """
- data_prefix = osp.join(osp.dirname(__file__), '../../data')
- seg_map = osp.join(data_prefix, 'gray.jpg')
- self.results = {
- 'ori_shape': (300, 400),
- 'seg_map_path':
- seg_map,
- 'instances': [{
- 'bbox': [0, 0, 10, 20],
- 'bbox_label': 1,
- 'mask': [[0, 0, 0, 20, 10, 20, 10, 0]],
- 'ignore_flag': 0
- }, {
- 'bbox': [10, 10, 110, 120],
- 'bbox_label': 2,
- 'mask': [[10, 10, 110, 10, 110, 120, 110, 10]],
- 'ignore_flag': 0
- }, {
- 'bbox': [50, 50, 60, 80],
- 'bbox_label': 2,
- 'mask': [[50, 50, 60, 50, 60, 80, 50, 80]],
- 'ignore_flag': 1
- }]
- }
- def test_load_bboxes(self):
- transform = LoadAnnotations(
- with_bbox=True,
- with_label=False,
- with_seg=False,
- with_mask=False,
- box_type=None)
- results = transform(copy.deepcopy(self.results))
- self.assertIn('gt_bboxes', results)
- self.assertTrue((results['gt_bboxes'] == np.array([[0, 0, 10, 20],
- [10, 10, 110, 120],
- [50, 50, 60,
- 80]])).all())
- self.assertEqual(results['gt_bboxes'].dtype, np.float32)
- self.assertTrue((results['gt_ignore_flags'] == np.array([0, 0,
- 1])).all())
- self.assertEqual(results['gt_ignore_flags'].dtype, bool)
- def test_load_labels(self):
- transform = LoadAnnotations(
- with_bbox=False,
- with_label=True,
- with_seg=False,
- with_mask=False,
- )
- results = transform(copy.deepcopy(self.results))
- self.assertIn('gt_bboxes_labels', results)
- self.assertTrue((results['gt_bboxes_labels'] == np.array([1, 2,
- 2])).all())
- self.assertEqual(results['gt_bboxes_labels'].dtype, np.int64)
- def test_load_mask(self):
- transform = LoadAnnotations(
- with_bbox=False,
- with_label=False,
- with_seg=False,
- with_mask=True,
- poly2mask=False)
- results = transform(copy.deepcopy(self.results))
- self.assertIn('gt_masks', results)
- self.assertEqual(len(results['gt_masks']), 3)
- self.assertIsInstance(results['gt_masks'], PolygonMasks)
- def test_load_mask_poly2mask(self):
- transform = LoadAnnotations(
- with_bbox=False,
- with_label=False,
- with_seg=False,
- with_mask=True,
- poly2mask=True)
- results = transform(copy.deepcopy(self.results))
- self.assertIn('gt_masks', results)
- self.assertEqual(len(results['gt_masks']), 3)
- self.assertIsInstance(results['gt_masks'], BitmapMasks)
- def test_repr(self):
- transform = LoadAnnotations(
- with_bbox=True,
- with_label=False,
- with_seg=False,
- with_mask=False,
- )
- self.assertEqual(
- repr(transform), ('LoadAnnotations(with_bbox=True, '
- 'with_label=False, with_mask=False, '
- 'with_seg=False, poly2mask=True, '
- "imdecode_backend='cv2', "
- 'backend_args=None)'))
- class TestFilterAnnotations(unittest.TestCase):
- def setUp(self):
- """Setup the model and optimizer which are used in every test method.
- TestCase calls functions in this order: setUp() -> testMethod() ->
- tearDown() -> cleanUp()
- """
- rng = np.random.RandomState(0)
- self.results = {
- 'img':
- np.random.random((224, 224, 3)),
- 'img_shape': (224, 224),
- 'gt_bboxes_labels':
- np.array([1, 2, 3], dtype=np.int64),
- 'gt_bboxes':
- np.array([[10, 10, 20, 20], [20, 20, 40, 40], [40, 40, 80, 80]]),
- 'gt_ignore_flags':
- np.array([0, 0, 1], dtype=np.bool8),
- 'gt_masks':
- BitmapMasks(rng.rand(3, 224, 224), height=224, width=224),
- }
- def test_transform(self):
- # test keep_empty = True
- transform = FilterAnnotations(
- min_gt_bbox_wh=(50, 50),
- keep_empty=True,
- )
- results = transform(copy.deepcopy(self.results))
- self.assertIsNone(results)
- # test keep_empty = False
- transform = FilterAnnotations(
- min_gt_bbox_wh=(50, 50),
- keep_empty=False,
- )
- results = transform(copy.deepcopy(self.results))
- self.assertTrue(isinstance(results, dict))
- # test filter annotations
- transform = FilterAnnotations(min_gt_bbox_wh=(15, 15), )
- results = transform(copy.deepcopy(self.results))
- self.assertIsInstance(results, dict)
- self.assertTrue((results['gt_bboxes_labels'] == np.array([2,
- 3])).all())
- self.assertTrue((results['gt_bboxes'] == np.array([[20, 20, 40, 40],
- [40, 40, 80,
- 80]])).all())
- self.assertEqual(len(results['gt_masks']), 2)
- self.assertEqual(len(results['gt_ignore_flags']), 2)
- def test_repr(self):
- transform = FilterAnnotations(
- min_gt_bbox_wh=(1, 1),
- keep_empty=False,
- )
- self.assertEqual(
- repr(transform), ('FilterAnnotations(min_gt_bbox_wh=(1, 1), '
- 'keep_empty=False)'))
- class TestLoadPanopticAnnotations(unittest.TestCase):
- def setUp(self):
- seg_map = np.zeros((10, 10), dtype=np.int32)
- seg_map[:5, :10] = 1 + 10 * INSTANCE_OFFSET
- seg_map[5:10, :5] = 4 + 11 * INSTANCE_OFFSET
- seg_map[5:10, 5:10] = 6 + 0 * INSTANCE_OFFSET
- rgb_seg_map = np.zeros((10, 10, 3), dtype=np.uint8)
- rgb_seg_map[:, :, 0] = seg_map / (256 * 256)
- rgb_seg_map[:, :, 1] = seg_map % (256 * 256) / 256
- rgb_seg_map[:, :, 2] = seg_map % 256
- self.seg_map_path = './1.png'
- mmcv.imwrite(rgb_seg_map, self.seg_map_path)
- self.seg_map = seg_map
- self.rgb_seg_map = rgb_seg_map
- self.results = {
- 'ori_shape': (10, 10),
- 'instances': [{
- 'bbox': [0, 0, 10, 5],
- 'bbox_label': 0,
- 'ignore_flag': 0,
- }, {
- 'bbox': [0, 5, 5, 10],
- 'bbox_label': 1,
- 'ignore_flag': 1,
- }],
- 'segments_info': [
- {
- 'id': 1 + 10 * INSTANCE_OFFSET,
- 'category': 0,
- 'is_thing': True,
- },
- {
- 'id': 4 + 11 * INSTANCE_OFFSET,
- 'category': 1,
- 'is_thing': True,
- },
- {
- 'id': 6 + 0 * INSTANCE_OFFSET,
- 'category': 2,
- 'is_thing': False,
- },
- ],
- 'seg_map_path':
- self.seg_map_path
- }
- self.gt_mask = BitmapMasks([
- (seg_map == 1 + 10 * INSTANCE_OFFSET).astype(np.uint8),
- (seg_map == 4 + 11 * INSTANCE_OFFSET).astype(np.uint8),
- ], 10, 10)
- self.gt_bboxes = np.array([[0, 0, 10, 5], [0, 5, 5, 10]],
- dtype=np.float32)
- self.gt_bboxes_labels = np.array([0, 1], dtype=np.int64)
- self.gt_ignore_flags = np.array([0, 1], dtype=bool)
- self.gt_seg_map = np.zeros((10, 10), dtype=np.int32)
- self.gt_seg_map[:5, :10] = 0
- self.gt_seg_map[5:10, :5] = 1
- self.gt_seg_map[5:10, 5:10] = 2
- def tearDown(self):
- os.remove(self.seg_map_path)
- @unittest.skipIf(panopticapi is not None, 'panopticapi is installed')
- def test_init_without_panopticapi(self):
- # test if panopticapi is not installed
- from mmdet.datasets.transforms import LoadPanopticAnnotations
- with self.assertRaisesRegex(
- ImportError,
- 'panopticapi is not installed, please install it by'):
- LoadPanopticAnnotations()
- def test_transform(self):
- sys.modules['panopticapi'] = MagicMock()
- sys.modules['panopticapi.utils'] = MagicMock()
- from mmdet.datasets.transforms import LoadPanopticAnnotations
- mock_rgb2id = Mock(return_value=self.seg_map)
- with patch('panopticapi.utils.rgb2id', mock_rgb2id):
- # test with all False
- transform = LoadPanopticAnnotations(
- with_bbox=False,
- with_label=False,
- with_mask=False,
- with_seg=False)
- results = transform(copy.deepcopy(self.results))
- self.assertDictEqual(results, self.results)
- # test with with_mask=True
- transform = LoadPanopticAnnotations(
- with_bbox=False,
- with_label=False,
- with_mask=True,
- with_seg=False)
- results = transform(copy.deepcopy(self.results))
- self.assertTrue(
- (results['gt_masks'].masks == self.gt_mask.masks).all())
- # test with with_seg=True
- transform = LoadPanopticAnnotations(
- with_bbox=False,
- with_label=False,
- with_mask=False,
- with_seg=True)
- results = transform(copy.deepcopy(self.results))
- self.assertNotIn('gt_masks', results)
- self.assertTrue((results['gt_seg_map'] == self.gt_seg_map).all())
- # test with all True
- transform = LoadPanopticAnnotations(
- with_bbox=True,
- with_label=True,
- with_mask=True,
- with_seg=True,
- box_type=None)
- results = transform(copy.deepcopy(self.results))
- self.assertTrue(
- (results['gt_masks'].masks == self.gt_mask.masks).all())
- self.assertTrue((results['gt_bboxes'] == self.gt_bboxes).all())
- self.assertTrue(
- (results['gt_bboxes_labels'] == self.gt_bboxes_labels).all())
- self.assertTrue(
- (results['gt_ignore_flags'] == self.gt_ignore_flags).all())
- self.assertTrue((results['gt_seg_map'] == self.gt_seg_map).all())
- class TestLoadImageFromNDArray(unittest.TestCase):
- def setUp(self):
- """Setup the model and optimizer which are used in every test method.
- TestCase calls functions in this order: setUp() -> testMethod() ->
- tearDown() -> cleanUp()
- """
- self.results = {'img': np.zeros((256, 256, 3), dtype=np.uint8)}
- def test_transform(self):
- transform = LoadImageFromNDArray()
- results = transform(copy.deepcopy(self.results))
- self.assertEqual(results['img'].shape, (256, 256, 3))
- self.assertEqual(results['img'].dtype, np.uint8)
- self.assertEqual(results['img_shape'], (256, 256))
- self.assertEqual(results['ori_shape'], (256, 256))
- # to_float32
- transform = LoadImageFromNDArray(to_float32=True)
- results = transform(copy.deepcopy(results))
- self.assertEqual(results['img'].dtype, np.float32)
- def test_repr(self):
- transform = LoadImageFromNDArray()
- self.assertEqual(
- repr(transform), ('LoadImageFromNDArray('
- 'ignore_empty=False, '
- 'to_float32=False, '
- "color_type='color', "
- "imdecode_backend='cv2', "
- 'backend_args=None)'))
- class TestLoadMultiChannelImageFromFiles(unittest.TestCase):
- def setUp(self):
- """Setup the model and optimizer which are used in every test method.
- TestCase calls functions in this order: setUp() -> testMethod() ->
- tearDown() -> cleanUp()
- """
- self.img_path = []
- for i in range(4):
- img_channel_path = f'./part_{i}.jpg'
- img_channel = np.zeros((10, 10), dtype=np.uint8)
- mmcv.imwrite(img_channel, img_channel_path)
- self.img_path.append(img_channel_path)
- self.results = {'img_path': self.img_path}
- def tearDown(self):
- for filename in self.img_path:
- os.remove(filename)
- def test_transform(self):
- transform = LoadMultiChannelImageFromFiles()
- results = transform(copy.deepcopy(self.results))
- self.assertEqual(results['img'].shape, (10, 10, 4))
- self.assertEqual(results['img'].dtype, np.uint8)
- self.assertEqual(results['img_shape'], (10, 10))
- self.assertEqual(results['ori_shape'], (10, 10))
- # to_float32
- transform = LoadMultiChannelImageFromFiles(to_float32=True)
- results = transform(copy.deepcopy(results))
- self.assertEqual(results['img'].dtype, np.float32)
- def test_rper(self):
- transform = LoadMultiChannelImageFromFiles()
- self.assertEqual(
- repr(transform), ('LoadMultiChannelImageFromFiles('
- 'to_float32=False, '
- "color_type='unchanged', "
- "imdecode_backend='cv2', "
- 'backend_args=None)'))
- class TestLoadProposals(unittest.TestCase):
- def test_transform(self):
- transform = LoadProposals()
- results = {
- 'proposals':
- dict(
- bboxes=np.zeros((5, 4), dtype=np.int64),
- scores=np.zeros((5, ), dtype=np.int64))
- }
- results = transform(results)
- self.assertEqual(results['proposals'].dtype, np.float32)
- self.assertEqual(results['proposals'].shape[-1], 4)
- self.assertEqual(results['proposals_scores'].dtype, np.float32)
- # bboxes.shape[1] should be 4
- results = {'proposals': dict(bboxes=np.zeros((5, 5), dtype=np.int64))}
- with self.assertRaises(AssertionError):
- transform(results)
- # bboxes.shape[0] should equal to scores.shape[0]
- results = {
- 'proposals':
- dict(
- bboxes=np.zeros((5, 4), dtype=np.int64),
- scores=np.zeros((3, ), dtype=np.int64))
- }
- with self.assertRaises(AssertionError):
- transform(results)
- # empty bboxes
- results = {
- 'proposals': dict(bboxes=np.zeros((0, 4), dtype=np.float32))
- }
- results = transform(results)
- excepted_proposals = np.zeros((0, 4), dtype=np.float32)
- excepted_proposals_scores = np.zeros(0, dtype=np.float32)
- self.assertTrue((results['proposals'] == excepted_proposals).all())
- self.assertTrue(
- (results['proposals_scores'] == excepted_proposals_scores).all())
- transform = LoadProposals(num_max_proposals=2)
- results = {
- 'proposals':
- dict(
- bboxes=np.zeros((5, 4), dtype=np.int64),
- scores=np.zeros((5, ), dtype=np.int64))
- }
- results = transform(results)
- self.assertEqual(results['proposals'].shape[0], 2)
- def test_repr(self):
- transform = LoadProposals()
- self.assertEqual(
- repr(transform), 'LoadProposals(num_max_proposals=None)')
- class TestLoadEmptyAnnotations(unittest.TestCase):
- def test_transform(self):
- transform = LoadEmptyAnnotations(
- with_bbox=True, with_label=True, with_mask=True, with_seg=True)
- results = {'img_shape': (224, 224)}
- results = transform(results)
- self.assertEqual(results['gt_bboxes'].dtype, np.float32)
- self.assertEqual(results['gt_bboxes'].shape[-1], 4)
- self.assertEqual(results['gt_ignore_flags'].dtype, bool)
- self.assertEqual(results['gt_bboxes_labels'].dtype, np.int64)
- self.assertEqual(results['gt_masks'].masks.dtype, np.uint8)
- self.assertEqual(results['gt_masks'].masks.shape[-2:],
- results['img_shape'])
- self.assertEqual(results['gt_seg_map'].dtype, np.uint8)
- self.assertEqual(results['gt_seg_map'].shape, results['img_shape'])
- def test_repr(self):
- transform = LoadEmptyAnnotations()
- self.assertEqual(
- repr(transform), 'LoadEmptyAnnotations(with_bbox=True, '
- 'with_label=True, '
- 'with_mask=False, '
- 'with_seg=False, '
- 'seg_ignore_label=255)')
|