You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_anchor.py 33 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. # Copyright (c) OpenMMLab. All rights reserved.
  2. """
  3. CommandLine:
  4. pytest tests/test_utils/test_anchor.py
  5. xdoctest tests/test_utils/test_anchor.py zero
  6. """
  7. import pytest
  8. import torch
  9. def test_standard_points_generator():
  10. from mmdet.core.anchor import build_prior_generator
  11. # teat init
  12. anchor_generator_cfg = dict(
  13. type='MlvlPointGenerator', strides=[4, 8], offset=0)
  14. anchor_generator = build_prior_generator(anchor_generator_cfg)
  15. assert anchor_generator is not None
  16. assert anchor_generator.num_base_priors == [1, 1]
  17. # test_stride
  18. from mmdet.core.anchor import MlvlPointGenerator
  19. # Square strides
  20. mlvl_points = MlvlPointGenerator(strides=[4, 10], offset=0)
  21. mlvl_points_half_stride_generator = MlvlPointGenerator(
  22. strides=[4, 10], offset=0.5)
  23. assert mlvl_points.num_levels == 2
  24. # assert self.num_levels == len(featmap_sizes)
  25. with pytest.raises(AssertionError):
  26. mlvl_points.grid_priors(featmap_sizes=[(2, 2)], device='cpu')
  27. priors = mlvl_points.grid_priors(
  28. featmap_sizes=[(2, 2), (4, 8)], device='cpu')
  29. priors_with_stride = mlvl_points.grid_priors(
  30. featmap_sizes=[(2, 2), (4, 8)], with_stride=True, device='cpu')
  31. assert len(priors) == 2
  32. # assert last dimension is (coord_x, coord_y, stride_w, stride_h).
  33. assert priors_with_stride[0].size(1) == 4
  34. assert priors_with_stride[0][0][2] == 4
  35. assert priors_with_stride[0][0][3] == 4
  36. assert priors_with_stride[1][0][2] == 10
  37. assert priors_with_stride[1][0][3] == 10
  38. stride_4_feat_2_2 = priors[0]
  39. assert (stride_4_feat_2_2[1] - stride_4_feat_2_2[0]).sum() == 4
  40. assert stride_4_feat_2_2.size(0) == 4
  41. assert stride_4_feat_2_2.size(1) == 2
  42. stride_10_feat_4_8 = priors[1]
  43. assert (stride_10_feat_4_8[1] - stride_10_feat_4_8[0]).sum() == 10
  44. assert stride_10_feat_4_8.size(0) == 4 * 8
  45. assert stride_10_feat_4_8.size(1) == 2
  46. # assert the offset of 0.5 * stride
  47. priors_half_offset = mlvl_points_half_stride_generator.grid_priors(
  48. featmap_sizes=[(2, 2), (4, 8)], device='cpu')
  49. assert (priors_half_offset[0][0] - priors[0][0]).sum() == 4 * 0.5 * 2
  50. assert (priors_half_offset[1][0] - priors[1][0]).sum() == 10 * 0.5 * 2
  51. if torch.cuda.is_available():
  52. anchor_generator_cfg = dict(
  53. type='MlvlPointGenerator', strides=[4, 8], offset=0)
  54. anchor_generator = build_prior_generator(anchor_generator_cfg)
  55. assert anchor_generator is not None
  56. # Square strides
  57. mlvl_points = MlvlPointGenerator(strides=[4, 10], offset=0)
  58. mlvl_points_half_stride_generator = MlvlPointGenerator(
  59. strides=[4, 10], offset=0.5)
  60. assert mlvl_points.num_levels == 2
  61. # assert self.num_levels == len(featmap_sizes)
  62. with pytest.raises(AssertionError):
  63. mlvl_points.grid_priors(featmap_sizes=[(2, 2)], device='cuda')
  64. priors = mlvl_points.grid_priors(
  65. featmap_sizes=[(2, 2), (4, 8)], device='cuda')
  66. priors_with_stride = mlvl_points.grid_priors(
  67. featmap_sizes=[(2, 2), (4, 8)], with_stride=True, device='cuda')
  68. assert len(priors) == 2
  69. # assert last dimension is (coord_x, coord_y, stride_w, stride_h).
  70. assert priors_with_stride[0].size(1) == 4
  71. assert priors_with_stride[0][0][2] == 4
  72. assert priors_with_stride[0][0][3] == 4
  73. assert priors_with_stride[1][0][2] == 10
  74. assert priors_with_stride[1][0][3] == 10
  75. stride_4_feat_2_2 = priors[0]
  76. assert (stride_4_feat_2_2[1] - stride_4_feat_2_2[0]).sum() == 4
  77. assert stride_4_feat_2_2.size(0) == 4
  78. assert stride_4_feat_2_2.size(1) == 2
  79. stride_10_feat_4_8 = priors[1]
  80. assert (stride_10_feat_4_8[1] - stride_10_feat_4_8[0]).sum() == 10
  81. assert stride_10_feat_4_8.size(0) == 4 * 8
  82. assert stride_10_feat_4_8.size(1) == 2
  83. # assert the offset of 0.5 * stride
  84. priors_half_offset = mlvl_points_half_stride_generator.grid_priors(
  85. featmap_sizes=[(2, 2), (4, 8)], device='cuda')
  86. assert (priors_half_offset[0][0] - priors[0][0]).sum() == 4 * 0.5 * 2
  87. assert (priors_half_offset[1][0] - priors[1][0]).sum() == 10 * 0.5 * 2
  88. def test_sparse_prior():
  89. from mmdet.core.anchor import MlvlPointGenerator
  90. mlvl_points = MlvlPointGenerator(strides=[4, 10], offset=0)
  91. prior_indexs = torch.Tensor([0, 2, 4, 5, 6, 9]).long()
  92. featmap_sizes = [(3, 5), (6, 4)]
  93. grid_anchors = mlvl_points.grid_priors(
  94. featmap_sizes=featmap_sizes, with_stride=False, device='cpu')
  95. sparse_prior = mlvl_points.sparse_priors(
  96. prior_idxs=prior_indexs,
  97. featmap_size=featmap_sizes[0],
  98. level_idx=0,
  99. device='cpu')
  100. assert not sparse_prior.is_cuda
  101. assert (sparse_prior == grid_anchors[0][prior_indexs]).all()
  102. sparse_prior = mlvl_points.sparse_priors(
  103. prior_idxs=prior_indexs,
  104. featmap_size=featmap_sizes[1],
  105. level_idx=1,
  106. device='cpu')
  107. assert (sparse_prior == grid_anchors[1][prior_indexs]).all()
  108. from mmdet.core.anchor import AnchorGenerator
  109. mlvl_anchors = AnchorGenerator(
  110. strides=[16, 32], ratios=[1.], scales=[1.], base_sizes=[4, 8])
  111. prior_indexs = torch.Tensor([0, 2, 4, 5, 6, 9]).long()
  112. featmap_sizes = [(3, 5), (6, 4)]
  113. grid_anchors = mlvl_anchors.grid_priors(
  114. featmap_sizes=featmap_sizes, device='cpu')
  115. sparse_prior = mlvl_anchors.sparse_priors(
  116. prior_idxs=prior_indexs,
  117. featmap_size=featmap_sizes[0],
  118. level_idx=0,
  119. device='cpu')
  120. assert (sparse_prior == grid_anchors[0][prior_indexs]).all()
  121. sparse_prior = mlvl_anchors.sparse_priors(
  122. prior_idxs=prior_indexs,
  123. featmap_size=featmap_sizes[1],
  124. level_idx=1,
  125. device='cpu')
  126. assert (sparse_prior == grid_anchors[1][prior_indexs]).all()
  127. # for ssd
  128. from mmdet.core.anchor.anchor_generator import SSDAnchorGenerator
  129. featmap_sizes = [(38, 38), (19, 19), (10, 10)]
  130. anchor_generator = SSDAnchorGenerator(
  131. scale_major=False,
  132. input_size=300,
  133. basesize_ratio_range=(0.15, 0.9),
  134. strides=[8, 16, 32],
  135. ratios=[[2], [2, 3], [2, 3]])
  136. ssd_anchors = anchor_generator.grid_anchors(featmap_sizes, device='cpu')
  137. for i in range(len(featmap_sizes)):
  138. sparse_ssd_anchors = anchor_generator.sparse_priors(
  139. prior_idxs=prior_indexs,
  140. level_idx=i,
  141. featmap_size=featmap_sizes[i],
  142. device='cpu')
  143. assert (sparse_ssd_anchors == ssd_anchors[i][prior_indexs]).all()
  144. # for yolo
  145. from mmdet.core.anchor.anchor_generator import YOLOAnchorGenerator
  146. featmap_sizes = [(38, 38), (19, 19), (10, 10)]
  147. anchor_generator = YOLOAnchorGenerator(
  148. strides=[32, 16, 8],
  149. base_sizes=[
  150. [(116, 90), (156, 198), (373, 326)],
  151. [(30, 61), (62, 45), (59, 119)],
  152. [(10, 13), (16, 30), (33, 23)],
  153. ])
  154. yolo_anchors = anchor_generator.grid_anchors(featmap_sizes, device='cpu')
  155. for i in range(len(featmap_sizes)):
  156. sparse_yolo_anchors = anchor_generator.sparse_priors(
  157. prior_idxs=prior_indexs,
  158. level_idx=i,
  159. featmap_size=featmap_sizes[i],
  160. device='cpu')
  161. assert (sparse_yolo_anchors == yolo_anchors[i][prior_indexs]).all()
  162. if torch.cuda.is_available():
  163. mlvl_points = MlvlPointGenerator(strides=[4, 10], offset=0)
  164. prior_indexs = torch.Tensor([0, 3, 4, 5, 6, 7, 1, 2, 4, 5, 6,
  165. 9]).long().cuda()
  166. featmap_sizes = [(6, 8), (6, 4)]
  167. grid_anchors = mlvl_points.grid_priors(
  168. featmap_sizes=featmap_sizes, with_stride=False, device='cuda')
  169. sparse_prior = mlvl_points.sparse_priors(
  170. prior_idxs=prior_indexs,
  171. featmap_size=featmap_sizes[0],
  172. level_idx=0,
  173. device='cuda')
  174. assert (sparse_prior == grid_anchors[0][prior_indexs]).all()
  175. sparse_prior = mlvl_points.sparse_priors(
  176. prior_idxs=prior_indexs,
  177. featmap_size=featmap_sizes[1],
  178. level_idx=1,
  179. device='cuda')
  180. assert (sparse_prior == grid_anchors[1][prior_indexs]).all()
  181. assert sparse_prior.is_cuda
  182. mlvl_anchors = AnchorGenerator(
  183. strides=[16, 32],
  184. ratios=[1., 2.5],
  185. scales=[1., 5.],
  186. base_sizes=[4, 8])
  187. prior_indexs = torch.Tensor([4, 5, 6, 7, 0, 2, 50, 4, 5, 6,
  188. 9]).long().cuda()
  189. featmap_sizes = [(13, 5), (16, 4)]
  190. grid_anchors = mlvl_anchors.grid_priors(
  191. featmap_sizes=featmap_sizes, device='cuda')
  192. sparse_prior = mlvl_anchors.sparse_priors(
  193. prior_idxs=prior_indexs,
  194. featmap_size=featmap_sizes[0],
  195. level_idx=0,
  196. device='cuda')
  197. assert (sparse_prior == grid_anchors[0][prior_indexs]).all()
  198. sparse_prior = mlvl_anchors.sparse_priors(
  199. prior_idxs=prior_indexs,
  200. featmap_size=featmap_sizes[1],
  201. level_idx=1,
  202. device='cuda')
  203. assert (sparse_prior == grid_anchors[1][prior_indexs]).all()
  204. # for ssd
  205. from mmdet.core.anchor.anchor_generator import SSDAnchorGenerator
  206. featmap_sizes = [(38, 38), (19, 19), (10, 10)]
  207. anchor_generator = SSDAnchorGenerator(
  208. scale_major=False,
  209. input_size=300,
  210. basesize_ratio_range=(0.15, 0.9),
  211. strides=[8, 16, 32],
  212. ratios=[[2], [2, 3], [2, 3]])
  213. ssd_anchors = anchor_generator.grid_anchors(
  214. featmap_sizes, device='cuda')
  215. for i in range(len(featmap_sizes)):
  216. sparse_ssd_anchors = anchor_generator.sparse_priors(
  217. prior_idxs=prior_indexs,
  218. level_idx=i,
  219. featmap_size=featmap_sizes[i],
  220. device='cuda')
  221. assert (sparse_ssd_anchors == ssd_anchors[i][prior_indexs]).all()
  222. # for yolo
  223. from mmdet.core.anchor.anchor_generator import YOLOAnchorGenerator
  224. featmap_sizes = [(38, 38), (19, 19), (10, 10)]
  225. anchor_generator = YOLOAnchorGenerator(
  226. strides=[32, 16, 8],
  227. base_sizes=[
  228. [(116, 90), (156, 198), (373, 326)],
  229. [(30, 61), (62, 45), (59, 119)],
  230. [(10, 13), (16, 30), (33, 23)],
  231. ])
  232. yolo_anchors = anchor_generator.grid_anchors(
  233. featmap_sizes, device='cuda')
  234. for i in range(len(featmap_sizes)):
  235. sparse_yolo_anchors = anchor_generator.sparse_priors(
  236. prior_idxs=prior_indexs,
  237. level_idx=i,
  238. featmap_size=featmap_sizes[i],
  239. device='cuda')
  240. assert (sparse_yolo_anchors == yolo_anchors[i][prior_indexs]).all()
  241. def test_standard_anchor_generator():
  242. from mmdet.core.anchor import build_anchor_generator
  243. anchor_generator_cfg = dict(
  244. type='AnchorGenerator',
  245. scales=[8],
  246. ratios=[0.5, 1.0, 2.0],
  247. strides=[4, 8])
  248. anchor_generator = build_anchor_generator(anchor_generator_cfg)
  249. assert anchor_generator.num_base_priors == \
  250. anchor_generator.num_base_anchors
  251. assert anchor_generator.num_base_priors == [3, 3]
  252. assert anchor_generator is not None
  253. def test_strides():
  254. from mmdet.core import AnchorGenerator
  255. # Square strides
  256. self = AnchorGenerator([10], [1.], [1.], [10])
  257. anchors = self.grid_anchors([(2, 2)], device='cpu')
  258. expected_anchors = torch.tensor([[-5., -5., 5., 5.], [5., -5., 15., 5.],
  259. [-5., 5., 5., 15.], [5., 5., 15., 15.]])
  260. assert torch.equal(anchors[0], expected_anchors)
  261. # Different strides in x and y direction
  262. self = AnchorGenerator([(10, 20)], [1.], [1.], [10])
  263. anchors = self.grid_anchors([(2, 2)], device='cpu')
  264. expected_anchors = torch.tensor([[-5., -5., 5., 5.], [5., -5., 15., 5.],
  265. [-5., 15., 5., 25.], [5., 15., 15., 25.]])
  266. assert torch.equal(anchors[0], expected_anchors)
  267. def test_ssd_anchor_generator():
  268. from mmdet.core.anchor import build_anchor_generator
  269. if torch.cuda.is_available():
  270. device = 'cuda'
  271. else:
  272. device = 'cpu'
  273. # min_sizes max_sizes must set at the same time
  274. with pytest.raises(AssertionError):
  275. anchor_generator_cfg = dict(
  276. type='SSDAnchorGenerator',
  277. scale_major=False,
  278. min_sizes=[48, 100, 150, 202, 253, 300],
  279. max_sizes=None,
  280. strides=[8, 16, 32, 64, 100, 300],
  281. ratios=[[2], [2, 3], [2, 3], [2, 3], [2], [2]])
  282. build_anchor_generator(anchor_generator_cfg)
  283. # length of min_sizes max_sizes must be the same
  284. with pytest.raises(AssertionError):
  285. anchor_generator_cfg = dict(
  286. type='SSDAnchorGenerator',
  287. scale_major=False,
  288. min_sizes=[48, 100, 150, 202, 253, 300],
  289. max_sizes=[100, 150, 202, 253],
  290. strides=[8, 16, 32, 64, 100, 300],
  291. ratios=[[2], [2, 3], [2, 3], [2, 3], [2], [2]])
  292. build_anchor_generator(anchor_generator_cfg)
  293. # test setting anchor size manually
  294. anchor_generator_cfg = dict(
  295. type='SSDAnchorGenerator',
  296. scale_major=False,
  297. min_sizes=[48, 100, 150, 202, 253, 304],
  298. max_sizes=[100, 150, 202, 253, 304, 320],
  299. strides=[16, 32, 64, 107, 160, 320],
  300. ratios=[[2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3]])
  301. featmap_sizes = [(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)]
  302. anchor_generator = build_anchor_generator(anchor_generator_cfg)
  303. expected_base_anchors = [
  304. torch.Tensor([[-16.0000, -16.0000, 32.0000, 32.0000],
  305. [-26.6410, -26.6410, 42.6410, 42.6410],
  306. [-25.9411, -8.9706, 41.9411, 24.9706],
  307. [-8.9706, -25.9411, 24.9706, 41.9411],
  308. [-33.5692, -5.8564, 49.5692, 21.8564],
  309. [-5.8564, -33.5692, 21.8564, 49.5692]]),
  310. torch.Tensor([[-34.0000, -34.0000, 66.0000, 66.0000],
  311. [-45.2372, -45.2372, 77.2372, 77.2372],
  312. [-54.7107, -19.3553, 86.7107, 51.3553],
  313. [-19.3553, -54.7107, 51.3553, 86.7107],
  314. [-70.6025, -12.8675, 102.6025, 44.8675],
  315. [-12.8675, -70.6025, 44.8675, 102.6025]]),
  316. torch.Tensor([[-43.0000, -43.0000, 107.0000, 107.0000],
  317. [-55.0345, -55.0345, 119.0345, 119.0345],
  318. [-74.0660, -21.0330, 138.0660, 85.0330],
  319. [-21.0330, -74.0660, 85.0330, 138.0660],
  320. [-97.9038, -11.3013, 161.9038, 75.3013],
  321. [-11.3013, -97.9038, 75.3013, 161.9038]]),
  322. torch.Tensor([[-47.5000, -47.5000, 154.5000, 154.5000],
  323. [-59.5332, -59.5332, 166.5332, 166.5332],
  324. [-89.3356, -17.9178, 196.3356, 124.9178],
  325. [-17.9178, -89.3356, 124.9178, 196.3356],
  326. [-121.4371, -4.8124, 228.4371, 111.8124],
  327. [-4.8124, -121.4371, 111.8124, 228.4371]]),
  328. torch.Tensor([[-46.5000, -46.5000, 206.5000, 206.5000],
  329. [-58.6651, -58.6651, 218.6651, 218.6651],
  330. [-98.8980, -9.4490, 258.8980, 169.4490],
  331. [-9.4490, -98.8980, 169.4490, 258.8980],
  332. [-139.1044, 6.9652, 299.1044, 153.0348],
  333. [6.9652, -139.1044, 153.0348, 299.1044]]),
  334. torch.Tensor([[8.0000, 8.0000, 312.0000, 312.0000],
  335. [4.0513, 4.0513, 315.9487, 315.9487],
  336. [-54.9605, 52.5198, 374.9604, 267.4802],
  337. [52.5198, -54.9605, 267.4802, 374.9604],
  338. [-103.2717, 72.2428, 423.2717, 247.7572],
  339. [72.2428, -103.2717, 247.7572, 423.2717]])
  340. ]
  341. base_anchors = anchor_generator.base_anchors
  342. for i, base_anchor in enumerate(base_anchors):
  343. assert base_anchor.allclose(expected_base_anchors[i])
  344. # check valid flags
  345. expected_valid_pixels = [2400, 600, 150, 54, 24, 6]
  346. multi_level_valid_flags = anchor_generator.valid_flags(
  347. featmap_sizes, (320, 320), device)
  348. for i, single_level_valid_flag in enumerate(multi_level_valid_flags):
  349. assert single_level_valid_flag.sum() == expected_valid_pixels[i]
  350. # check number of base anchors for each level
  351. assert anchor_generator.num_base_anchors == [6, 6, 6, 6, 6, 6]
  352. # check anchor generation
  353. anchors = anchor_generator.grid_anchors(featmap_sizes, device)
  354. assert len(anchors) == 6
  355. # test vgg ssd anchor setting
  356. anchor_generator_cfg = dict(
  357. type='SSDAnchorGenerator',
  358. scale_major=False,
  359. input_size=300,
  360. basesize_ratio_range=(0.15, 0.9),
  361. strides=[8, 16, 32, 64, 100, 300],
  362. ratios=[[2], [2, 3], [2, 3], [2, 3], [2], [2]])
  363. featmap_sizes = [(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)]
  364. anchor_generator = build_anchor_generator(anchor_generator_cfg)
  365. # check base anchors
  366. expected_base_anchors = [
  367. torch.Tensor([[-6.5000, -6.5000, 14.5000, 14.5000],
  368. [-11.3704, -11.3704, 19.3704, 19.3704],
  369. [-10.8492, -3.4246, 18.8492, 11.4246],
  370. [-3.4246, -10.8492, 11.4246, 18.8492]]),
  371. torch.Tensor([[-14.5000, -14.5000, 30.5000, 30.5000],
  372. [-25.3729, -25.3729, 41.3729, 41.3729],
  373. [-23.8198, -7.9099, 39.8198, 23.9099],
  374. [-7.9099, -23.8198, 23.9099, 39.8198],
  375. [-30.9711, -4.9904, 46.9711, 20.9904],
  376. [-4.9904, -30.9711, 20.9904, 46.9711]]),
  377. torch.Tensor([[-33.5000, -33.5000, 65.5000, 65.5000],
  378. [-45.5366, -45.5366, 77.5366, 77.5366],
  379. [-54.0036, -19.0018, 86.0036, 51.0018],
  380. [-19.0018, -54.0036, 51.0018, 86.0036],
  381. [-69.7365, -12.5788, 101.7365, 44.5788],
  382. [-12.5788, -69.7365, 44.5788, 101.7365]]),
  383. torch.Tensor([[-44.5000, -44.5000, 108.5000, 108.5000],
  384. [-56.9817, -56.9817, 120.9817, 120.9817],
  385. [-76.1873, -22.0937, 140.1873, 86.0937],
  386. [-22.0937, -76.1873, 86.0937, 140.1873],
  387. [-100.5019, -12.1673, 164.5019, 76.1673],
  388. [-12.1673, -100.5019, 76.1673, 164.5019]]),
  389. torch.Tensor([[-53.5000, -53.5000, 153.5000, 153.5000],
  390. [-66.2185, -66.2185, 166.2185, 166.2185],
  391. [-96.3711, -23.1855, 196.3711, 123.1855],
  392. [-23.1855, -96.3711, 123.1855, 196.3711]]),
  393. torch.Tensor([[19.5000, 19.5000, 280.5000, 280.5000],
  394. [6.6342, 6.6342, 293.3658, 293.3658],
  395. [-34.5549, 57.7226, 334.5549, 242.2774],
  396. [57.7226, -34.5549, 242.2774, 334.5549]]),
  397. ]
  398. base_anchors = anchor_generator.base_anchors
  399. for i, base_anchor in enumerate(base_anchors):
  400. assert base_anchor.allclose(expected_base_anchors[i])
  401. # check valid flags
  402. expected_valid_pixels = [5776, 2166, 600, 150, 36, 4]
  403. multi_level_valid_flags = anchor_generator.valid_flags(
  404. featmap_sizes, (300, 300), device)
  405. for i, single_level_valid_flag in enumerate(multi_level_valid_flags):
  406. assert single_level_valid_flag.sum() == expected_valid_pixels[i]
  407. # check number of base anchors for each level
  408. assert anchor_generator.num_base_anchors == [4, 6, 6, 6, 4, 4]
  409. # check anchor generation
  410. anchors = anchor_generator.grid_anchors(featmap_sizes, device)
  411. assert len(anchors) == 6
  412. def test_anchor_generator_with_tuples():
  413. from mmdet.core.anchor import build_anchor_generator
  414. if torch.cuda.is_available():
  415. device = 'cuda'
  416. else:
  417. device = 'cpu'
  418. anchor_generator_cfg = dict(
  419. type='SSDAnchorGenerator',
  420. scale_major=False,
  421. input_size=300,
  422. basesize_ratio_range=(0.15, 0.9),
  423. strides=[8, 16, 32, 64, 100, 300],
  424. ratios=[[2], [2, 3], [2, 3], [2, 3], [2], [2]])
  425. featmap_sizes = [(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)]
  426. anchor_generator = build_anchor_generator(anchor_generator_cfg)
  427. anchors = anchor_generator.grid_anchors(featmap_sizes, device)
  428. anchor_generator_cfg_tuples = dict(
  429. type='SSDAnchorGenerator',
  430. scale_major=False,
  431. input_size=300,
  432. basesize_ratio_range=(0.15, 0.9),
  433. strides=[(8, 8), (16, 16), (32, 32), (64, 64), (100, 100), (300, 300)],
  434. ratios=[[2], [2, 3], [2, 3], [2, 3], [2], [2]])
  435. anchor_generator_tuples = build_anchor_generator(
  436. anchor_generator_cfg_tuples)
  437. anchors_tuples = anchor_generator_tuples.grid_anchors(
  438. featmap_sizes, device)
  439. for anchor, anchor_tuples in zip(anchors, anchors_tuples):
  440. assert torch.equal(anchor, anchor_tuples)
  441. def test_yolo_anchor_generator():
  442. from mmdet.core.anchor import build_anchor_generator
  443. if torch.cuda.is_available():
  444. device = 'cuda'
  445. else:
  446. device = 'cpu'
  447. anchor_generator_cfg = dict(
  448. type='YOLOAnchorGenerator',
  449. strides=[32, 16, 8],
  450. base_sizes=[
  451. [(116, 90), (156, 198), (373, 326)],
  452. [(30, 61), (62, 45), (59, 119)],
  453. [(10, 13), (16, 30), (33, 23)],
  454. ])
  455. featmap_sizes = [(14, 18), (28, 36), (56, 72)]
  456. anchor_generator = build_anchor_generator(anchor_generator_cfg)
  457. # check base anchors
  458. expected_base_anchors = [
  459. torch.Tensor([[-42.0000, -29.0000, 74.0000, 61.0000],
  460. [-62.0000, -83.0000, 94.0000, 115.0000],
  461. [-170.5000, -147.0000, 202.5000, 179.0000]]),
  462. torch.Tensor([[-7.0000, -22.5000, 23.0000, 38.5000],
  463. [-23.0000, -14.5000, 39.0000, 30.5000],
  464. [-21.5000, -51.5000, 37.5000, 67.5000]]),
  465. torch.Tensor([[-1.0000, -2.5000, 9.0000, 10.5000],
  466. [-4.0000, -11.0000, 12.0000, 19.0000],
  467. [-12.5000, -7.5000, 20.5000, 15.5000]])
  468. ]
  469. base_anchors = anchor_generator.base_anchors
  470. for i, base_anchor in enumerate(base_anchors):
  471. assert base_anchor.allclose(expected_base_anchors[i])
  472. # check number of base anchors for each level
  473. assert anchor_generator.num_base_anchors == [3, 3, 3]
  474. # check anchor generation
  475. anchors = anchor_generator.grid_anchors(featmap_sizes, device)
  476. assert len(anchors) == 3
  477. def test_retina_anchor():
  478. from mmdet.models import build_head
  479. if torch.cuda.is_available():
  480. device = 'cuda'
  481. else:
  482. device = 'cpu'
  483. # head configs modified from
  484. # configs/nas_fpn/retinanet_r50_fpn_crop640_50e.py
  485. bbox_head = dict(
  486. type='RetinaSepBNHead',
  487. num_classes=4,
  488. num_ins=5,
  489. in_channels=4,
  490. stacked_convs=1,
  491. feat_channels=4,
  492. anchor_generator=dict(
  493. type='AnchorGenerator',
  494. octave_base_scale=4,
  495. scales_per_octave=3,
  496. ratios=[0.5, 1.0, 2.0],
  497. strides=[8, 16, 32, 64, 128]),
  498. bbox_coder=dict(
  499. type='DeltaXYWHBBoxCoder',
  500. target_means=[.0, .0, .0, .0],
  501. target_stds=[1.0, 1.0, 1.0, 1.0]))
  502. retina_head = build_head(bbox_head)
  503. assert retina_head.anchor_generator is not None
  504. # use the featmap sizes in NASFPN setting to test retina head
  505. featmap_sizes = [(80, 80), (40, 40), (20, 20), (10, 10), (5, 5)]
  506. # check base anchors
  507. expected_base_anchors = [
  508. torch.Tensor([[-22.6274, -11.3137, 22.6274, 11.3137],
  509. [-28.5088, -14.2544, 28.5088, 14.2544],
  510. [-35.9188, -17.9594, 35.9188, 17.9594],
  511. [-16.0000, -16.0000, 16.0000, 16.0000],
  512. [-20.1587, -20.1587, 20.1587, 20.1587],
  513. [-25.3984, -25.3984, 25.3984, 25.3984],
  514. [-11.3137, -22.6274, 11.3137, 22.6274],
  515. [-14.2544, -28.5088, 14.2544, 28.5088],
  516. [-17.9594, -35.9188, 17.9594, 35.9188]]),
  517. torch.Tensor([[-45.2548, -22.6274, 45.2548, 22.6274],
  518. [-57.0175, -28.5088, 57.0175, 28.5088],
  519. [-71.8376, -35.9188, 71.8376, 35.9188],
  520. [-32.0000, -32.0000, 32.0000, 32.0000],
  521. [-40.3175, -40.3175, 40.3175, 40.3175],
  522. [-50.7968, -50.7968, 50.7968, 50.7968],
  523. [-22.6274, -45.2548, 22.6274, 45.2548],
  524. [-28.5088, -57.0175, 28.5088, 57.0175],
  525. [-35.9188, -71.8376, 35.9188, 71.8376]]),
  526. torch.Tensor([[-90.5097, -45.2548, 90.5097, 45.2548],
  527. [-114.0350, -57.0175, 114.0350, 57.0175],
  528. [-143.6751, -71.8376, 143.6751, 71.8376],
  529. [-64.0000, -64.0000, 64.0000, 64.0000],
  530. [-80.6349, -80.6349, 80.6349, 80.6349],
  531. [-101.5937, -101.5937, 101.5937, 101.5937],
  532. [-45.2548, -90.5097, 45.2548, 90.5097],
  533. [-57.0175, -114.0350, 57.0175, 114.0350],
  534. [-71.8376, -143.6751, 71.8376, 143.6751]]),
  535. torch.Tensor([[-181.0193, -90.5097, 181.0193, 90.5097],
  536. [-228.0701, -114.0350, 228.0701, 114.0350],
  537. [-287.3503, -143.6751, 287.3503, 143.6751],
  538. [-128.0000, -128.0000, 128.0000, 128.0000],
  539. [-161.2699, -161.2699, 161.2699, 161.2699],
  540. [-203.1873, -203.1873, 203.1873, 203.1873],
  541. [-90.5097, -181.0193, 90.5097, 181.0193],
  542. [-114.0350, -228.0701, 114.0350, 228.0701],
  543. [-143.6751, -287.3503, 143.6751, 287.3503]]),
  544. torch.Tensor([[-362.0387, -181.0193, 362.0387, 181.0193],
  545. [-456.1401, -228.0701, 456.1401, 228.0701],
  546. [-574.7006, -287.3503, 574.7006, 287.3503],
  547. [-256.0000, -256.0000, 256.0000, 256.0000],
  548. [-322.5398, -322.5398, 322.5398, 322.5398],
  549. [-406.3747, -406.3747, 406.3747, 406.3747],
  550. [-181.0193, -362.0387, 181.0193, 362.0387],
  551. [-228.0701, -456.1401, 228.0701, 456.1401],
  552. [-287.3503, -574.7006, 287.3503, 574.7006]])
  553. ]
  554. base_anchors = retina_head.anchor_generator.base_anchors
  555. for i, base_anchor in enumerate(base_anchors):
  556. assert base_anchor.allclose(expected_base_anchors[i])
  557. # check valid flags
  558. expected_valid_pixels = [57600, 14400, 3600, 900, 225]
  559. multi_level_valid_flags = retina_head.anchor_generator.valid_flags(
  560. featmap_sizes, (640, 640), device)
  561. for i, single_level_valid_flag in enumerate(multi_level_valid_flags):
  562. assert single_level_valid_flag.sum() == expected_valid_pixels[i]
  563. # check number of base anchors for each level
  564. assert retina_head.anchor_generator.num_base_anchors == [9, 9, 9, 9, 9]
  565. # check anchor generation
  566. anchors = retina_head.anchor_generator.grid_anchors(featmap_sizes, device)
  567. assert len(anchors) == 5
  568. def test_guided_anchor():
  569. from mmdet.models import build_head
  570. if torch.cuda.is_available():
  571. device = 'cuda'
  572. else:
  573. device = 'cpu'
  574. # head configs modified from
  575. # configs/guided_anchoring/ga_retinanet_r50_fpn_1x_coco.py
  576. bbox_head = dict(
  577. type='GARetinaHead',
  578. num_classes=8,
  579. in_channels=4,
  580. stacked_convs=1,
  581. feat_channels=4,
  582. approx_anchor_generator=dict(
  583. type='AnchorGenerator',
  584. octave_base_scale=4,
  585. scales_per_octave=3,
  586. ratios=[0.5, 1.0, 2.0],
  587. strides=[8, 16, 32, 64, 128]),
  588. square_anchor_generator=dict(
  589. type='AnchorGenerator',
  590. ratios=[1.0],
  591. scales=[4],
  592. strides=[8, 16, 32, 64, 128]))
  593. ga_retina_head = build_head(bbox_head)
  594. assert ga_retina_head.approx_anchor_generator is not None
  595. # use the featmap sizes in NASFPN setting to test ga_retina_head
  596. featmap_sizes = [(100, 152), (50, 76), (25, 38), (13, 19), (7, 10)]
  597. # check base anchors
  598. expected_approxs = [
  599. torch.Tensor([[-22.6274, -11.3137, 22.6274, 11.3137],
  600. [-28.5088, -14.2544, 28.5088, 14.2544],
  601. [-35.9188, -17.9594, 35.9188, 17.9594],
  602. [-16.0000, -16.0000, 16.0000, 16.0000],
  603. [-20.1587, -20.1587, 20.1587, 20.1587],
  604. [-25.3984, -25.3984, 25.3984, 25.3984],
  605. [-11.3137, -22.6274, 11.3137, 22.6274],
  606. [-14.2544, -28.5088, 14.2544, 28.5088],
  607. [-17.9594, -35.9188, 17.9594, 35.9188]]),
  608. torch.Tensor([[-45.2548, -22.6274, 45.2548, 22.6274],
  609. [-57.0175, -28.5088, 57.0175, 28.5088],
  610. [-71.8376, -35.9188, 71.8376, 35.9188],
  611. [-32.0000, -32.0000, 32.0000, 32.0000],
  612. [-40.3175, -40.3175, 40.3175, 40.3175],
  613. [-50.7968, -50.7968, 50.7968, 50.7968],
  614. [-22.6274, -45.2548, 22.6274, 45.2548],
  615. [-28.5088, -57.0175, 28.5088, 57.0175],
  616. [-35.9188, -71.8376, 35.9188, 71.8376]]),
  617. torch.Tensor([[-90.5097, -45.2548, 90.5097, 45.2548],
  618. [-114.0350, -57.0175, 114.0350, 57.0175],
  619. [-143.6751, -71.8376, 143.6751, 71.8376],
  620. [-64.0000, -64.0000, 64.0000, 64.0000],
  621. [-80.6349, -80.6349, 80.6349, 80.6349],
  622. [-101.5937, -101.5937, 101.5937, 101.5937],
  623. [-45.2548, -90.5097, 45.2548, 90.5097],
  624. [-57.0175, -114.0350, 57.0175, 114.0350],
  625. [-71.8376, -143.6751, 71.8376, 143.6751]]),
  626. torch.Tensor([[-181.0193, -90.5097, 181.0193, 90.5097],
  627. [-228.0701, -114.0350, 228.0701, 114.0350],
  628. [-287.3503, -143.6751, 287.3503, 143.6751],
  629. [-128.0000, -128.0000, 128.0000, 128.0000],
  630. [-161.2699, -161.2699, 161.2699, 161.2699],
  631. [-203.1873, -203.1873, 203.1873, 203.1873],
  632. [-90.5097, -181.0193, 90.5097, 181.0193],
  633. [-114.0350, -228.0701, 114.0350, 228.0701],
  634. [-143.6751, -287.3503, 143.6751, 287.3503]]),
  635. torch.Tensor([[-362.0387, -181.0193, 362.0387, 181.0193],
  636. [-456.1401, -228.0701, 456.1401, 228.0701],
  637. [-574.7006, -287.3503, 574.7006, 287.3503],
  638. [-256.0000, -256.0000, 256.0000, 256.0000],
  639. [-322.5398, -322.5398, 322.5398, 322.5398],
  640. [-406.3747, -406.3747, 406.3747, 406.3747],
  641. [-181.0193, -362.0387, 181.0193, 362.0387],
  642. [-228.0701, -456.1401, 228.0701, 456.1401],
  643. [-287.3503, -574.7006, 287.3503, 574.7006]])
  644. ]
  645. approxs = ga_retina_head.approx_anchor_generator.base_anchors
  646. for i, base_anchor in enumerate(approxs):
  647. assert base_anchor.allclose(expected_approxs[i])
  648. # check valid flags
  649. expected_valid_pixels = [136800, 34200, 8550, 2223, 630]
  650. multi_level_valid_flags = ga_retina_head.approx_anchor_generator \
  651. .valid_flags(featmap_sizes, (800, 1216), device)
  652. for i, single_level_valid_flag in enumerate(multi_level_valid_flags):
  653. assert single_level_valid_flag.sum() == expected_valid_pixels[i]
  654. # check number of base anchors for each level
  655. assert ga_retina_head.approx_anchor_generator.num_base_anchors == [
  656. 9, 9, 9, 9, 9
  657. ]
  658. # check approx generation
  659. squares = ga_retina_head.square_anchor_generator.grid_anchors(
  660. featmap_sizes, device)
  661. assert len(squares) == 5
  662. expected_squares = [
  663. torch.Tensor([[-16., -16., 16., 16.]]),
  664. torch.Tensor([[-32., -32., 32., 32]]),
  665. torch.Tensor([[-64., -64., 64., 64.]]),
  666. torch.Tensor([[-128., -128., 128., 128.]]),
  667. torch.Tensor([[-256., -256., 256., 256.]])
  668. ]
  669. squares = ga_retina_head.square_anchor_generator.base_anchors
  670. for i, base_anchor in enumerate(squares):
  671. assert base_anchor.allclose(expected_squares[i])
  672. # square_anchor_generator does not check valid flags
  673. # check number of base anchors for each level
  674. assert (ga_retina_head.square_anchor_generator.num_base_anchors == [
  675. 1, 1, 1, 1, 1
  676. ])
  677. # check square generation
  678. anchors = ga_retina_head.square_anchor_generator.grid_anchors(
  679. featmap_sizes, device)
  680. assert len(anchors) == 5

No Description

Contributors (3)