postprocessor.cc 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "ultra_infer/vision/detection/contrib/rknpu2/postprocessor.h"
  15. #include "ultra_infer/vision/utils/utils.h"
  16. namespace ultra_infer {
  17. namespace vision {
  18. namespace detection {
  19. RKYOLOPostprocessor::RKYOLOPostprocessor() {}
  20. bool RKYOLOPostprocessor::Run(const std::vector<FDTensor> &tensors,
  21. std::vector<DetectionResult> *results) {
  22. results->resize(tensors[0].shape[0]);
  23. for (int num = 0; num < tensors[0].shape[0]; ++num) {
  24. int validCount = 0;
  25. std::vector<float> filterBoxes;
  26. std::vector<float> boxesScore;
  27. std::vector<int> classId;
  28. for (int i = 0; i < tensors.size(); i++) {
  29. auto tensor_shape = tensors[i].shape;
  30. auto skip_num = std::accumulate(tensor_shape.begin(), tensor_shape.end(),
  31. 1, std::multiplies<int>());
  32. int skip_address = num * skip_num;
  33. int stride = strides_[i];
  34. int grid_h = height_ / stride;
  35. int grid_w = width_ / stride;
  36. int *anchor = &(anchors_.data()[i * 2 * anchor_per_branch_]);
  37. if (tensors[i].dtype == FDDataType::FP32) {
  38. validCount = validCount +
  39. ProcessFP16((float *)tensors[i].Data() + skip_address,
  40. anchor, grid_h, grid_w, stride, filterBoxes,
  41. boxesScore, classId, conf_threshold_);
  42. } else {
  43. FDERROR << "RKYOLO Only Support FP32 Model."
  44. << "But the result's type is " << Str(tensors[i].dtype)
  45. << std::endl;
  46. }
  47. }
  48. // no object detect
  49. if (validCount <= 0) {
  50. FDINFO << "The number of object detect is 0." << std::endl;
  51. return true;
  52. }
  53. std::vector<int> indexArray;
  54. for (int i = 0; i < validCount; ++i) {
  55. indexArray.push_back(i);
  56. }
  57. QuickSortIndiceInverse(boxesScore, 0, validCount - 1, indexArray);
  58. if (anchor_per_branch_ == 3) {
  59. NMS(validCount, filterBoxes, classId, indexArray, nms_threshold_, false);
  60. } else if (anchor_per_branch_ == 1) {
  61. NMS(validCount, filterBoxes, classId, indexArray, nms_threshold_, true);
  62. } else {
  63. FDERROR << "anchor_per_branch_ only support 3 or 1." << std::endl;
  64. return false;
  65. }
  66. int last_count = 0;
  67. (*results)[num].Clear();
  68. (*results)[num].Reserve(validCount);
  69. /* box valid detect target */
  70. for (int i = 0; i < validCount; ++i) {
  71. if (indexArray[i] == -1 || boxesScore[i] < conf_threshold_ ||
  72. last_count >= obj_num_bbox_max_size) {
  73. continue;
  74. }
  75. int n = indexArray[i];
  76. float x1 = filterBoxes[n * 4 + 0];
  77. float y1 = filterBoxes[n * 4 + 1];
  78. float x2 = x1 + filterBoxes[n * 4 + 2];
  79. float y2 = y1 + filterBoxes[n * 4 + 3];
  80. int id = classId[n];
  81. (*results)[num].boxes.emplace_back(std::array<float, 4>{
  82. (float)((Clamp(x1, 0, width_) - pad_hw_values_[num][1] / 2) /
  83. scale_[num]),
  84. (float)((Clamp(y1, 0, height_) - pad_hw_values_[num][0] / 2) /
  85. scale_[num]),
  86. (float)((Clamp(x2, 0, width_) - pad_hw_values_[num][1] / 2) /
  87. scale_[num]),
  88. (float)((Clamp(y2, 0, height_) - pad_hw_values_[num][0] / 2) /
  89. scale_[0])});
  90. (*results)[num].label_ids.push_back(id);
  91. (*results)[num].scores.push_back(boxesScore[i]);
  92. last_count++;
  93. }
  94. }
  95. return true;
  96. }
  97. int RKYOLOPostprocessor::ProcessFP16(float *input, int *anchor, int grid_h,
  98. int grid_w, int stride,
  99. std::vector<float> &boxes,
  100. std::vector<float> &boxScores,
  101. std::vector<int> &classId,
  102. float threshold) {
  103. int validCount = 0;
  104. int grid_len = grid_h * grid_w;
  105. // float thres_sigmoid = threshold;
  106. for (int a = 0; a < anchor_per_branch_; a++) {
  107. for (int i = 0; i < grid_h; i++) {
  108. for (int j = 0; j < grid_w; j++) {
  109. float box_confidence =
  110. input[(prob_box_size_ * a + 4) * grid_len + i * grid_w + j];
  111. if (box_confidence >= threshold) {
  112. int offset = (prob_box_size_ * a) * grid_len + i * grid_w + j;
  113. float *in_ptr = input + offset;
  114. float maxClassProbs = in_ptr[5 * grid_len];
  115. int maxClassId = 0;
  116. for (int k = 1; k < obj_class_num_; ++k) {
  117. float prob = in_ptr[(5 + k) * grid_len];
  118. if (prob > maxClassProbs) {
  119. maxClassId = k;
  120. maxClassProbs = prob;
  121. }
  122. }
  123. float box_conf_f32 = (box_confidence);
  124. float class_prob_f32 = (maxClassProbs);
  125. float limit_score = 0;
  126. if (anchor_per_branch_ == 1) {
  127. limit_score = class_prob_f32;
  128. } else {
  129. limit_score = box_conf_f32 * class_prob_f32;
  130. }
  131. if (limit_score > conf_threshold_) {
  132. float box_x, box_y, box_w, box_h;
  133. if (anchor_per_branch_ == 1) {
  134. box_x = *in_ptr;
  135. box_y = (in_ptr[grid_len]);
  136. box_w = exp(in_ptr[2 * grid_len]) * stride;
  137. box_h = exp(in_ptr[3 * grid_len]) * stride;
  138. } else {
  139. box_x = *in_ptr * 2.0 - 0.5;
  140. box_y = (in_ptr[grid_len]) * 2.0 - 0.5;
  141. box_w = (in_ptr[2 * grid_len]) * 2.0;
  142. box_h = (in_ptr[3 * grid_len]) * 2.0;
  143. box_w *= box_w;
  144. box_h *= box_h;
  145. }
  146. box_x = (box_x + j) * (float)stride;
  147. box_y = (box_y + i) * (float)stride;
  148. box_w *= (float)anchor[a * 2];
  149. box_h *= (float)anchor[a * 2 + 1];
  150. box_x -= (box_w / 2.0);
  151. box_y -= (box_h / 2.0);
  152. boxes.push_back(box_x);
  153. boxes.push_back(box_y);
  154. boxes.push_back(box_w);
  155. boxes.push_back(box_h);
  156. boxScores.push_back(box_conf_f32 * class_prob_f32);
  157. classId.push_back(maxClassId);
  158. validCount++;
  159. }
  160. }
  161. }
  162. }
  163. }
  164. return validCount;
  165. }
  166. int RKYOLOPostprocessor::QuickSortIndiceInverse(std::vector<float> &input,
  167. int left, int right,
  168. std::vector<int> &indices) {
  169. float key;
  170. int key_index;
  171. int low = left;
  172. int high = right;
  173. if (left < right) {
  174. key_index = indices[left];
  175. key = input[left];
  176. while (low < high) {
  177. while (low < high && input[high] <= key) {
  178. high--;
  179. }
  180. input[low] = input[high];
  181. indices[low] = indices[high];
  182. while (low < high && input[low] >= key) {
  183. low++;
  184. }
  185. input[high] = input[low];
  186. indices[high] = indices[low];
  187. }
  188. input[low] = key;
  189. indices[low] = key_index;
  190. QuickSortIndiceInverse(input, left, low - 1, indices);
  191. QuickSortIndiceInverse(input, low + 1, right, indices);
  192. }
  193. return low;
  194. }
  195. } // namespace detection
  196. } // namespace vision
  197. } // namespace ultra_infer