test_transforms.py 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790
  1. # Copyright (c) OpenMMLab. All rights reserved.
  2. import copy
  3. import os.path as osp
  4. import unittest
  5. import mmcv
  6. import numpy as np
  7. import torch
  8. from mmcv.transforms import LoadImageFromFile
  9. # yapf:disable
  10. from mmdet.datasets.transforms import (CopyPaste, CutOut, Expand,
  11. FixScaleResize, FixShapeResize,
  12. MinIoURandomCrop, MixUp, Mosaic, Pad,
  13. PhotoMetricDistortion, RandomAffine,
  14. RandomCenterCropPad, RandomCrop,
  15. RandomErasing, RandomFlip, RandomShift,
  16. Resize, ResizeShortestEdge, SegRescale,
  17. YOLOXHSVRandomAug)
  18. # yapf:enable
  19. from mmdet.evaluation import bbox_overlaps
  20. from mmdet.registry import TRANSFORMS
  21. from mmdet.structures.bbox import HorizontalBoxes, bbox_project
  22. from mmdet.structures.mask import BitmapMasks
  23. from .utils import construct_toy_data, create_full_masks, create_random_bboxes
  24. try:
  25. import albumentations
  26. from albumentations import Compose
  27. except ImportError:
  28. albumentations = None
  29. Compose = None
  30. # yapf:enable
  31. class TestResize(unittest.TestCase):
  32. def setUp(self):
  33. """Setup the model and optimizer which are used in every test method.
  34. TestCase calls functions in this order: setUp() -> testMethod()
  35. -> tearDown() -> cleanUp()
  36. """
  37. rng = np.random.RandomState(0)
  38. self.data_info1 = dict(
  39. img=np.random.random((400, 500, 3)),
  40. gt_seg_map=np.random.random((400, 500, 3)),
  41. gt_bboxes=np.array([[0, 0, 112, 112]], dtype=np.float32),
  42. gt_masks=BitmapMasks(rng.rand(1, 400, 500), height=400, width=500))
  43. self.data_info2 = dict(
  44. img=np.random.random((200, 100, 3)),
  45. gt_bboxes=np.array([[20, 15, 60, 45]], dtype=np.float32),
  46. dtype=np.float32)
  47. self.data_info3 = dict(img=np.random.random((200, 100, 3)))
  48. def test_resize(self):
  49. # test keep_ratio is True
  50. transform = Resize(scale=(100, 100), keep_ratio=True)
  51. results = transform(copy.deepcopy(self.data_info1))
  52. self.assertEqual(results['img_shape'], (80, 100))
  53. self.assertEqual(results['scale_factor'], (80 / 400, 100 / 500))
  54. # test resize_bboxes/seg/masks
  55. transform = Resize(scale_factor=(1.5, 2))
  56. results = transform(copy.deepcopy(self.data_info1))
  57. self.assertTrue(
  58. (results['gt_bboxes'] == np.array([[0., 0., 168., 224.]])).all())
  59. self.assertEqual(results['gt_masks'].height, 800)
  60. self.assertEqual(results['gt_masks'].width, 750)
  61. self.assertEqual(results['gt_seg_map'].shape[:2], (800, 750))
  62. # test clip_object_border = False
  63. transform = Resize(scale=(200, 150), clip_object_border=False)
  64. results = transform(self.data_info2)
  65. self.assertTrue(
  66. (results['gt_bboxes'] == np.array([40., 11.25, 120.,
  67. 33.75])).all())
  68. # test only with image
  69. transform = Resize(scale=(200, 150), clip_object_border=False)
  70. results = transform(self.data_info3)
  71. self.assertTupleEqual(results['img'].shape[:2], (150, 200))
  72. # test geometric transformation with homography matrix
  73. transform = Resize(scale_factor=(1.5, 2))
  74. results = transform(copy.deepcopy(self.data_info1))
  75. self.assertTrue((bbox_project(
  76. copy.deepcopy(self.data_info1['gt_bboxes']),
  77. results['homography_matrix']) == results['gt_bboxes']).all())
  78. def test_resize_use_box_type(self):
  79. data_info1 = copy.deepcopy(self.data_info1)
  80. data_info1['gt_bboxes'] = HorizontalBoxes(data_info1['gt_bboxes'])
  81. data_info2 = copy.deepcopy(self.data_info2)
  82. data_info2['gt_bboxes'] = HorizontalBoxes(data_info2['gt_bboxes'])
  83. # test keep_ratio is True
  84. transform = Resize(scale=(100, 150), keep_ratio=True)
  85. results = transform(copy.deepcopy(data_info1))
  86. self.assertEqual(results['img_shape'], (100, 125))
  87. self.assertEqual(results['scale_factor'], (100 / 400, 125 / 500))
  88. # test resize_bboxes/seg/masks
  89. transform = Resize(scale_factor=(1.5, 2))
  90. results = transform(copy.deepcopy(data_info1))
  91. self.assertTrue(
  92. (results['gt_bboxes'].numpy() == np.array([[0, 0, 168,
  93. 224]])).all())
  94. self.assertEqual(results['gt_masks'].height, 800)
  95. self.assertEqual(results['gt_masks'].width, 750)
  96. self.assertEqual(results['gt_seg_map'].shape[:2], (800, 750))
  97. # test clip_object_border = False
  98. transform = Resize(scale=(200, 150), clip_object_border=False)
  99. results = transform(data_info2)
  100. self.assertTrue((results['gt_bboxes'].numpy() == np.array(
  101. [40., 11.25, 120., 33.75])).all())
  102. # test geometric transformation with homography matrix
  103. transform = Resize(scale_factor=(1.5, 2))
  104. results = transform(copy.deepcopy(data_info1))
  105. self.assertTrue((bbox_project(
  106. copy.deepcopy(data_info1['gt_bboxes'].numpy()),
  107. results['homography_matrix']) == results['gt_bboxes'].numpy()
  108. ).all())
  109. def test_repr(self):
  110. transform = Resize(scale=(100, 100), keep_ratio=True)
  111. self.assertEqual(
  112. repr(transform), ('Resize(scale=(100, 100), '
  113. 'scale_factor=None, keep_ratio=True, '
  114. 'clip_object_border=True), backend=cv2), '
  115. 'interpolation=bilinear)'))
  116. class TestFixScaleResize(unittest.TestCase):
  117. def setUp(self):
  118. """Setup the model and optimizer which are used in every test method.
  119. TestCase calls functions in this order: setUp() -> testMethod()
  120. -> tearDown() -> cleanUp()
  121. """
  122. rng = np.random.RandomState(0)
  123. self.data_info1 = dict(
  124. img=np.random.random((200, 300, 3)),
  125. gt_seg_map=np.random.random((200, 300, 3)),
  126. gt_bboxes=np.array([[0, 0, 112, 112]], dtype=np.float32),
  127. gt_masks=BitmapMasks(rng.rand(1, 200, 300), height=200, width=300))
  128. def test_resize(self):
  129. # test keep_ratio is True
  130. transform = FixScaleResize(scale=(101, 201), keep_ratio=True)
  131. results = transform(copy.deepcopy(self.data_info1))
  132. self.assertEqual(results['img_shape'], (101, 151))
  133. self.assertEqual(results['scale_factor'], (151 / 300, 101 / 200))
  134. class TestFixShapeResize(unittest.TestCase):
  135. def setUp(self):
  136. """Setup the model and optimizer which are used in every test method.
  137. TestCase calls functions in this order: setUp() -> testMethod() ->
  138. tearDown() -> cleanUp()
  139. """
  140. rng = np.random.RandomState(0)
  141. self.data_info1 = dict(
  142. img=np.random.random((200, 300, 3)),
  143. gt_seg_map=np.random.random((200, 300, 3)),
  144. gt_bboxes=np.array([[0, 0, 112, 133]], dtype=np.float32),
  145. gt_masks=BitmapMasks(rng.rand(1, 200, 300), height=200, width=300))
  146. self.data_info2 = dict(
  147. img=np.random.random((300, 400, 3)),
  148. gt_bboxes=np.array([[200, 150, 600, 450]], dtype=np.float32),
  149. dtype=np.float32)
  150. self.data_info3 = dict(img=np.random.random((300, 400, 3)))
  151. self.data_info4 = dict(
  152. img=np.random.random((400, 450, 3)),
  153. gt_bboxes=np.array([[200, 150, 300, 400]], dtype=np.float32),
  154. dtype=np.float32)
  155. def test_resize(self):
  156. # test keep_ratio is True
  157. transform = FixShapeResize(width=100, height=50, keep_ratio=True)
  158. results = transform(copy.deepcopy(self.data_info1))
  159. self.assertEqual(results['img_shape'], (50, 100))
  160. self.assertEqual(results['scale_factor'], (50 / 200, 50 / 200))
  161. # test resize_bboxes/seg/masks
  162. transform = FixShapeResize(width=120, height=100, keep_ratio=False)
  163. results = transform(copy.deepcopy(self.data_info1))
  164. self.assertEqual(results['gt_masks'].height, 100)
  165. self.assertEqual(results['gt_masks'].width, 120)
  166. self.assertEqual(results['gt_seg_map'].shape[:2], (100, 120))
  167. # test clip_object_border = False
  168. transform = FixShapeResize(
  169. width=200, height=150, clip_object_border=False)
  170. results = transform(copy.deepcopy(self.data_info2))
  171. self.assertTrue((results['gt_bboxes'] == np.array([100, 75, 300,
  172. 225])).all())
  173. # test only with image
  174. transform = FixShapeResize(
  175. width=200, height=150, clip_object_border=False)
  176. results = transform(self.data_info3)
  177. self.assertTupleEqual(results['img'].shape[:2], (150, 200))
  178. # test geometric transformation with homography matrix
  179. transform = FixShapeResize(width=400, height=300)
  180. results = transform(copy.deepcopy(self.data_info4))
  181. self.assertTrue((bbox_project(
  182. copy.deepcopy(self.data_info4['gt_bboxes']),
  183. results['homography_matrix']) == results['gt_bboxes']).all())
  184. def test_resize_with_boxlist(self):
  185. data_info1 = copy.deepcopy(self.data_info1)
  186. data_info1['gt_bboxes'] = HorizontalBoxes(data_info1['gt_bboxes'])
  187. data_info2 = copy.deepcopy(self.data_info2)
  188. data_info2['gt_bboxes'] = HorizontalBoxes(data_info2['gt_bboxes'])
  189. data_info4 = copy.deepcopy(self.data_info4)
  190. data_info4['gt_bboxes'] = HorizontalBoxes(data_info4['gt_bboxes'])
  191. # test keep_ratio is True
  192. transform = FixShapeResize(width=100, height=200, keep_ratio=True)
  193. results = transform(copy.deepcopy(data_info1))
  194. self.assertEqual(results['img_shape'], (200, 100))
  195. self.assertEqual(results['scale_factor'], (100 / 300, 100 / 300))
  196. # test resize_bboxes/seg/masks
  197. transform = FixShapeResize(width=150, height=200, keep_ratio=False)
  198. results = transform(copy.deepcopy(data_info1))
  199. self.assertTrue(
  200. (results['gt_bboxes'].numpy() == np.array([[0, 0, 56,
  201. 133]])).all())
  202. self.assertEqual(results['gt_masks'].height, 200)
  203. self.assertEqual(results['gt_masks'].width, 150)
  204. self.assertEqual(results['gt_seg_map'].shape[:2], (200, 150))
  205. # test clip_object_border = False
  206. transform = FixShapeResize(
  207. width=200, height=150, clip_object_border=False)
  208. results = transform(copy.deepcopy(data_info2))
  209. self.assertTrue(
  210. (results['gt_bboxes'].numpy() == np.array([100, 75, 300,
  211. 225])).all())
  212. # test only with image
  213. transform = FixShapeResize(
  214. width=200, height=150, clip_object_border=False)
  215. results = transform(self.data_info3)
  216. self.assertTupleEqual(results['img'].shape[:2], (150, 200))
  217. # test geometric transformation with homography matrix
  218. transform = FixShapeResize(width=400, height=300)
  219. results = transform(copy.deepcopy(data_info4))
  220. self.assertTrue((bbox_project(
  221. copy.deepcopy(self.data_info4['gt_bboxes']),
  222. results['homography_matrix']) == results['gt_bboxes'].numpy()
  223. ).all())
  224. def test_repr(self):
  225. transform = FixShapeResize(width=100, height=50, keep_ratio=True)
  226. self.assertEqual(
  227. repr(transform), ('FixShapeResize(width=100, height=50, '
  228. 'keep_ratio=True, '
  229. 'clip_object_border=True), backend=cv2), '
  230. 'interpolation=bilinear)'))
  231. class TestRandomFlip(unittest.TestCase):
  232. def setUp(self):
  233. """Setup the model and optimizer which are used in every test method.
  234. TestCase calls functions in this order: setUp() -> testMethod() ->
  235. tearDown() -> cleanUp()
  236. """
  237. rng = np.random.RandomState(0)
  238. self.results1 = {
  239. 'img': np.random.random((224, 224, 3)),
  240. 'gt_bboxes': np.array([[0, 1, 100, 101]], dtype=np.float32),
  241. 'gt_masks':
  242. BitmapMasks(rng.rand(1, 224, 224), height=224, width=224),
  243. 'gt_seg_map': np.random.random((224, 224))
  244. }
  245. self.results2 = {'img': self.results1['img']}
  246. def test_transform(self):
  247. # test with image, gt_bboxes, gt_masks, gt_seg_map
  248. transform = RandomFlip(1.0)
  249. results_update = transform.transform(copy.deepcopy(self.results1))
  250. self.assertTrue(
  251. (results_update['gt_bboxes'] == np.array([[124, 1, 224,
  252. 101]])).all())
  253. # test only with image
  254. transform = RandomFlip(1.0)
  255. results_update = transform.transform(copy.deepcopy(self.results2))
  256. self.assertTrue(
  257. (results_update['img'] == self.results2['img'][:, ::-1]).all())
  258. # test geometric transformation with homography matrix
  259. # (1) Horizontal Flip
  260. transform = RandomFlip(1.0)
  261. results_update = transform.transform(copy.deepcopy(self.results1))
  262. bboxes = copy.deepcopy(self.results1['gt_bboxes'])
  263. self.assertTrue((bbox_project(
  264. bboxes,
  265. results_update['homography_matrix']) == results_update['gt_bboxes']
  266. ).all())
  267. # (2) Vertical Flip
  268. transform = RandomFlip(1.0, direction='vertical')
  269. results_update = transform.transform(copy.deepcopy(self.results1))
  270. bboxes = copy.deepcopy(self.results1['gt_bboxes'])
  271. self.assertTrue((bbox_project(
  272. bboxes,
  273. results_update['homography_matrix']) == results_update['gt_bboxes']
  274. ).all())
  275. # (3) Diagonal Flip
  276. transform = RandomFlip(1.0, direction='diagonal')
  277. results_update = transform.transform(copy.deepcopy(self.results1))
  278. bboxes = copy.deepcopy(self.results1['gt_bboxes'])
  279. self.assertTrue((bbox_project(
  280. bboxes,
  281. results_update['homography_matrix']) == results_update['gt_bboxes']
  282. ).all())
  283. def test_transform_use_box_type(self):
  284. results1 = copy.deepcopy(self.results1)
  285. results1['gt_bboxes'] = HorizontalBoxes(results1['gt_bboxes'])
  286. # test with image, gt_bboxes, gt_masks, gt_seg_map
  287. transform = RandomFlip(1.0)
  288. results_update = transform.transform(copy.deepcopy(results1))
  289. self.assertTrue((results_update['gt_bboxes'].numpy() == np.array(
  290. [[124, 1, 224, 101]])).all())
  291. # test geometric transformation with homography matrix
  292. # (1) Horizontal Flip
  293. transform = RandomFlip(1.0)
  294. results_update = transform.transform(copy.deepcopy(results1))
  295. bboxes = copy.deepcopy(results1['gt_bboxes'].numpy())
  296. self.assertTrue((bbox_project(bboxes,
  297. results_update['homography_matrix']) ==
  298. results_update['gt_bboxes'].numpy()).all())
  299. # (2) Vertical Flip
  300. transform = RandomFlip(1.0, direction='vertical')
  301. results_update = transform.transform(copy.deepcopy(results1))
  302. bboxes = copy.deepcopy(results1['gt_bboxes'].numpy())
  303. self.assertTrue((bbox_project(bboxes,
  304. results_update['homography_matrix']) ==
  305. results_update['gt_bboxes'].numpy()).all())
  306. # (3) Diagonal Flip
  307. transform = RandomFlip(1.0, direction='diagonal')
  308. results_update = transform.transform(copy.deepcopy(results1))
  309. bboxes = copy.deepcopy(results1['gt_bboxes'].numpy())
  310. self.assertTrue((bbox_project(bboxes,
  311. results_update['homography_matrix']) ==
  312. results_update['gt_bboxes'].numpy()).all())
  313. def test_repr(self):
  314. transform = RandomFlip(0.1)
  315. transform_str = str(transform)
  316. self.assertIsInstance(transform_str, str)
  317. class TestPad(unittest.TestCase):
  318. def setUp(self):
  319. """Setup the model and optimizer which are used in every test method.
  320. TestCase calls functions in this order: setUp() -> testMethod() ->
  321. tearDown() -> cleanUp()
  322. """
  323. rng = np.random.RandomState(0)
  324. self.results = {
  325. 'img': np.random.random((100, 80, 3)),
  326. 'gt_masks':
  327. BitmapMasks(rng.rand(4, 100, 80), height=100, width=80)
  328. }
  329. def test_transform(self):
  330. # test pad img/gt_masks with size
  331. transform = Pad(size=(120, 110))
  332. results = transform(copy.deepcopy(self.results))
  333. self.assertEqual(results['img'].shape[:2], (110, 120))
  334. self.assertEqual(results['gt_masks'].masks.shape[1:], (110, 120))
  335. # test pad img/gt_masks with size_divisor
  336. transform = Pad(size_divisor=11)
  337. results = transform(copy.deepcopy(self.results))
  338. self.assertEqual(results['img'].shape[:2], (110, 88))
  339. self.assertEqual(results['gt_masks'].masks.shape[1:], (110, 88))
  340. # test pad img/gt_masks with pad_to_square
  341. transform = Pad(pad_to_square=True)
  342. results = transform(copy.deepcopy(self.results))
  343. self.assertEqual(results['img'].shape[:2], (100, 100))
  344. self.assertEqual(results['gt_masks'].masks.shape[1:], (100, 100))
  345. # test pad img/gt_masks with pad_to_square and size_divisor
  346. transform = Pad(pad_to_square=True, size_divisor=11)
  347. results = transform(copy.deepcopy(self.results))
  348. self.assertEqual(results['img'].shape[:2], (110, 110))
  349. self.assertEqual(results['gt_masks'].masks.shape[1:], (110, 110))
  350. # test pad img/gt_masks with pad_to_square and size_divisor
  351. transform = Pad(pad_to_square=True, size_divisor=11)
  352. results = transform(copy.deepcopy(self.results))
  353. self.assertEqual(results['img'].shape[:2], (110, 110))
  354. self.assertEqual(results['gt_masks'].masks.shape[1:], (110, 110))
  355. def test_repr(self):
  356. transform = Pad(
  357. pad_to_square=True, size_divisor=11, padding_mode='edge')
  358. self.assertEqual(
  359. repr(transform),
  360. ('Pad(size=None, size_divisor=11, pad_to_square=True, '
  361. "pad_val={'img': 0, 'seg': 255}), padding_mode=edge)"))
  362. class TestMinIoURandomCrop(unittest.TestCase):
  363. def test_transform(self):
  364. results = dict()
  365. img = mmcv.imread(
  366. osp.join(osp.dirname(__file__), '../../data/color.jpg'), 'color')
  367. results['img'] = img
  368. results['img_shape'] = img.shape[:2]
  369. gt_bboxes = create_random_bboxes(1, results['img_shape'][1],
  370. results['img_shape'][0])
  371. results['gt_labels'] = np.ones(gt_bboxes.shape[0], dtype=np.int64)
  372. results['gt_bboxes'] = gt_bboxes
  373. transform = MinIoURandomCrop()
  374. results = transform.transform(copy.deepcopy(results))
  375. self.assertEqual(results['gt_labels'].shape[0],
  376. results['gt_bboxes'].shape[0])
  377. self.assertEqual(results['gt_labels'].dtype, np.int64)
  378. self.assertEqual(results['gt_bboxes'].dtype, np.float32)
  379. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  380. patch = np.array(
  381. [0, 0, results['img_shape'][1], results['img_shape'][0]])
  382. ious = bbox_overlaps(patch.reshape(-1, 4),
  383. results['gt_bboxes']).reshape(-1)
  384. mode = transform.mode
  385. if mode == 1:
  386. self.assertTrue(np.equal(results['gt_bboxes'], gt_bboxes).all())
  387. else:
  388. self.assertTrue((ious >= mode).all())
  389. def test_transform_use_box_type(self):
  390. results = dict()
  391. img = mmcv.imread(
  392. osp.join(osp.dirname(__file__), '../../data/color.jpg'), 'color')
  393. results['img'] = img
  394. results['img_shape'] = img.shape[:2]
  395. gt_bboxes = create_random_bboxes(1, results['img_shape'][1],
  396. results['img_shape'][0])
  397. results['gt_labels'] = np.ones(gt_bboxes.shape[0], dtype=np.int64)
  398. results['gt_bboxes'] = HorizontalBoxes(gt_bboxes)
  399. transform = MinIoURandomCrop()
  400. results = transform.transform(copy.deepcopy(results))
  401. self.assertEqual(results['gt_labels'].shape[0],
  402. results['gt_bboxes'].shape[0])
  403. self.assertEqual(results['gt_labels'].dtype, np.int64)
  404. self.assertEqual(results['gt_bboxes'].dtype, torch.float32)
  405. patch = np.array(
  406. [0, 0, results['img_shape'][1], results['img_shape'][0]])
  407. ious = bbox_overlaps(
  408. patch.reshape(-1, 4), results['gt_bboxes'].numpy()).reshape(-1)
  409. mode = transform.mode
  410. if mode == 1:
  411. self.assertTrue((results['gt_bboxes'].numpy() == gt_bboxes).all())
  412. else:
  413. self.assertTrue((ious >= mode).all())
  414. def test_repr(self):
  415. transform = MinIoURandomCrop()
  416. self.assertEqual(
  417. repr(transform), ('MinIoURandomCrop'
  418. '(min_ious=(0.1, 0.3, 0.5, 0.7, 0.9), '
  419. 'min_crop_size=0.3, '
  420. 'bbox_clip_border=True)'))
  421. class TestPhotoMetricDistortion(unittest.TestCase):
  422. def test_transform(self):
  423. img = mmcv.imread(
  424. osp.join(osp.dirname(__file__), '../../data/color.jpg'), 'color')
  425. transform = PhotoMetricDistortion()
  426. # test uint8 input
  427. results = dict()
  428. results['img'] = img
  429. results = transform.transform(copy.deepcopy(results))
  430. self.assertEqual(results['img'].dtype, np.float32)
  431. # test float32 input
  432. results = dict()
  433. results['img'] = img.astype(np.float32)
  434. results = transform.transform(copy.deepcopy(results))
  435. self.assertEqual(results['img'].dtype, np.float32)
  436. def test_repr(self):
  437. transform = PhotoMetricDistortion()
  438. self.assertEqual(
  439. repr(transform), ('PhotoMetricDistortion'
  440. '(brightness_delta=32, '
  441. 'contrast_range=(0.5, 1.5), '
  442. 'saturation_range=(0.5, 1.5), '
  443. 'hue_delta=18)'))
  444. class TestExpand(unittest.TestCase):
  445. def setUp(self):
  446. """Setup the model and optimizer which are used in every test method.
  447. TestCase calls functions in this order: setUp() -> testMethod() ->
  448. tearDown() -> cleanUp()
  449. """
  450. rng = np.random.RandomState(0)
  451. self.results = {
  452. 'img': np.random.random((224, 224, 3)),
  453. 'img_shape': (224, 224),
  454. 'gt_bboxes': np.array([[0, 1, 100, 101]]),
  455. 'gt_masks':
  456. BitmapMasks(rng.rand(1, 224, 224), height=224, width=224),
  457. 'gt_seg_map': np.random.random((224, 224))
  458. }
  459. def test_transform(self):
  460. transform = Expand()
  461. results = transform.transform(copy.deepcopy(self.results))
  462. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  463. self.assertEqual(
  464. results['img_shape'],
  465. (results['gt_masks'].height, results['gt_masks'].width))
  466. self.assertEqual(results['img_shape'], results['gt_seg_map'].shape)
  467. def test_transform_use_box_type(self):
  468. results = copy.deepcopy(self.results)
  469. results['gt_bboxes'] = HorizontalBoxes(results['gt_bboxes'])
  470. transform = Expand()
  471. results = transform.transform(results)
  472. self.assertEqual(
  473. results['img_shape'],
  474. (results['gt_masks'].height, results['gt_masks'].width))
  475. self.assertEqual(results['img_shape'], results['gt_seg_map'].shape)
  476. def test_repr(self):
  477. transform = Expand()
  478. self.assertEqual(
  479. repr(transform), ('Expand'
  480. '(mean=(0, 0, 0), to_rgb=True, '
  481. 'ratio_range=(1, 4), '
  482. 'seg_ignore_label=None, '
  483. 'prob=0.5)'))
  484. class TestSegRescale(unittest.TestCase):
  485. def setUp(self) -> None:
  486. seg_map = np.random.randint(0, 255, size=(32, 32), dtype=np.int32)
  487. self.results = {'gt_seg_map': seg_map}
  488. def test_transform(self):
  489. # test scale_factor != 1
  490. transform = SegRescale(scale_factor=2)
  491. results = transform(copy.deepcopy(self.results))
  492. self.assertEqual(results['gt_seg_map'].shape[:2], (64, 64))
  493. # test scale_factor = 1
  494. transform = SegRescale(scale_factor=1)
  495. results = transform(copy.deepcopy(self.results))
  496. self.assertEqual(results['gt_seg_map'].shape[:2], (32, 32))
  497. def test_repr(self):
  498. transform = SegRescale(scale_factor=2)
  499. self.assertEqual(
  500. repr(transform), ('SegRescale(scale_factor=2, backend=cv2)'))
  501. class TestRandomCrop(unittest.TestCase):
  502. def test_init(self):
  503. # test invalid crop_type
  504. with self.assertRaisesRegex(ValueError, 'Invalid crop_type'):
  505. RandomCrop(crop_size=(10, 10), crop_type='unknown')
  506. crop_type_list = ['absolute', 'absolute_range']
  507. for crop_type in crop_type_list:
  508. # test h > 0 and w > 0
  509. for crop_size in [(0, 0), (0, 1), (1, 0)]:
  510. with self.assertRaises(AssertionError):
  511. RandomCrop(crop_size=crop_size, crop_type=crop_type)
  512. # test type(h) = int and type(w) = int
  513. for crop_size in [(1.0, 1), (1, 1.0), (1.0, 1.0)]:
  514. with self.assertRaises(AssertionError):
  515. RandomCrop(crop_size=crop_size, crop_type=crop_type)
  516. # test crop_size[0] <= crop_size[1]
  517. with self.assertRaises(AssertionError):
  518. RandomCrop(crop_size=(10, 5), crop_type='absolute_range')
  519. # test h in (0, 1] and w in (0, 1]
  520. crop_type_list = ['relative_range', 'relative']
  521. for crop_type in crop_type_list:
  522. for crop_size in [(0, 1), (1, 0), (1.1, 0.5), (0.5, 1.1)]:
  523. with self.assertRaises(AssertionError):
  524. RandomCrop(crop_size=crop_size, crop_type=crop_type)
  525. def test_transform(self):
  526. # test relative and absolute crop
  527. src_results = {
  528. 'img': np.random.randint(0, 255, size=(24, 32), dtype=np.int32)
  529. }
  530. target_shape = (12, 16)
  531. for crop_type, crop_size in zip(['relative', 'absolute'], [(0.5, 0.5),
  532. (16, 12)]):
  533. transform = RandomCrop(crop_size=crop_size, crop_type=crop_type)
  534. results = transform(copy.deepcopy(src_results))
  535. print(results['img'].shape[:2])
  536. self.assertEqual(results['img'].shape[:2], target_shape)
  537. # test absolute_range crop
  538. transform = RandomCrop(crop_size=(10, 20), crop_type='absolute_range')
  539. results = transform(copy.deepcopy(src_results))
  540. h, w = results['img'].shape
  541. self.assertTrue(10 <= w <= 20)
  542. self.assertTrue(10 <= h <= 20)
  543. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  544. # test relative_range crop
  545. transform = RandomCrop(
  546. crop_size=(0.5, 0.5), crop_type='relative_range')
  547. results = transform(copy.deepcopy(src_results))
  548. h, w = results['img'].shape
  549. self.assertTrue(16 <= w <= 32)
  550. self.assertTrue(12 <= h <= 24)
  551. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  552. # test with gt_bboxes, gt_bboxes_labels, gt_ignore_flags,
  553. # gt_masks, gt_seg_map, gt_instances_ids
  554. img = np.random.randint(0, 255, size=(10, 10), dtype=np.uint8)
  555. gt_bboxes = np.array([[0, 0, 7, 7], [2, 3, 9, 9]], dtype=np.float32)
  556. gt_bboxes_labels = np.array([0, 1], dtype=np.int64)
  557. gt_ignore_flags = np.array([0, 1], dtype=bool)
  558. gt_masks_ = np.zeros((2, 10, 10), np.uint8)
  559. gt_masks_[0, 0:7, 0:7] = 1
  560. gt_masks_[1, 2:7, 3:8] = 1
  561. gt_masks = BitmapMasks(gt_masks_.copy(), height=10, width=10)
  562. gt_seg_map = np.random.randint(0, 255, size=(10, 10), dtype=np.uint8)
  563. gt_instances_ids = np.array([0, 1], dtype=np.int64)
  564. src_results = {
  565. 'img': img,
  566. 'gt_bboxes': gt_bboxes,
  567. 'gt_bboxes_labels': gt_bboxes_labels,
  568. 'gt_ignore_flags': gt_ignore_flags,
  569. 'gt_masks': gt_masks,
  570. 'gt_seg_map': gt_seg_map,
  571. 'gt_instances_ids': gt_instances_ids
  572. }
  573. transform = RandomCrop(
  574. crop_size=(7, 5),
  575. allow_negative_crop=False,
  576. recompute_bbox=False,
  577. bbox_clip_border=True)
  578. results = transform(copy.deepcopy(src_results))
  579. h, w = results['img'].shape
  580. self.assertEqual(h, 5)
  581. self.assertEqual(w, 7)
  582. self.assertEqual(results['gt_bboxes'].shape[0], 2)
  583. self.assertEqual(results['gt_bboxes_labels'].shape[0], 2)
  584. self.assertEqual(results['gt_ignore_flags'].shape[0], 2)
  585. self.assertTupleEqual(results['gt_seg_map'].shape[:2], (5, 7))
  586. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  587. self.assertEqual(results['gt_instances_ids'].shape[0], 2)
  588. # test geometric transformation with homography matrix
  589. bboxes = copy.deepcopy(src_results['gt_bboxes'])
  590. self.assertTrue((bbox_project(bboxes, results['homography_matrix'],
  591. (5, 7)) == results['gt_bboxes']).all())
  592. # test recompute_bbox = True
  593. gt_masks_ = np.zeros((2, 10, 10), np.uint8)
  594. gt_masks = BitmapMasks(gt_masks_.copy(), height=10, width=10)
  595. gt_bboxes = np.array([[0.1, 0.1, 0.2, 0.2]])
  596. src_results = {
  597. 'img': img,
  598. 'gt_bboxes': gt_bboxes,
  599. 'gt_masks': gt_masks
  600. }
  601. target_gt_bboxes = np.zeros((1, 4), dtype=np.float32)
  602. transform = RandomCrop(
  603. crop_size=(10, 11),
  604. allow_negative_crop=False,
  605. recompute_bbox=True,
  606. bbox_clip_border=True)
  607. results = transform(copy.deepcopy(src_results))
  608. self.assertTrue((results['gt_bboxes'] == target_gt_bboxes).all())
  609. # test bbox_clip_border = False
  610. src_results = {'img': img, 'gt_bboxes': gt_bboxes}
  611. transform = RandomCrop(
  612. crop_size=(10, 11),
  613. allow_negative_crop=False,
  614. recompute_bbox=True,
  615. bbox_clip_border=False)
  616. results = transform(copy.deepcopy(src_results))
  617. self.assertTrue(
  618. (results['gt_bboxes'] == src_results['gt_bboxes']).all())
  619. # test the crop does not contain any gt-bbox
  620. # allow_negative_crop = False
  621. img = np.random.randint(0, 255, size=(10, 10), dtype=np.uint8)
  622. gt_bboxes = np.zeros((0, 4), dtype=np.float32)
  623. src_results = {'img': img, 'gt_bboxes': gt_bboxes}
  624. transform = RandomCrop(crop_size=(5, 3), allow_negative_crop=False)
  625. results = transform(copy.deepcopy(src_results))
  626. self.assertIsNone(results)
  627. # allow_negative_crop = True
  628. img = np.random.randint(0, 255, size=(10, 10), dtype=np.uint8)
  629. gt_bboxes = np.zeros((0, 4), dtype=np.float32)
  630. src_results = {'img': img, 'gt_bboxes': gt_bboxes}
  631. transform = RandomCrop(crop_size=(5, 3), allow_negative_crop=True)
  632. results = transform(copy.deepcopy(src_results))
  633. self.assertTrue(isinstance(results, dict))
  634. def test_transform_use_box_type(self):
  635. # test with gt_bboxes, gt_bboxes_labels, gt_ignore_flags,
  636. # gt_masks, gt_seg_map
  637. img = np.random.randint(0, 255, size=(10, 10), dtype=np.uint8)
  638. gt_bboxes = np.array([[0, 0, 7, 7], [2, 3, 9, 9]], dtype=np.float32)
  639. gt_bboxes_labels = np.array([0, 1], dtype=np.int64)
  640. gt_ignore_flags = np.array([0, 1], dtype=bool)
  641. gt_masks_ = np.zeros((2, 10, 10), np.uint8)
  642. gt_masks_[0, 0:7, 0:7] = 1
  643. gt_masks_[1, 2:7, 3:8] = 1
  644. gt_masks = BitmapMasks(gt_masks_.copy(), height=10, width=10)
  645. gt_seg_map = np.random.randint(0, 255, size=(10, 10), dtype=np.uint8)
  646. gt_instances_ids = np.array([0, 1], dtype=np.int64)
  647. src_results = {
  648. 'img': img,
  649. 'gt_bboxes': HorizontalBoxes(gt_bboxes),
  650. 'gt_bboxes_labels': gt_bboxes_labels,
  651. 'gt_ignore_flags': gt_ignore_flags,
  652. 'gt_masks': gt_masks,
  653. 'gt_seg_map': gt_seg_map,
  654. 'gt_instances_ids': gt_instances_ids
  655. }
  656. transform = RandomCrop(
  657. crop_size=(7, 5),
  658. allow_negative_crop=False,
  659. recompute_bbox=False,
  660. bbox_clip_border=True)
  661. results = transform(copy.deepcopy(src_results))
  662. h, w = results['img'].shape
  663. self.assertEqual(h, 5)
  664. self.assertEqual(w, 7)
  665. self.assertEqual(results['gt_bboxes'].shape[0], 2)
  666. self.assertEqual(results['gt_bboxes_labels'].shape[0], 2)
  667. self.assertEqual(results['gt_ignore_flags'].shape[0], 2)
  668. self.assertTupleEqual(results['gt_seg_map'].shape[:2], (5, 7))
  669. self.assertEqual(results['gt_instances_ids'].shape[0], 2)
  670. # test geometric transformation with homography matrix
  671. bboxes = copy.deepcopy(src_results['gt_bboxes'].numpy())
  672. print(bboxes, results['gt_bboxes'])
  673. self.assertTrue(
  674. (bbox_project(bboxes, results['homography_matrix'],
  675. (5, 7)) == results['gt_bboxes'].numpy()).all())
  676. # test recompute_bbox = True
  677. gt_masks_ = np.zeros((2, 10, 10), np.uint8)
  678. gt_masks = BitmapMasks(gt_masks_.copy(), height=10, width=10)
  679. gt_bboxes = HorizontalBoxes(np.array([[0.1, 0.1, 0.2, 0.2]]))
  680. src_results = {
  681. 'img': img,
  682. 'gt_bboxes': gt_bboxes,
  683. 'gt_masks': gt_masks
  684. }
  685. target_gt_bboxes = np.zeros((1, 4), dtype=np.float32)
  686. transform = RandomCrop(
  687. crop_size=(10, 11),
  688. allow_negative_crop=False,
  689. recompute_bbox=True,
  690. bbox_clip_border=True)
  691. results = transform(copy.deepcopy(src_results))
  692. self.assertTrue(
  693. (results['gt_bboxes'].numpy() == target_gt_bboxes).all())
  694. # test bbox_clip_border = False
  695. src_results = {'img': img, 'gt_bboxes': gt_bboxes}
  696. transform = RandomCrop(
  697. crop_size=(10, 10),
  698. allow_negative_crop=False,
  699. recompute_bbox=True,
  700. bbox_clip_border=False)
  701. results = transform(copy.deepcopy(src_results))
  702. self.assertTrue(
  703. (results['gt_bboxes'].numpy() == src_results['gt_bboxes'].numpy()
  704. ).all())
  705. # test the crop does not contain any gt-bbox
  706. # allow_negative_crop = False
  707. img = np.random.randint(0, 255, size=(10, 10), dtype=np.uint8)
  708. gt_bboxes = HorizontalBoxes(np.zeros((0, 4), dtype=np.float32))
  709. src_results = {'img': img, 'gt_bboxes': gt_bboxes}
  710. transform = RandomCrop(crop_size=(5, 2), allow_negative_crop=False)
  711. results = transform(copy.deepcopy(src_results))
  712. self.assertIsNone(results)
  713. # allow_negative_crop = True
  714. img = np.random.randint(0, 255, size=(10, 10), dtype=np.uint8)
  715. gt_bboxes = HorizontalBoxes(np.zeros((0, 4), dtype=np.float32))
  716. src_results = {'img': img, 'gt_bboxes': gt_bboxes}
  717. transform = RandomCrop(crop_size=(5, 2), allow_negative_crop=True)
  718. results = transform(copy.deepcopy(src_results))
  719. self.assertTrue(isinstance(results, dict))
  720. def test_repr(self):
  721. crop_type = 'absolute'
  722. crop_size = (10, 5)
  723. allow_negative_crop = False
  724. recompute_bbox = True
  725. bbox_clip_border = False
  726. transform = RandomCrop(
  727. crop_size=crop_size,
  728. crop_type=crop_type,
  729. allow_negative_crop=allow_negative_crop,
  730. recompute_bbox=recompute_bbox,
  731. bbox_clip_border=bbox_clip_border)
  732. self.assertEqual(
  733. repr(transform),
  734. f'RandomCrop(crop_size={crop_size}, crop_type={crop_type}, '
  735. f'allow_negative_crop={allow_negative_crop}, '
  736. f'recompute_bbox={recompute_bbox}, '
  737. f'bbox_clip_border={bbox_clip_border})')
  738. class TestCutOut(unittest.TestCase):
  739. def setUp(self):
  740. """Setup the model and optimizer which are used in every test method.
  741. TestCase calls functions in this order: setUp() -> testMethod() ->
  742. tearDown() -> cleanUp()
  743. """
  744. img = mmcv.imread(
  745. osp.join(osp.dirname(__file__), '../../data/color.jpg'), 'color')
  746. self.results = {'img': img}
  747. def test_transform(self):
  748. # test n_holes
  749. with self.assertRaises(AssertionError):
  750. transform = CutOut(n_holes=(5, 3), cutout_shape=(8, 8))
  751. with self.assertRaises(AssertionError):
  752. transform = CutOut(n_holes=(3, 4, 5), cutout_shape=(8, 8))
  753. # test cutout_shape and cutout_ratio
  754. with self.assertRaises(AssertionError):
  755. transform = CutOut(n_holes=1, cutout_shape=8)
  756. with self.assertRaises(AssertionError):
  757. transform = CutOut(n_holes=1, cutout_ratio=0.2)
  758. # either of cutout_shape and cutout_ratio should be given
  759. with self.assertRaises(AssertionError):
  760. transform = CutOut(n_holes=1)
  761. with self.assertRaises(AssertionError):
  762. transform = CutOut(
  763. n_holes=1, cutout_shape=(2, 2), cutout_ratio=(0.4, 0.4))
  764. transform = CutOut(n_holes=1, cutout_shape=(10, 10))
  765. results = transform(copy.deepcopy(self.results))
  766. self.assertTrue(results['img'].sum() < self.results['img'].sum())
  767. transform = CutOut(
  768. n_holes=(2, 4),
  769. cutout_shape=[(10, 10), (15, 15)],
  770. fill_in=(255, 255, 255))
  771. results = transform(copy.deepcopy(self.results))
  772. self.assertTrue(results['img'].sum() > self.results['img'].sum())
  773. transform = CutOut(
  774. n_holes=1, cutout_ratio=(0.8, 0.8), fill_in=(255, 255, 255))
  775. results = transform(copy.deepcopy(self.results))
  776. self.assertTrue(results['img'].sum() > self.results['img'].sum())
  777. def test_repr(self):
  778. transform = CutOut(n_holes=1, cutout_shape=(10, 10))
  779. self.assertEqual(
  780. repr(transform), ('CutOut(n_holes=(1, 1), '
  781. 'cutout_shape=[(10, 10)], '
  782. 'fill_in=(0, 0, 0))'))
  783. transform = CutOut(
  784. n_holes=1, cutout_ratio=(0.8, 0.8), fill_in=(255, 255, 255))
  785. self.assertEqual(
  786. repr(transform), ('CutOut(n_holes=(1, 1), '
  787. 'cutout_ratio=[(0.8, 0.8)], '
  788. 'fill_in=(255, 255, 255))'))
  789. class TestMosaic(unittest.TestCase):
  790. def setUp(self):
  791. """Setup the model and optimizer which are used in every test method.
  792. TestCase calls functions in this order: setUp() -> testMethod() ->
  793. tearDown() -> cleanUp()
  794. """
  795. rng = np.random.RandomState(0)
  796. self.results = {
  797. 'img':
  798. np.random.random((224, 224, 3)),
  799. 'img_shape': (224, 224),
  800. 'gt_bboxes_labels':
  801. np.array([1, 2, 3], dtype=np.int64),
  802. 'gt_bboxes':
  803. np.array([[10, 10, 20, 20], [20, 20, 40, 40], [40, 40, 80, 80]],
  804. dtype=np.float32),
  805. 'gt_ignore_flags':
  806. np.array([0, 0, 1], dtype=bool),
  807. 'gt_masks':
  808. BitmapMasks(rng.rand(3, 224, 224), height=224, width=224),
  809. }
  810. def test_transform(self):
  811. # test assertion for invalid img_scale
  812. with self.assertRaises(AssertionError):
  813. transform = Mosaic(img_scale=640)
  814. # test assertion for invalid probability
  815. with self.assertRaises(AssertionError):
  816. transform = Mosaic(prob=1.5)
  817. transform = Mosaic(img_scale=(12, 10))
  818. # test assertion for invalid mix_results
  819. with self.assertRaises(AssertionError):
  820. results = transform(copy.deepcopy(self.results))
  821. self.results['mix_results'] = [copy.deepcopy(self.results)] * 3
  822. results = transform(copy.deepcopy(self.results))
  823. self.assertTrue(results['img'].shape[:2] == (20, 24))
  824. self.assertTrue(results['gt_bboxes_labels'].shape[0] ==
  825. results['gt_bboxes'].shape[0])
  826. self.assertTrue(results['gt_bboxes_labels'].dtype == np.int64)
  827. self.assertTrue(results['gt_bboxes'].dtype == np.float32)
  828. self.assertTrue(results['gt_ignore_flags'].dtype == bool)
  829. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  830. def test_transform_with_no_gt(self):
  831. self.results['gt_bboxes'] = np.empty((0, 4), dtype=np.float32)
  832. self.results['gt_bboxes_labels'] = np.empty((0, ), dtype=np.int64)
  833. self.results['gt_ignore_flags'] = np.empty((0, ), dtype=bool)
  834. transform = Mosaic(img_scale=(12, 10))
  835. self.results['mix_results'] = [copy.deepcopy(self.results)] * 3
  836. results = transform(copy.deepcopy(self.results))
  837. self.assertIsInstance(results, dict)
  838. self.assertTrue(results['img'].shape[:2] == (20, 24))
  839. self.assertTrue(
  840. results['gt_bboxes_labels'].shape[0] == results['gt_bboxes'].
  841. shape[0] == results['gt_ignore_flags'].shape[0] == 0)
  842. self.assertTrue(results['gt_bboxes_labels'].dtype == np.int64)
  843. self.assertTrue(results['gt_bboxes'].dtype == np.float32)
  844. self.assertTrue(results['gt_ignore_flags'].dtype == bool)
  845. def test_transform_use_box_type(self):
  846. transform = Mosaic(img_scale=(12, 10))
  847. results = copy.deepcopy(self.results)
  848. results['gt_bboxes'] = HorizontalBoxes(results['gt_bboxes'])
  849. results['mix_results'] = [results] * 3
  850. results = transform(results)
  851. self.assertTrue(results['img'].shape[:2] == (20, 24))
  852. self.assertTrue(results['gt_bboxes_labels'].shape[0] ==
  853. results['gt_bboxes'].shape[0])
  854. self.assertTrue(results['gt_bboxes_labels'].dtype == np.int64)
  855. self.assertTrue(results['gt_bboxes'].dtype == torch.float32)
  856. self.assertTrue(results['gt_ignore_flags'].dtype == bool)
  857. def test_repr(self):
  858. transform = Mosaic(img_scale=(640, 640), )
  859. self.assertEqual(
  860. repr(transform), ('Mosaic(img_scale=(640, 640), '
  861. 'center_ratio_range=(0.5, 1.5), '
  862. 'pad_val=114.0, '
  863. 'prob=1.0)'))
  864. class TestMixUp(unittest.TestCase):
  865. def setUp(self):
  866. """Setup the model and optimizer which are used in every test method.
  867. TestCase calls functions in this order: setUp() -> testMethod() ->
  868. tearDown() -> cleanUp()
  869. """
  870. rng = np.random.RandomState(0)
  871. self.results = {
  872. 'img':
  873. np.random.random((224, 224, 3)),
  874. 'img_shape': (224, 224),
  875. 'gt_bboxes_labels':
  876. np.array([1, 2, 3], dtype=np.int64),
  877. 'gt_bboxes':
  878. np.array([[10, 10, 20, 20], [20, 20, 40, 40], [40, 40, 80, 80]],
  879. dtype=np.float32),
  880. 'gt_ignore_flags':
  881. np.array([0, 0, 1], dtype=bool),
  882. 'gt_masks':
  883. BitmapMasks(rng.rand(3, 224, 224), height=224, width=224),
  884. }
  885. def test_transform(self):
  886. # test assertion for invalid img_scale
  887. with self.assertRaises(AssertionError):
  888. transform = MixUp(img_scale=640)
  889. transform = MixUp(img_scale=(12, 10))
  890. # test assertion for invalid mix_results
  891. with self.assertRaises(AssertionError):
  892. results = transform(copy.deepcopy(self.results))
  893. with self.assertRaises(AssertionError):
  894. self.results['mix_results'] = [copy.deepcopy(self.results)] * 2
  895. results = transform(copy.deepcopy(self.results))
  896. self.results['mix_results'] = [copy.deepcopy(self.results)]
  897. results = transform(copy.deepcopy(self.results))
  898. self.assertTrue(results['img'].shape[:2] == (224, 224))
  899. self.assertTrue(results['gt_bboxes_labels'].shape[0] ==
  900. results['gt_bboxes'].shape[0])
  901. self.assertTrue(results['gt_bboxes_labels'].dtype == np.int64)
  902. self.assertTrue(results['gt_bboxes'].dtype == np.float32)
  903. self.assertTrue(results['gt_ignore_flags'].dtype == bool)
  904. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  905. def test_transform_use_box_type(self):
  906. results = copy.deepcopy(self.results)
  907. results['gt_bboxes'] = HorizontalBoxes(results['gt_bboxes'])
  908. transform = MixUp(img_scale=(12, 10))
  909. results['mix_results'] = [results]
  910. results = transform(results)
  911. self.assertTrue(results['img'].shape[:2] == (224, 224))
  912. self.assertTrue(results['gt_bboxes_labels'].shape[0] ==
  913. results['gt_bboxes'].shape[0])
  914. self.assertTrue(results['gt_bboxes_labels'].dtype == np.int64)
  915. self.assertTrue(results['gt_bboxes'].dtype == torch.float32)
  916. self.assertTrue(results['gt_ignore_flags'].dtype == bool)
  917. def test_repr(self):
  918. transform = MixUp(
  919. img_scale=(640, 640),
  920. ratio_range=(0.8, 1.6),
  921. pad_val=114.0,
  922. )
  923. self.assertEqual(
  924. repr(transform), ('MixUp(dynamic_scale=(640, 640), '
  925. 'ratio_range=(0.8, 1.6), '
  926. 'flip_ratio=0.5, '
  927. 'pad_val=114.0, '
  928. 'max_iters=15, '
  929. 'bbox_clip_border=True)'))
  930. class TestRandomAffine(unittest.TestCase):
  931. def setUp(self):
  932. """Setup the model and optimizer which are used in every test method.
  933. TestCase calls functions in this order: setUp() -> testMethod() ->
  934. tearDown() -> cleanUp()
  935. """
  936. self.results = {
  937. 'img':
  938. np.random.random((224, 224, 3)),
  939. 'img_shape': (224, 224),
  940. 'gt_bboxes_labels':
  941. np.array([1, 2, 3], dtype=np.int64),
  942. 'gt_bboxes':
  943. np.array([[10, 10, 20, 20], [20, 20, 40, 40], [40, 40, 80, 80]],
  944. dtype=np.float32),
  945. 'gt_ignore_flags':
  946. np.array([0, 0, 1], dtype=bool),
  947. }
  948. def test_transform(self):
  949. # test assertion for invalid translate_ratio
  950. with self.assertRaises(AssertionError):
  951. transform = RandomAffine(max_translate_ratio=1.5)
  952. # test assertion for invalid scaling_ratio_range
  953. with self.assertRaises(AssertionError):
  954. transform = RandomAffine(scaling_ratio_range=(1.5, 0.5))
  955. with self.assertRaises(AssertionError):
  956. transform = RandomAffine(scaling_ratio_range=(0, 0.5))
  957. transform = RandomAffine()
  958. results = transform(copy.deepcopy(self.results))
  959. self.assertTrue(results['img'].shape[:2] == (224, 224))
  960. self.assertTrue(results['gt_bboxes_labels'].shape[0] ==
  961. results['gt_bboxes'].shape[0])
  962. self.assertTrue(results['gt_bboxes_labels'].dtype == np.int64)
  963. self.assertTrue(results['gt_bboxes'].dtype == np.float32)
  964. self.assertTrue(results['gt_ignore_flags'].dtype == bool)
  965. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  966. def test_transform_use_box_type(self):
  967. results = copy.deepcopy(self.results)
  968. results['gt_bboxes'] = HorizontalBoxes(results['gt_bboxes'])
  969. transform = RandomAffine()
  970. results = transform(copy.deepcopy(results))
  971. self.assertTrue(results['img'].shape[:2] == (224, 224))
  972. self.assertTrue(results['gt_bboxes_labels'].shape[0] ==
  973. results['gt_bboxes'].shape[0])
  974. self.assertTrue(results['gt_bboxes_labels'].dtype == np.int64)
  975. self.assertTrue(results['gt_bboxes'].dtype == torch.float32)
  976. self.assertTrue(results['gt_ignore_flags'].dtype == bool)
  977. def test_repr(self):
  978. transform = RandomAffine(
  979. scaling_ratio_range=(0.1, 2),
  980. border=(-320, -320),
  981. )
  982. self.assertEqual(
  983. repr(transform), ('RandomAffine(max_rotate_degree=10.0, '
  984. 'max_translate_ratio=0.1, '
  985. 'scaling_ratio_range=(0.1, 2), '
  986. 'max_shear_degree=2.0, '
  987. 'border=(-320, -320), '
  988. 'border_val=(114, 114, 114), '
  989. 'bbox_clip_border=True)'))
  990. class TestYOLOXHSVRandomAug(unittest.TestCase):
  991. def setUp(self):
  992. """Setup the model and optimizer which are used in every test method.
  993. TestCase calls functions in this order: setUp() -> testMethod() ->
  994. tearDown() -> cleanUp()
  995. """
  996. img = mmcv.imread(
  997. osp.join(osp.dirname(__file__), '../../data/color.jpg'), 'color')
  998. self.results = {
  999. 'img':
  1000. img,
  1001. 'img_shape': (224, 224),
  1002. 'gt_bboxes_labels':
  1003. np.array([1, 2, 3], dtype=np.int64),
  1004. 'gt_bboxes':
  1005. np.array([[10, 10, 20, 20], [20, 20, 40, 40], [40, 40, 80, 80]],
  1006. dtype=np.float32),
  1007. 'gt_ignore_flags':
  1008. np.array([0, 0, 1], dtype=bool),
  1009. }
  1010. def test_transform(self):
  1011. transform = YOLOXHSVRandomAug()
  1012. results = transform(copy.deepcopy(self.results))
  1013. self.assertTrue(
  1014. results['img'].shape[:2] == self.results['img'].shape[:2])
  1015. self.assertTrue(results['gt_bboxes_labels'].shape[0] ==
  1016. results['gt_bboxes'].shape[0])
  1017. self.assertTrue(results['gt_bboxes_labels'].dtype == np.int64)
  1018. self.assertTrue(results['gt_bboxes'].dtype == np.float32)
  1019. self.assertTrue(results['gt_ignore_flags'].dtype == bool)
  1020. def test_repr(self):
  1021. transform = YOLOXHSVRandomAug()
  1022. self.assertEqual(
  1023. repr(transform), ('YOLOXHSVRandomAug(hue_delta=5, '
  1024. 'saturation_delta=30, '
  1025. 'value_delta=30)'))
  1026. class TestRandomCenterCropPad(unittest.TestCase):
  1027. def test_init(self):
  1028. # test assertion for invalid crop_size while test_mode=False
  1029. with self.assertRaises(AssertionError):
  1030. RandomCenterCropPad(
  1031. crop_size=(-1, 0), test_mode=False, test_pad_mode=None)
  1032. # test assertion for invalid ratios while test_mode=False
  1033. with self.assertRaises(AssertionError):
  1034. RandomCenterCropPad(
  1035. crop_size=(511, 511),
  1036. ratios=(1.0, 1.0),
  1037. test_mode=False,
  1038. test_pad_mode=None)
  1039. # test assertion for invalid mean, std and to_rgb
  1040. with self.assertRaises(AssertionError):
  1041. RandomCenterCropPad(
  1042. crop_size=(511, 511),
  1043. mean=None,
  1044. std=None,
  1045. to_rgb=None,
  1046. test_mode=False,
  1047. test_pad_mode=None)
  1048. # test assertion for invalid crop_size while test_mode=True
  1049. with self.assertRaises(AssertionError):
  1050. RandomCenterCropPad(
  1051. crop_size=(511, 511),
  1052. ratios=None,
  1053. border=None,
  1054. mean=[123.675, 116.28, 103.53],
  1055. std=[58.395, 57.12, 57.375],
  1056. to_rgb=True,
  1057. test_mode=True,
  1058. test_pad_mode=('logical_or', 127))
  1059. # test assertion for invalid ratios while test_mode=True
  1060. with self.assertRaises(AssertionError):
  1061. RandomCenterCropPad(
  1062. crop_size=None,
  1063. ratios=(0.9, 1.0, 1.1),
  1064. border=None,
  1065. mean=[123.675, 116.28, 103.53],
  1066. std=[58.395, 57.12, 57.375],
  1067. to_rgb=True,
  1068. test_mode=True,
  1069. test_pad_mode=('logical_or', 127))
  1070. # test assertion for invalid border while test_mode=True
  1071. with self.assertRaises(AssertionError):
  1072. RandomCenterCropPad(
  1073. crop_size=None,
  1074. ratios=None,
  1075. border=128,
  1076. mean=[123.675, 116.28, 103.53],
  1077. std=[58.395, 57.12, 57.375],
  1078. to_rgb=True,
  1079. test_mode=True,
  1080. test_pad_mode=('logical_or', 127))
  1081. # test assertion for invalid test_pad_mode while test_mode=True
  1082. with self.assertRaises(AssertionError):
  1083. RandomCenterCropPad(
  1084. crop_size=None,
  1085. ratios=None,
  1086. border=None,
  1087. mean=[123.675, 116.28, 103.53],
  1088. std=[58.395, 57.12, 57.375],
  1089. to_rgb=True,
  1090. test_mode=True,
  1091. test_pad_mode=('do_nothing', 100))
  1092. def test_transform(self):
  1093. results = dict(
  1094. img_path=osp.join(osp.dirname(__file__), '../../data/color.jpg'))
  1095. load = LoadImageFromFile(to_float32=True)
  1096. results = load(results)
  1097. test_results = copy.deepcopy(results)
  1098. h, w = results['img_shape']
  1099. gt_bboxes = create_random_bboxes(4, w, h)
  1100. gt_bboxes_labels = np.array([1, 2, 3, 1], dtype=np.int64)
  1101. gt_ignore_flags = np.array([0, 0, 1, 1], dtype=bool)
  1102. results['gt_bboxes'] = gt_bboxes
  1103. results['gt_bboxes_labels'] = gt_bboxes_labels
  1104. results['gt_ignore_flags'] = gt_ignore_flags
  1105. crop_module = RandomCenterCropPad(
  1106. crop_size=(w - 20, h - 20),
  1107. ratios=(1.0, ),
  1108. border=128,
  1109. mean=[123.675, 116.28, 103.53],
  1110. std=[58.395, 57.12, 57.375],
  1111. to_rgb=True,
  1112. test_mode=False,
  1113. test_pad_mode=None)
  1114. train_results = crop_module(results)
  1115. assert train_results['img'].shape[:2] == (h - 20, w - 20)
  1116. # All bboxes should be reserved after crop
  1117. assert train_results['img_shape'][:2] == (h - 20, w - 20)
  1118. assert train_results['gt_bboxes'].shape[0] == 4
  1119. assert train_results['gt_bboxes'].dtype == np.float32
  1120. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  1121. crop_module = RandomCenterCropPad(
  1122. crop_size=None,
  1123. ratios=None,
  1124. border=None,
  1125. mean=[123.675, 116.28, 103.53],
  1126. std=[58.395, 57.12, 57.375],
  1127. to_rgb=True,
  1128. test_mode=True,
  1129. test_pad_mode=('logical_or', 127))
  1130. test_results = crop_module(test_results)
  1131. assert test_results['img'].shape[:2] == (h | 127, w | 127)
  1132. assert test_results['img_shape'][:2] == (h | 127, w | 127)
  1133. assert 'border' in test_results
  1134. def test_transform_use_box_type(self):
  1135. results = dict(
  1136. img_path=osp.join(osp.dirname(__file__), '../../data/color.jpg'))
  1137. load = LoadImageFromFile(to_float32=True)
  1138. results = load(results)
  1139. test_results = copy.deepcopy(results)
  1140. h, w = results['img_shape']
  1141. gt_bboxes = create_random_bboxes(4, w, h)
  1142. gt_bboxes_labels = np.array([1, 2, 3, 1], dtype=np.int64)
  1143. gt_ignore_flags = np.array([0, 0, 1, 1], dtype=bool)
  1144. results['gt_bboxes'] = HorizontalBoxes(gt_bboxes)
  1145. results['gt_bboxes_labels'] = gt_bboxes_labels
  1146. results['gt_ignore_flags'] = gt_ignore_flags
  1147. crop_module = RandomCenterCropPad(
  1148. crop_size=(w - 20, h - 20),
  1149. ratios=(1.0, ),
  1150. border=128,
  1151. mean=[123.675, 116.28, 103.53],
  1152. std=[58.395, 57.12, 57.375],
  1153. to_rgb=True,
  1154. test_mode=False,
  1155. test_pad_mode=None)
  1156. train_results = crop_module(results)
  1157. assert train_results['img'].shape[:2] == (h - 20, w - 20)
  1158. # All bboxes should be reserved after crop
  1159. assert train_results['img_shape'][:2] == (h - 20, w - 20)
  1160. assert train_results['gt_bboxes'].shape[0] == 4
  1161. assert train_results['gt_bboxes'].dtype == torch.float32
  1162. crop_module = RandomCenterCropPad(
  1163. crop_size=None,
  1164. ratios=None,
  1165. border=None,
  1166. mean=[123.675, 116.28, 103.53],
  1167. std=[58.395, 57.12, 57.375],
  1168. to_rgb=True,
  1169. test_mode=True,
  1170. test_pad_mode=('logical_or', 127))
  1171. test_results = crop_module(test_results)
  1172. assert test_results['img'].shape[:2] == (h | 127, w | 127)
  1173. assert test_results['img_shape'][:2] == (h | 127, w | 127)
  1174. assert 'border' in test_results
  1175. class TestCopyPaste(unittest.TestCase):
  1176. def setUp(self):
  1177. """Setup the model and optimizer which are used in every test method.
  1178. TestCase calls functions in this order: setUp() -> testMethod() ->
  1179. tearDown() -> cleanUp()
  1180. """
  1181. img = mmcv.imread(
  1182. osp.join(osp.dirname(__file__), '../../data/color.jpg'), 'color')
  1183. h, w, _ = img.shape
  1184. dst_bboxes = np.array([[0.2 * w, 0.2 * h, 0.4 * w, 0.4 * h],
  1185. [0.5 * w, 0.5 * h, 0.6 * w, 0.6 * h]],
  1186. dtype=np.float32)
  1187. src_bboxes = np.array([[0.1 * w, 0.1 * h, 0.3 * w, 0.5 * h],
  1188. [0.4 * w, 0.4 * h, 0.7 * w, 0.7 * h],
  1189. [0.8 * w, 0.8 * h, 0.9 * w, 0.9 * h]],
  1190. dtype=np.float32)
  1191. self.dst_results = {
  1192. 'img': img.copy(),
  1193. 'gt_bboxes': dst_bboxes,
  1194. 'gt_bboxes_labels': np.ones(dst_bboxes.shape[0], dtype=np.int64),
  1195. 'gt_masks': create_full_masks(dst_bboxes, w, h),
  1196. 'gt_ignore_flags': np.array([0, 1], dtype=bool),
  1197. }
  1198. self.src_results = {
  1199. 'img': img.copy(),
  1200. 'gt_bboxes': src_bboxes,
  1201. 'gt_bboxes_labels':
  1202. np.ones(src_bboxes.shape[0], dtype=np.int64) * 2,
  1203. 'gt_masks': create_full_masks(src_bboxes, w, h),
  1204. 'gt_ignore_flags': np.array([0, 0, 1], dtype=bool),
  1205. }
  1206. def test_transform(self):
  1207. transform = CopyPaste(selected=False)
  1208. # test assertion for invalid mix_results
  1209. with self.assertRaises(AssertionError):
  1210. results = transform(copy.deepcopy(self.dst_results))
  1211. results = copy.deepcopy(self.dst_results)
  1212. results['mix_results'] = [copy.deepcopy(self.src_results)]
  1213. results = transform(results)
  1214. self.assertEqual(results['img'].shape[:2],
  1215. self.dst_results['img'].shape[:2])
  1216. # one object of destination image is totally occluded
  1217. self.assertEqual(
  1218. results['gt_bboxes'].shape[0],
  1219. self.dst_results['gt_bboxes'].shape[0] +
  1220. self.src_results['gt_bboxes'].shape[0] - 1)
  1221. self.assertEqual(
  1222. results['gt_bboxes_labels'].shape[0],
  1223. self.dst_results['gt_bboxes_labels'].shape[0] +
  1224. self.src_results['gt_bboxes_labels'].shape[0] - 1)
  1225. self.assertEqual(
  1226. results['gt_masks'].masks.shape[0],
  1227. self.dst_results['gt_masks'].masks.shape[0] +
  1228. self.src_results['gt_masks'].masks.shape[0] - 1)
  1229. self.assertEqual(
  1230. results['gt_ignore_flags'].shape[0],
  1231. self.dst_results['gt_ignore_flags'].shape[0] +
  1232. self.src_results['gt_ignore_flags'].shape[0] - 1)
  1233. # the object of destination image is partially occluded
  1234. ori_bbox = self.dst_results['gt_bboxes'][0]
  1235. occ_bbox = results['gt_bboxes'][0]
  1236. ori_mask = self.dst_results['gt_masks'].masks[0]
  1237. occ_mask = results['gt_masks'].masks[0]
  1238. self.assertTrue(ori_mask.sum() > occ_mask.sum())
  1239. self.assertTrue(
  1240. np.all(np.abs(occ_bbox - ori_bbox) <= transform.bbox_occluded_thr)
  1241. or occ_mask.sum() > transform.mask_occluded_thr)
  1242. # test copypaste with selected objects
  1243. transform = CopyPaste()
  1244. results = copy.deepcopy(self.dst_results)
  1245. results['mix_results'] = [copy.deepcopy(self.src_results)]
  1246. results = transform(results)
  1247. # test copypaste with an empty source image
  1248. results = copy.deepcopy(self.dst_results)
  1249. valid_inds = [False] * self.src_results['gt_bboxes'].shape[0]
  1250. results['mix_results'] = [{
  1251. 'img':
  1252. self.src_results['img'].copy(),
  1253. 'gt_bboxes':
  1254. self.src_results['gt_bboxes'][valid_inds],
  1255. 'gt_bboxes_labels':
  1256. self.src_results['gt_bboxes_labels'][valid_inds],
  1257. 'gt_masks':
  1258. self.src_results['gt_masks'][valid_inds],
  1259. 'gt_ignore_flags':
  1260. self.src_results['gt_ignore_flags'][valid_inds],
  1261. }]
  1262. results = transform(results)
  1263. # test copypaste with an empty mask results
  1264. transform = CopyPaste()
  1265. results = copy.deepcopy(self.dst_results)
  1266. results = {k: v for k, v in results.items() if 'mask' not in k}
  1267. results['mix_results'] = [copy.deepcopy(self.src_results)]
  1268. with self.assertRaises(RuntimeError):
  1269. results = transform(results)
  1270. # test copypaste with boxes as masks
  1271. transform = CopyPaste(paste_by_box=True)
  1272. results = copy.deepcopy(self.dst_results)
  1273. results = {k: v for k, v in results.items() if 'mask' not in k}
  1274. src_results = copy.deepcopy(self.src_results)
  1275. src_results = {k: v for k, v in src_results.items() if 'mask' not in k}
  1276. results['mix_results'] = [src_results]
  1277. results = transform(results)
  1278. self.assertEqual(results['img'].shape[:2],
  1279. self.dst_results['img'].shape[:2])
  1280. def test_transform_use_box_type(self):
  1281. src_results = copy.deepcopy(self.src_results)
  1282. src_results['gt_bboxes'] = HorizontalBoxes(src_results['gt_bboxes'])
  1283. dst_results = copy.deepcopy(self.dst_results)
  1284. dst_results['gt_bboxes'] = HorizontalBoxes(dst_results['gt_bboxes'])
  1285. transform = CopyPaste(selected=False)
  1286. results = copy.deepcopy(dst_results)
  1287. results['mix_results'] = [copy.deepcopy(src_results)]
  1288. results = transform(results)
  1289. self.assertEqual(results['img'].shape[:2],
  1290. self.dst_results['img'].shape[:2])
  1291. # one object of destination image is totally occluded
  1292. self.assertEqual(
  1293. results['gt_bboxes'].shape[0],
  1294. self.dst_results['gt_bboxes'].shape[0] +
  1295. self.src_results['gt_bboxes'].shape[0] - 1)
  1296. self.assertEqual(
  1297. results['gt_bboxes_labels'].shape[0],
  1298. self.dst_results['gt_bboxes_labels'].shape[0] +
  1299. self.src_results['gt_bboxes_labels'].shape[0] - 1)
  1300. self.assertEqual(
  1301. results['gt_masks'].masks.shape[0],
  1302. self.dst_results['gt_masks'].masks.shape[0] +
  1303. self.src_results['gt_masks'].masks.shape[0] - 1)
  1304. self.assertEqual(
  1305. results['gt_ignore_flags'].shape[0],
  1306. self.dst_results['gt_ignore_flags'].shape[0] +
  1307. self.src_results['gt_ignore_flags'].shape[0] - 1)
  1308. # the object of destination image is partially occluded
  1309. ori_bbox = dst_results['gt_bboxes'][0].numpy()
  1310. occ_bbox = results['gt_bboxes'][0].numpy()
  1311. ori_mask = dst_results['gt_masks'].masks[0]
  1312. occ_mask = results['gt_masks'].masks[0]
  1313. self.assertTrue(ori_mask.sum() > occ_mask.sum())
  1314. self.assertTrue(
  1315. np.all(np.abs(occ_bbox - ori_bbox) <= transform.bbox_occluded_thr)
  1316. or occ_mask.sum() > transform.mask_occluded_thr)
  1317. # test copypaste with selected objects
  1318. transform = CopyPaste()
  1319. results = copy.deepcopy(dst_results)
  1320. results['mix_results'] = [copy.deepcopy(src_results)]
  1321. results = transform(results)
  1322. # test copypaste with an empty source image
  1323. results = copy.deepcopy(dst_results)
  1324. valid_inds = [False] * self.src_results['gt_bboxes'].shape[0]
  1325. results['mix_results'] = [{
  1326. 'img':
  1327. src_results['img'].copy(),
  1328. 'gt_bboxes':
  1329. src_results['gt_bboxes'][valid_inds],
  1330. 'gt_bboxes_labels':
  1331. src_results['gt_bboxes_labels'][valid_inds],
  1332. 'gt_masks':
  1333. src_results['gt_masks'][valid_inds],
  1334. 'gt_ignore_flags':
  1335. src_results['gt_ignore_flags'][valid_inds],
  1336. }]
  1337. results = transform(results)
  1338. def test_repr(self):
  1339. transform = CopyPaste()
  1340. self.assertEqual(
  1341. repr(transform), ('CopyPaste(max_num_pasted=100, '
  1342. 'bbox_occluded_thr=10, '
  1343. 'mask_occluded_thr=300, '
  1344. 'selected=True), '
  1345. 'paste_by_box=False)'))
  1346. class TestAlbu(unittest.TestCase):
  1347. @unittest.skipIf(albumentations is None, 'albumentations is not installed')
  1348. def test_transform(self):
  1349. results = dict(
  1350. img_path=osp.join(osp.dirname(__file__), '../../data/color.jpg'))
  1351. # Define simple pipeline
  1352. load = dict(type='LoadImageFromFile')
  1353. load = TRANSFORMS.build(load)
  1354. albu_transform = dict(
  1355. type='Albu', transforms=[dict(type='ChannelShuffle', p=1)])
  1356. albu_transform = TRANSFORMS.build(albu_transform)
  1357. # Execute transforms
  1358. results = load(results)
  1359. results = albu_transform(results)
  1360. self.assertEqual(results['img'].dtype, np.uint8)
  1361. # test bbox
  1362. albu_transform = dict(
  1363. type='Albu',
  1364. transforms=[dict(type='ChannelShuffle', p=1)],
  1365. bbox_params=dict(
  1366. type='BboxParams',
  1367. format='pascal_voc',
  1368. label_fields=['gt_bboxes_labels', 'gt_ignore_flags']),
  1369. keymap={
  1370. 'img': 'image',
  1371. 'gt_bboxes': 'bboxes'
  1372. })
  1373. albu_transform = TRANSFORMS.build(albu_transform)
  1374. results = {
  1375. 'img':
  1376. np.random.random((224, 224, 3)),
  1377. 'img_shape': (224, 224),
  1378. 'gt_bboxes_labels':
  1379. np.array([1, 2, 3], dtype=np.int64),
  1380. 'gt_bboxes':
  1381. np.array([[10, 10, 20, 20], [20, 20, 40, 40], [40, 40, 80, 80]],
  1382. dtype=np.float32),
  1383. 'gt_ignore_flags':
  1384. np.array([0, 0, 1], dtype=bool),
  1385. }
  1386. results = albu_transform(results)
  1387. self.assertEqual(results['img'].dtype, np.float64)
  1388. self.assertEqual(results['gt_bboxes'].dtype, np.float32)
  1389. self.assertEqual(results['gt_ignore_flags'].dtype, bool)
  1390. self.assertEqual(results['gt_bboxes_labels'].dtype, np.int64)
  1391. self.assertEqual(results['img_shape'], results['img'].shape[:2])
  1392. @unittest.skipIf(albumentations is None, 'albumentations is not installed')
  1393. def test_repr(self):
  1394. albu_transform = dict(
  1395. type='Albu', transforms=[dict(type='ChannelShuffle', p=1)])
  1396. albu_transform = TRANSFORMS.build(albu_transform)
  1397. self.assertEqual(
  1398. repr(albu_transform), 'Albu(transforms=['
  1399. '{\'type\': \'ChannelShuffle\', '
  1400. '\'p\': 1}])')
  1401. class TestCorrupt(unittest.TestCase):
  1402. def test_transform(self):
  1403. results = dict(
  1404. img_path=osp.join(osp.dirname(__file__), '../../data/color.jpg'))
  1405. # Define simple pipeline
  1406. load = dict(type='LoadImageFromFile')
  1407. load = TRANSFORMS.build(load)
  1408. corrupt_transform = dict(type='Corrupt', corruption='gaussian_blur')
  1409. corrupt_transform = TRANSFORMS.build(corrupt_transform)
  1410. # Execute transforms
  1411. results = load(results)
  1412. results = corrupt_transform(results)
  1413. self.assertEqual(results['img'].dtype, np.uint8)
  1414. def test_repr(self):
  1415. corrupt_transform = dict(type='Corrupt', corruption='gaussian_blur')
  1416. corrupt_transform = TRANSFORMS.build(corrupt_transform)
  1417. self.assertEqual(
  1418. repr(corrupt_transform), 'Corrupt(corruption=gaussian_blur, '
  1419. 'severity=1)')
  1420. class TestRandomShift(unittest.TestCase):
  1421. def test_init(self):
  1422. # test assertion for invalid shift_ratio
  1423. with self.assertRaises(AssertionError):
  1424. RandomShift(prob=1.5)
  1425. # test assertion for invalid max_shift_px
  1426. with self.assertRaises(AssertionError):
  1427. RandomShift(max_shift_px=-1)
  1428. def test_transform(self):
  1429. results = dict()
  1430. img = mmcv.imread(
  1431. osp.join(osp.dirname(__file__), '../../data/color.jpg'), 'color')
  1432. results['img'] = img
  1433. h, w, _ = img.shape
  1434. gt_bboxes = create_random_bboxes(8, w, h)
  1435. results['gt_bboxes_labels'] = np.ones(
  1436. gt_bboxes.shape[0], dtype=np.int64)
  1437. results['gt_bboxes'] = gt_bboxes
  1438. transform = RandomShift(prob=1.0)
  1439. results = transform(results)
  1440. self.assertEqual(results['img'].shape[:2], (h, w))
  1441. self.assertEqual(results['gt_bboxes_labels'].shape[0],
  1442. results['gt_bboxes'].shape[0])
  1443. self.assertEqual(results['gt_bboxes_labels'].dtype, np.int64)
  1444. self.assertEqual(results['gt_bboxes'].dtype, np.float32)
  1445. def test_transform_use_box_type(self):
  1446. results = dict()
  1447. img = mmcv.imread(
  1448. osp.join(osp.dirname(__file__), '../../data/color.jpg'), 'color')
  1449. results['img'] = img
  1450. h, w, _ = img.shape
  1451. gt_bboxes = create_random_bboxes(8, w, h)
  1452. results['gt_bboxes_labels'] = np.ones(
  1453. gt_bboxes.shape[0], dtype=np.int64)
  1454. results['gt_bboxes'] = HorizontalBoxes(gt_bboxes)
  1455. transform = RandomShift(prob=1.0)
  1456. results = transform(results)
  1457. self.assertEqual(results['img'].shape[:2], (h, w))
  1458. self.assertEqual(results['gt_bboxes_labels'].shape[0],
  1459. results['gt_bboxes'].shape[0])
  1460. self.assertEqual(results['gt_bboxes_labels'].dtype, np.int64)
  1461. self.assertEqual(results['gt_bboxes'].dtype, torch.float32)
  1462. def test_repr(self):
  1463. transform = RandomShift()
  1464. self.assertEqual(
  1465. repr(transform), ('RandomShift(prob=0.5, '
  1466. 'max_shift_px=32, '
  1467. 'filter_thr_px=1)'))
  1468. class TestRandomErasing(unittest.TestCase):
  1469. def setUp(self):
  1470. """Setup the model and optimizer which are used in every test method.
  1471. TestCase calls functions in this order: setUp() -> testMethod() ->
  1472. tearDown() -> cleanUp()
  1473. """
  1474. self.results = construct_toy_data(poly2mask=True)
  1475. def test_transform(self):
  1476. transform = RandomErasing(
  1477. n_patches=(1, 5), ratio=(0.4, 0.8), img_border_value=0)
  1478. results = transform(copy.deepcopy(self.results))
  1479. self.assertTrue(results['img'].sum() < self.results['img'].sum())
  1480. transform = RandomErasing(
  1481. n_patches=1, ratio=0.999, img_border_value=255)
  1482. results = transform(copy.deepcopy(self.results))
  1483. self.assertTrue(results['img'].sum() > self.results['img'].sum())
  1484. # test empty results
  1485. empty_results = copy.deepcopy(self.results)
  1486. empty_results['gt_bboxes'] = np.zeros((0, 4), dtype=np.float32)
  1487. empty_results['gt_bboxes_labels'] = np.zeros((0, ), dtype=np.int64)
  1488. empty_results['gt_masks'] = empty_results['gt_masks'][False]
  1489. empty_results['gt_ignore_flags'] = np.zeros((0, ), dtype=bool)
  1490. empty_results['gt_seg_map'] = np.ones_like(
  1491. empty_results['gt_seg_map']) * 255
  1492. results = transform(copy.deepcopy(empty_results))
  1493. self.assertTrue(results['img'].sum() > self.results['img'].sum())
  1494. def test_transform_use_box_type(self):
  1495. src_results = copy.deepcopy(self.results)
  1496. src_results['gt_bboxes'] = HorizontalBoxes(src_results['gt_bboxes'])
  1497. transform = RandomErasing(
  1498. n_patches=(1, 5), ratio=(0.4, 0.8), img_border_value=0)
  1499. results = transform(copy.deepcopy(src_results))
  1500. self.assertTrue(results['img'].sum() < src_results['img'].sum())
  1501. transform = RandomErasing(
  1502. n_patches=1, ratio=0.999, img_border_value=255)
  1503. results = transform(copy.deepcopy(src_results))
  1504. self.assertTrue(results['img'].sum() > src_results['img'].sum())
  1505. # test empty results
  1506. empty_results = copy.deepcopy(src_results)
  1507. empty_results['gt_bboxes'] = HorizontalBoxes([], dtype=torch.float32)
  1508. empty_results['gt_bboxes_labels'] = np.zeros((0, ), dtype=np.int64)
  1509. empty_results['gt_masks'] = empty_results['gt_masks'][False]
  1510. empty_results['gt_ignore_flags'] = np.zeros((0, ), dtype=bool)
  1511. empty_results['gt_seg_map'] = np.ones_like(
  1512. empty_results['gt_seg_map']) * 255
  1513. results = transform(copy.deepcopy(empty_results))
  1514. self.assertTrue(results['img'].sum() > src_results['img'].sum())
  1515. def test_repr(self):
  1516. transform = RandomErasing(n_patches=(1, 5), ratio=(0, 0.2))
  1517. self.assertEqual(
  1518. repr(transform), ('RandomErasing(n_patches=(1, 5), '
  1519. 'ratio=(0, 0.2), '
  1520. 'squared=True, '
  1521. 'bbox_erased_thr=0.9, '
  1522. 'img_border_value=128, '
  1523. 'mask_border_value=0, '
  1524. 'seg_ignore_label=255)'))
  1525. class TestResizeShortestEdge(unittest.TestCase):
  1526. def setUp(self):
  1527. """Setup the model and optimizer which are used in every test method.
  1528. TestCase calls functions in this order: setUp() -> testMethod()
  1529. -> tearDown() -> cleanUp()
  1530. """
  1531. rng = np.random.RandomState(0)
  1532. self.data_info = dict(
  1533. img=np.random.random((220, 100, 3)),
  1534. gt_seg_map=np.random.random((220, 100, 3)),
  1535. gt_bboxes=np.array([[0, 0, 112, 12]], dtype=np.float32),
  1536. gt_masks=BitmapMasks(rng.rand(1, 220, 100), height=220, width=100))
  1537. def test_resize(self):
  1538. transform = ResizeShortestEdge(scale=200)
  1539. results = transform(copy.deepcopy(self.data_info))
  1540. self.assertEqual(results['img_shape'], (440, 200))
  1541. self.assertEqual(results['scale_factor'], (200 / 100, 440 / 220))
  1542. transform = ResizeShortestEdge(scale=200, max_size=301)
  1543. results = transform(copy.deepcopy(self.data_info))
  1544. self.assertEqual(results['img_shape'], (301, 137))
  1545. self.assertEqual(results['scale_factor'], (137 / 100, 301 / 220))
  1546. transform = ResizeShortestEdge(scale=201, keep_ratio=True)
  1547. results = transform(copy.deepcopy(self.data_info))
  1548. self.assertEqual(results['img_shape'], (442, 201))
  1549. self.assertEqual(results['scale_factor'], (201 / 100, 442 / 220))