picodet_postprocess.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (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.0
  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. //
  15. // The code is based on:
  16. // https://github.com/RangiLyu/nanodet/blob/main/demo_mnn/nanodet_mnn.cpp
  17. #include "include/picodet_postprocess.h"
  18. namespace PaddleDetection {
  19. float fast_exp(float x) {
  20. union {
  21. uint32_t i;
  22. float f;
  23. } v{};
  24. v.i = (1 << 23) * (1.4426950409 * x + 126.93490512f);
  25. return v.f;
  26. }
  27. template <typename _Tp>
  28. int activation_function_softmax(const _Tp *src, _Tp *dst, int length) {
  29. const _Tp alpha = *std::max_element(src, src + length);
  30. _Tp denominator{0};
  31. for (int i = 0; i < length; ++i) {
  32. dst[i] = fast_exp(src[i] - alpha);
  33. denominator += dst[i];
  34. }
  35. for (int i = 0; i < length; ++i) {
  36. dst[i] /= denominator;
  37. }
  38. return 0;
  39. }
  40. // PicoDet decode
  41. PaddleDetection::ObjectResult
  42. disPred2Bbox(const float *&dfl_det, int label, float score, int x, int y,
  43. int stride, std::vector<float> im_shape, int reg_max) {
  44. float ct_x = (x + 0.5) * stride;
  45. float ct_y = (y + 0.5) * stride;
  46. std::vector<float> dis_pred;
  47. dis_pred.resize(4);
  48. for (int i = 0; i < 4; i++) {
  49. float dis = 0;
  50. float *dis_after_sm = new float[reg_max + 1];
  51. activation_function_softmax(dfl_det + i * (reg_max + 1), dis_after_sm,
  52. reg_max + 1);
  53. for (int j = 0; j < reg_max + 1; j++) {
  54. dis += j * dis_after_sm[j];
  55. }
  56. dis *= stride;
  57. dis_pred[i] = dis;
  58. delete[] dis_after_sm;
  59. }
  60. int xmin = (int)(std::max)(ct_x - dis_pred[0], .0f);
  61. int ymin = (int)(std::max)(ct_y - dis_pred[1], .0f);
  62. int xmax = (int)(std::min)(ct_x + dis_pred[2], (float)im_shape[0]);
  63. int ymax = (int)(std::min)(ct_y + dis_pred[3], (float)im_shape[1]);
  64. PaddleDetection::ObjectResult result_item;
  65. result_item.rect = {xmin, ymin, xmax, ymax};
  66. result_item.class_id = label;
  67. result_item.confidence = score;
  68. return result_item;
  69. }
  70. void PicoDetPostProcess(std::vector<PaddleDetection::ObjectResult> *results,
  71. std::vector<const float *> outs,
  72. std::vector<int> fpn_stride,
  73. std::vector<float> im_shape,
  74. std::vector<float> scale_factor, float score_threshold,
  75. float nms_threshold, int num_class, int reg_max) {
  76. std::vector<std::vector<PaddleDetection::ObjectResult>> bbox_results;
  77. bbox_results.resize(num_class);
  78. int in_h = im_shape[0], in_w = im_shape[1];
  79. for (int i = 0; i < fpn_stride.size(); ++i) {
  80. int feature_h = std::ceil((float)in_h / fpn_stride[i]);
  81. int feature_w = std::ceil((float)in_w / fpn_stride[i]);
  82. for (int idx = 0; idx < feature_h * feature_w; idx++) {
  83. const float *scores = outs[i] + (idx * num_class);
  84. int row = idx / feature_w;
  85. int col = idx % feature_w;
  86. float score = 0;
  87. int cur_label = 0;
  88. for (int label = 0; label < num_class; label++) {
  89. if (scores[label] > score) {
  90. score = scores[label];
  91. cur_label = label;
  92. }
  93. }
  94. if (score > score_threshold) {
  95. const float *bbox_pred =
  96. outs[i + fpn_stride.size()] + (idx * 4 * (reg_max + 1));
  97. bbox_results[cur_label].push_back(
  98. disPred2Bbox(bbox_pred, cur_label, score, col, row, fpn_stride[i],
  99. im_shape, reg_max));
  100. }
  101. }
  102. }
  103. for (int i = 0; i < (int)bbox_results.size(); i++) {
  104. PaddleDetection::nms(bbox_results[i], nms_threshold);
  105. for (auto box : bbox_results[i]) {
  106. box.rect[0] = box.rect[0] / scale_factor[1];
  107. box.rect[2] = box.rect[2] / scale_factor[1];
  108. box.rect[1] = box.rect[1] / scale_factor[0];
  109. box.rect[3] = box.rect[3] / scale_factor[0];
  110. results->push_back(box);
  111. }
  112. }
  113. }
  114. } // namespace PaddleDetection