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_mixins.py 14 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. # Copyright (c) OpenMMLab. All rights reserved.
  2. import sys
  3. import warnings
  4. import numpy as np
  5. import torch
  6. from mmdet.core import (bbox2roi, bbox_mapping, merge_aug_bboxes,
  7. merge_aug_masks, multiclass_nms)
  8. if sys.version_info >= (3, 7):
  9. from mmdet.utils.contextmanagers import completed
  10. class BBoxTestMixin:
  11. if sys.version_info >= (3, 7):
  12. async def async_test_bboxes(self,
  13. x,
  14. img_metas,
  15. proposals,
  16. rcnn_test_cfg,
  17. rescale=False,
  18. **kwargs):
  19. """Asynchronized test for box head without augmentation."""
  20. rois = bbox2roi(proposals)
  21. roi_feats = self.bbox_roi_extractor(
  22. x[:len(self.bbox_roi_extractor.featmap_strides)], rois)
  23. if self.with_shared_head:
  24. roi_feats = self.shared_head(roi_feats)
  25. sleep_interval = rcnn_test_cfg.get('async_sleep_interval', 0.017)
  26. async with completed(
  27. __name__, 'bbox_head_forward',
  28. sleep_interval=sleep_interval):
  29. cls_score, bbox_pred = self.bbox_head(roi_feats)
  30. img_shape = img_metas[0]['img_shape']
  31. scale_factor = img_metas[0]['scale_factor']
  32. det_bboxes, det_labels = self.bbox_head.get_bboxes(
  33. rois,
  34. cls_score,
  35. bbox_pred,
  36. img_shape,
  37. scale_factor,
  38. rescale=rescale,
  39. cfg=rcnn_test_cfg)
  40. return det_bboxes, det_labels
  41. def simple_test_bboxes(self,
  42. x,
  43. img_metas,
  44. proposals,
  45. rcnn_test_cfg,
  46. rescale=False):
  47. """Test only det bboxes without augmentation.
  48. Args:
  49. x (tuple[Tensor]): Feature maps of all scale level.
  50. img_metas (list[dict]): Image meta info.
  51. proposals (List[Tensor]): Region proposals.
  52. rcnn_test_cfg (obj:`ConfigDict`): `test_cfg` of R-CNN.
  53. rescale (bool): If True, return boxes in original image space.
  54. Default: False.
  55. Returns:
  56. tuple[list[Tensor], list[Tensor]]: The first list contains
  57. the boxes of the corresponding image in a batch, each
  58. tensor has the shape (num_boxes, 5) and last dimension
  59. 5 represent (tl_x, tl_y, br_x, br_y, score). Each Tensor
  60. in the second list is the labels with shape (num_boxes, ).
  61. The length of both lists should be equal to batch_size.
  62. """
  63. rois = bbox2roi(proposals)
  64. if rois.shape[0] == 0:
  65. batch_size = len(proposals)
  66. det_bbox = rois.new_zeros(0, 5)
  67. det_label = rois.new_zeros((0, ), dtype=torch.long)
  68. if rcnn_test_cfg is None:
  69. det_bbox = det_bbox[:, :4]
  70. det_label = rois.new_zeros(
  71. (0, self.bbox_head.fc_cls.out_features))
  72. # There is no proposal in the whole batch
  73. return [det_bbox] * batch_size, [det_label] * batch_size
  74. bbox_results = self._bbox_forward(x, rois)
  75. img_shapes = tuple(meta['img_shape'] for meta in img_metas)
  76. scale_factors = tuple(meta['scale_factor'] for meta in img_metas)
  77. # split batch bbox prediction back to each image
  78. cls_score = bbox_results['cls_score']
  79. bbox_pred = bbox_results['bbox_pred']
  80. num_proposals_per_img = tuple(len(p) for p in proposals)
  81. rois = rois.split(num_proposals_per_img, 0)
  82. cls_score = cls_score.split(num_proposals_per_img, 0)
  83. # some detector with_reg is False, bbox_pred will be None
  84. if bbox_pred is not None:
  85. # TODO move this to a sabl_roi_head
  86. # the bbox prediction of some detectors like SABL is not Tensor
  87. if isinstance(bbox_pred, torch.Tensor):
  88. bbox_pred = bbox_pred.split(num_proposals_per_img, 0)
  89. else:
  90. bbox_pred = self.bbox_head.bbox_pred_split(
  91. bbox_pred, num_proposals_per_img)
  92. else:
  93. bbox_pred = (None, ) * len(proposals)
  94. # apply bbox post-processing to each image individually
  95. det_bboxes = []
  96. det_labels = []
  97. for i in range(len(proposals)):
  98. if rois[i].shape[0] == 0:
  99. # There is no proposal in the single image
  100. det_bbox = rois[i].new_zeros(0, 5)
  101. det_label = rois[i].new_zeros((0, ), dtype=torch.long)
  102. if rcnn_test_cfg is None:
  103. det_bbox = det_bbox[:, :4]
  104. det_label = rois[i].new_zeros(
  105. (0, self.bbox_head.fc_cls.out_features))
  106. else:
  107. det_bbox, det_label = self.bbox_head.get_bboxes(
  108. rois[i],
  109. cls_score[i],
  110. bbox_pred[i],
  111. img_shapes[i],
  112. scale_factors[i],
  113. rescale=rescale,
  114. cfg=rcnn_test_cfg)
  115. det_bboxes.append(det_bbox)
  116. det_labels.append(det_label)
  117. return det_bboxes, det_labels
  118. def aug_test_bboxes(self, feats, img_metas, proposal_list, rcnn_test_cfg):
  119. """Test det bboxes with test time augmentation."""
  120. aug_bboxes = []
  121. aug_scores = []
  122. for x, img_meta in zip(feats, img_metas):
  123. # only one image in the batch
  124. img_shape = img_meta[0]['img_shape']
  125. scale_factor = img_meta[0]['scale_factor']
  126. flip = img_meta[0]['flip']
  127. flip_direction = img_meta[0]['flip_direction']
  128. # TODO more flexible
  129. proposals = bbox_mapping(proposal_list[0][:, :4], img_shape,
  130. scale_factor, flip, flip_direction)
  131. rois = bbox2roi([proposals])
  132. bbox_results = self._bbox_forward(x, rois)
  133. bboxes, scores = self.bbox_head.get_bboxes(
  134. rois,
  135. bbox_results['cls_score'],
  136. bbox_results['bbox_pred'],
  137. img_shape,
  138. scale_factor,
  139. rescale=False,
  140. cfg=None)
  141. aug_bboxes.append(bboxes)
  142. aug_scores.append(scores)
  143. # after merging, bboxes will be rescaled to the original image size
  144. merged_bboxes, merged_scores = merge_aug_bboxes(
  145. aug_bboxes, aug_scores, img_metas, rcnn_test_cfg)
  146. if merged_bboxes.shape[0] == 0:
  147. # There is no proposal in the single image
  148. det_bboxes = merged_bboxes.new_zeros(0, 5)
  149. det_labels = merged_bboxes.new_zeros((0, ), dtype=torch.long)
  150. else:
  151. det_bboxes, det_labels = multiclass_nms(merged_bboxes,
  152. merged_scores,
  153. rcnn_test_cfg.score_thr,
  154. rcnn_test_cfg.nms,
  155. rcnn_test_cfg.max_per_img)
  156. return det_bboxes, det_labels
  157. class MaskTestMixin:
  158. if sys.version_info >= (3, 7):
  159. async def async_test_mask(self,
  160. x,
  161. img_metas,
  162. det_bboxes,
  163. det_labels,
  164. rescale=False,
  165. mask_test_cfg=None):
  166. """Asynchronized test for mask head without augmentation."""
  167. # image shape of the first image in the batch (only one)
  168. ori_shape = img_metas[0]['ori_shape']
  169. scale_factor = img_metas[0]['scale_factor']
  170. if det_bboxes.shape[0] == 0:
  171. segm_result = [[] for _ in range(self.mask_head.num_classes)]
  172. else:
  173. if rescale and not isinstance(scale_factor,
  174. (float, torch.Tensor)):
  175. scale_factor = det_bboxes.new_tensor(scale_factor)
  176. _bboxes = (
  177. det_bboxes[:, :4] *
  178. scale_factor if rescale else det_bboxes)
  179. mask_rois = bbox2roi([_bboxes])
  180. mask_feats = self.mask_roi_extractor(
  181. x[:len(self.mask_roi_extractor.featmap_strides)],
  182. mask_rois)
  183. if self.with_shared_head:
  184. mask_feats = self.shared_head(mask_feats)
  185. if mask_test_cfg and mask_test_cfg.get('async_sleep_interval'):
  186. sleep_interval = mask_test_cfg['async_sleep_interval']
  187. else:
  188. sleep_interval = 0.035
  189. async with completed(
  190. __name__,
  191. 'mask_head_forward',
  192. sleep_interval=sleep_interval):
  193. mask_pred = self.mask_head(mask_feats)
  194. segm_result = self.mask_head.get_seg_masks(
  195. mask_pred, _bboxes, det_labels, self.test_cfg, ori_shape,
  196. scale_factor, rescale)
  197. return segm_result
  198. def simple_test_mask(self,
  199. x,
  200. img_metas,
  201. det_bboxes,
  202. det_labels,
  203. rescale=False):
  204. """Simple test for mask head without augmentation."""
  205. # image shapes of images in the batch
  206. ori_shapes = tuple(meta['ori_shape'] for meta in img_metas)
  207. scale_factors = tuple(meta['scale_factor'] for meta in img_metas)
  208. if isinstance(scale_factors[0], float):
  209. warnings.warn(
  210. 'Scale factor in img_metas should be a '
  211. 'ndarray with shape (4,) '
  212. 'arrange as (factor_w, factor_h, factor_w, factor_h), '
  213. 'The scale_factor with float type has been deprecated. ')
  214. scale_factors = np.array([scale_factors] * 4, dtype=np.float32)
  215. num_imgs = len(det_bboxes)
  216. if all(det_bbox.shape[0] == 0 for det_bbox in det_bboxes):
  217. segm_results = [[[] for _ in range(self.mask_head.num_classes)]
  218. for _ in range(num_imgs)]
  219. else:
  220. # if det_bboxes is rescaled to the original image size, we need to
  221. # rescale it back to the testing scale to obtain RoIs.
  222. if rescale:
  223. scale_factors = [
  224. torch.from_numpy(scale_factor).to(det_bboxes[0].device)
  225. for scale_factor in scale_factors
  226. ]
  227. _bboxes = [
  228. det_bboxes[i][:, :4] *
  229. scale_factors[i] if rescale else det_bboxes[i][:, :4]
  230. for i in range(len(det_bboxes))
  231. ]
  232. mask_rois = bbox2roi(_bboxes)
  233. mask_results = self._mask_forward(x, mask_rois)
  234. mask_pred = mask_results['mask_pred']
  235. # split batch mask prediction back to each image
  236. num_mask_roi_per_img = [len(det_bbox) for det_bbox in det_bboxes]
  237. mask_preds = mask_pred.split(num_mask_roi_per_img, 0)
  238. # apply mask post-processing to each image individually
  239. segm_results = []
  240. for i in range(num_imgs):
  241. if det_bboxes[i].shape[0] == 0:
  242. segm_results.append(
  243. [[] for _ in range(self.mask_head.num_classes)])
  244. else:
  245. segm_result = self.mask_head.get_seg_masks(
  246. mask_preds[i], _bboxes[i], det_labels[i],
  247. self.test_cfg, ori_shapes[i], scale_factors[i],
  248. rescale)
  249. segm_results.append(segm_result)
  250. return segm_results
  251. def aug_test_mask(self, feats, img_metas, det_bboxes, det_labels):
  252. """Test for mask head with test time augmentation."""
  253. if det_bboxes.shape[0] == 0:
  254. segm_result = [[] for _ in range(self.mask_head.num_classes)]
  255. else:
  256. aug_masks = []
  257. for x, img_meta in zip(feats, img_metas):
  258. img_shape = img_meta[0]['img_shape']
  259. scale_factor = img_meta[0]['scale_factor']
  260. flip = img_meta[0]['flip']
  261. flip_direction = img_meta[0]['flip_direction']
  262. _bboxes = bbox_mapping(det_bboxes[:, :4], img_shape,
  263. scale_factor, flip, flip_direction)
  264. mask_rois = bbox2roi([_bboxes])
  265. mask_results = self._mask_forward(x, mask_rois)
  266. # convert to numpy array to save memory
  267. aug_masks.append(
  268. mask_results['mask_pred'].sigmoid().cpu().numpy())
  269. merged_masks = merge_aug_masks(aug_masks, img_metas, self.test_cfg)
  270. ori_shape = img_metas[0][0]['ori_shape']
  271. scale_factor = det_bboxes.new_ones(4)
  272. segm_result = self.mask_head.get_seg_masks(
  273. merged_masks,
  274. det_bboxes,
  275. det_labels,
  276. self.test_cfg,
  277. ori_shape,
  278. scale_factor=scale_factor,
  279. rescale=False)
  280. return segm_result

No Description

Contributors (3)