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

boxes.py 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. # Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  4. import numpy as np
  5. import torch
  6. import torchvision
  7. import torch.nn.functional as F
  8. __all__ = [
  9. "filter_box",
  10. "postprocess",
  11. "bboxes_iou",
  12. "matrix_iou",
  13. "adjust_box_anns",
  14. "xyxy2xywh",
  15. "xyxy2cxcywh",
  16. ]
  17. def filter_box(output, scale_range):
  18. """
  19. output: (N, 5+class) shape
  20. """
  21. min_scale, max_scale = scale_range
  22. w = output[:, 2] - output[:, 0]
  23. h = output[:, 3] - output[:, 1]
  24. keep = (w * h > min_scale * min_scale) & (w * h < max_scale * max_scale)
  25. return output[keep]
  26. def postprocess(prediction, num_classes, conf_thre=0.7, nms_thre=0.45):
  27. box_corner = prediction.new(prediction.shape)
  28. box_corner[:, :, 0] = prediction[:, :, 0] - prediction[:, :, 2] / 2
  29. box_corner[:, :, 1] = prediction[:, :, 1] - prediction[:, :, 3] / 2
  30. box_corner[:, :, 2] = prediction[:, :, 0] + prediction[:, :, 2] / 2
  31. box_corner[:, :, 3] = prediction[:, :, 1] + prediction[:, :, 3] / 2
  32. prediction[:, :, :4] = box_corner[:, :, :4]
  33. output = [None for _ in range(len(prediction))]
  34. for i, image_pred in enumerate(prediction):
  35. # If none are remaining => process next image
  36. if not image_pred.size(0):
  37. continue
  38. # Get score and class with highest confidence
  39. class_conf, class_pred = torch.max(
  40. image_pred[:, 5 : 5 + num_classes], 1, keepdim=True
  41. )
  42. conf_mask = (image_pred[:, 4] * class_conf.squeeze() >= conf_thre).squeeze()
  43. # _, conf_mask = torch.topk((image_pred[:, 4] * class_conf.squeeze()), 1000)
  44. # Detections ordered as (x1, y1, x2, y2, obj_conf, class_conf, class_pred)
  45. detections = torch.cat((image_pred[:, :5], class_conf, class_pred.float()), 1)
  46. detections = detections[conf_mask]
  47. if not detections.size(0):
  48. continue
  49. nms_out_index = torchvision.ops.batched_nms(
  50. detections[:, :4],
  51. detections[:, 4] * detections[:, 5],
  52. detections[:, 6],
  53. nms_thre,
  54. )
  55. detections = detections[nms_out_index]
  56. if output[i] is None:
  57. output[i] = detections
  58. else:
  59. output[i] = torch.cat((output[i], detections))
  60. return output
  61. def bboxes_iou(bboxes_a, bboxes_b, xyxy=True):
  62. if bboxes_a.shape[1] != 4 or bboxes_b.shape[1] != 4:
  63. raise IndexError
  64. if xyxy:
  65. tl = torch.max(bboxes_a[:, None, :2], bboxes_b[:, :2])
  66. br = torch.min(bboxes_a[:, None, 2:], bboxes_b[:, 2:])
  67. area_a = torch.prod(bboxes_a[:, 2:] - bboxes_a[:, :2], 1)
  68. area_b = torch.prod(bboxes_b[:, 2:] - bboxes_b[:, :2], 1)
  69. else:
  70. tl = torch.max(
  71. (bboxes_a[:, None, :2] - bboxes_a[:, None, 2:] / 2),
  72. (bboxes_b[:, :2] - bboxes_b[:, 2:] / 2),
  73. )
  74. br = torch.min(
  75. (bboxes_a[:, None, :2] + bboxes_a[:, None, 2:] / 2),
  76. (bboxes_b[:, :2] + bboxes_b[:, 2:] / 2),
  77. )
  78. area_a = torch.prod(bboxes_a[:, 2:], 1)
  79. area_b = torch.prod(bboxes_b[:, 2:], 1)
  80. en = (tl < br).type(tl.type()).prod(dim=2)
  81. area_i = torch.prod(br - tl, 2) * en # * ((tl < br).all())
  82. return area_i / (area_a[:, None] + area_b - area_i)
  83. def matrix_iou(a, b):
  84. """
  85. return iou of a and b, numpy version for data augenmentation
  86. """
  87. lt = np.maximum(a[:, np.newaxis, :2], b[:, :2])
  88. rb = np.minimum(a[:, np.newaxis, 2:], b[:, 2:])
  89. area_i = np.prod(rb - lt, axis=2) * (lt < rb).all(axis=2)
  90. area_a = np.prod(a[:, 2:] - a[:, :2], axis=1)
  91. area_b = np.prod(b[:, 2:] - b[:, :2], axis=1)
  92. return area_i / (area_a[:, np.newaxis] + area_b - area_i + 1e-12)
  93. def adjust_box_anns(bbox, scale_ratio, padw, padh, w_max, h_max):
  94. #bbox[:, 0::2] = np.clip(bbox[:, 0::2] * scale_ratio + padw, 0, w_max)
  95. #bbox[:, 1::2] = np.clip(bbox[:, 1::2] * scale_ratio + padh, 0, h_max)
  96. bbox[:, 0::2] = bbox[:, 0::2] * scale_ratio + padw
  97. bbox[:, 1::2] = bbox[:, 1::2] * scale_ratio + padh
  98. return bbox
  99. def xyxy2xywh(bboxes):
  100. bboxes[:, 2] = bboxes[:, 2] - bboxes[:, 0]
  101. bboxes[:, 3] = bboxes[:, 3] - bboxes[:, 1]
  102. return bboxes
  103. def xyxy2cxcywh(bboxes):
  104. bboxes[:, 2] = bboxes[:, 2] - bboxes[:, 0]
  105. bboxes[:, 3] = bboxes[:, 3] - bboxes[:, 1]
  106. bboxes[:, 0] = bboxes[:, 0] + bboxes[:, 2] * 0.5
  107. bboxes[:, 1] = bboxes[:, 1] + bboxes[:, 3] * 0.5
  108. return bboxes