Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

#378 Feature/sg 281 add kd notebook

Merged
Ghost merged 1 commits into Deci-AI:master from deci-ai:feature/SG-281-add_kd_notebook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  1. import itertools
  2. from math import sqrt
  3. from typing import List
  4. import numpy as np
  5. import torch
  6. from super_gradients.training.utils.detection_utils import non_max_suppression, NMS_Type, \
  7. matrix_non_max_suppression, DetectionPostPredictionCallback
  8. class DefaultBoxes(object):
  9. """
  10. Default Boxes, (aka: anchor boxes or priors boxes) used by SSD model
  11. """
  12. def __init__(self, fig_size: int, feat_size: List[int], scales: List[int], aspect_ratios: List[List[int]],
  13. scale_xy=0.1, scale_wh=0.2):
  14. """
  15. For each feature map i (each predicting level, grids) the anchors (a.k.a. default boxes) will be:
  16. [
  17. [s, s], [sqrt(s * s_next), sqrt(s * s_next)],
  18. [s * sqrt(alpha1), s / sqrt(alpha1)], [s / sqrt(alpha1), s * sqrt(alpha1)],
  19. ...
  20. [s * sqrt(alphaN), s / sqrt(alphaN)], [s / sqrt(alphaN), s * sqrt(alphaN)]
  21. ] / fig_size
  22. where:
  23. * s = scale[i] - this level's scale
  24. * s_next = scale[i + 1] - next level's scale
  25. * alpha1, ... alphaN - this level's alphas, e.g. [2, 3]
  26. * fig_size - input image resolution
  27. Because of division by image resolution, the anchors will be in image coordinates normalized to [0, 1]
  28. :param fig_size: input image resolution
  29. :param feat_size: resolution of all feature maps with predictions (grids)
  30. :param scales: anchor sizes in pixels for each feature level;
  31. one value per level will be used to generate anchors based on the formula above
  32. :param aspect_ratios: lists of alpha values for each feature map
  33. :param scale_xy: predicted boxes will be with a factor scale_xy
  34. so will be multiplied by scale_xy during post-prediction processing;
  35. e.g. scale 0.1 means that prediction will be 10 times bigger
  36. (improves predictions quality)
  37. :param scale_wh: same logic as in scale_xy, but for width and height.
  38. """
  39. self.feat_size = feat_size
  40. self.fig_size = fig_size
  41. self.scale_xy_ = scale_xy
  42. self.scale_wh_ = scale_wh
  43. # According to https://github.com/weiliu89/caffe
  44. # Calculation method slightly different from paper
  45. self.scales = scales
  46. self.aspect_ratios = aspect_ratios
  47. self.default_boxes = []
  48. self.num_anchors = []
  49. # size of feature and number of feature
  50. for idx, sfeat in enumerate(self.feat_size):
  51. sk1 = scales[idx]
  52. sk2 = scales[idx + 1]
  53. sk3 = sqrt(sk1 * sk2)
  54. all_sizes = [(sk1, sk1), (sk3, sk3)]
  55. for alpha in aspect_ratios[idx]:
  56. w, h = sk1 * sqrt(alpha), sk1 / sqrt(alpha)
  57. all_sizes.append((w, h))
  58. all_sizes.append((h, w))
  59. all_sizes = np.array(all_sizes) / fig_size
  60. self.num_anchors.append(len(all_sizes))
  61. for w, h in all_sizes:
  62. for i, j in itertools.product(range(sfeat), repeat=2):
  63. cx, cy = (j + 0.5) / sfeat, (i + 0.5) / sfeat
  64. self.default_boxes.append((cx, cy, w, h))
  65. self.dboxes = torch.tensor(self.default_boxes, dtype=torch.float)
  66. self.dboxes.clamp_(min=0, max=1)
  67. # For IoU calculation
  68. self.dboxes_xyxy = self.dboxes.clone()
  69. self.dboxes_xyxy[:, 0] = self.dboxes[:, 0] - 0.5 * self.dboxes[:, 2]
  70. self.dboxes_xyxy[:, 1] = self.dboxes[:, 1] - 0.5 * self.dboxes[:, 3]
  71. self.dboxes_xyxy[:, 2] = self.dboxes[:, 0] + 0.5 * self.dboxes[:, 2]
  72. self.dboxes_xyxy[:, 3] = self.dboxes[:, 1] + 0.5 * self.dboxes[:, 3]
  73. @property
  74. def scale_xy(self):
  75. return self.scale_xy_
  76. @property
  77. def scale_wh(self):
  78. return self.scale_wh_
  79. def __call__(self, order="xyxy"):
  80. if order == "xyxy":
  81. return self.dboxes_xyxy
  82. if order == "xywh":
  83. return self.dboxes
  84. class SSDPostPredictCallback(DetectionPostPredictionCallback):
  85. """
  86. post prediction callback module to convert and filter predictions coming from the SSD net to a format
  87. used by all other detection models
  88. """
  89. def __init__(self, conf: float = 0.001, iou: float = 0.6, classes: list = None,
  90. max_predictions: int = 300,
  91. nms_type: NMS_Type = NMS_Type.ITERATIVE,
  92. multi_label_per_box=True):
  93. """
  94. Predictions of SSD contain unnormalized probabilities for a background class,
  95. together with confidences for all the dataset classes. Background will be utilized and discarded,
  96. so this callback will return 0-based classes without background
  97. :param conf: confidence threshold
  98. :param iou: IoU threshold
  99. :param classes: (optional list) filter by class
  100. :param nms_type: the type of nms to use (iterative or matrix)
  101. :param multi_label_per_box: whether to use re-use each box with all possible labels
  102. (instead of the maximum confidence all confidences above threshold
  103. will be sent to NMS)
  104. """
  105. super(SSDPostPredictCallback, self).__init__()
  106. self.conf = conf
  107. self.iou = iou
  108. self.nms_type = nms_type
  109. self.classes = classes
  110. self.max_predictions = max_predictions
  111. self.multi_label_per_box = multi_label_per_box
  112. def forward(self, predictions, device=None):
  113. nms_input = predictions[0]
  114. if self.nms_type == NMS_Type.ITERATIVE:
  115. nms_res = non_max_suppression(nms_input, conf_thres=self.conf, iou_thres=self.iou,
  116. multi_label_per_box=self.multi_label_per_box, with_confidence=True)
  117. else:
  118. nms_res = matrix_non_max_suppression(nms_input, conf_thres=self.conf,
  119. max_num_of_detections=self.max_predictions)
  120. return self._filter_max_predictions(nms_res)
  121. def _filter_max_predictions(self, res: List) -> List:
  122. res[:] = [im[:self.max_predictions] if (im is not None and im.shape[0] > self.max_predictions) else im for im in res]
  123. return res
Discard
Tip!

Press p or to see the previous file or, n or to see the next file