seg_postprocess.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. #include <time.h>
  15. #include "model_deploy/ppseg/include/seg_postprocess.h"
  16. namespace PaddleDeploy {
  17. bool SegPostprocess::Init(const YAML::Node& yaml_config) {
  18. return true;
  19. }
  20. void SegPostprocess::RestoreSegMap(const ShapeInfo& shape_info,
  21. cv::Mat* label_mat,
  22. cv::Mat* score_mat,
  23. SegResult* result) {
  24. int ori_h = shape_info.shapes[0][1];
  25. int ori_w = shape_info.shapes[0][0];
  26. result->label_map.Resize({ori_h, ori_w});
  27. result->score_map.Resize({ori_h, ori_w});
  28. for (int j = shape_info.transforms.size() - 1; j > 0; --j) {
  29. std::vector<int> last_shape = shape_info.shapes[j - 1];
  30. std::vector<int> cur_shape = shape_info.shapes[j];
  31. if (shape_info.transforms[j] == "Resize" ||
  32. shape_info.transforms[j] == "ResizeByShort" ||
  33. shape_info.transforms[j] == "ResizeByLong") {
  34. if (last_shape[0] != label_mat->cols ||
  35. last_shape[1] != label_mat->rows) {
  36. cv::resize(*label_mat, *label_mat,
  37. cv::Size(last_shape[0], last_shape[1]),
  38. 0, 0, cv::INTER_NEAREST);
  39. cv::resize(*score_mat, *score_mat,
  40. cv::Size(last_shape[0], last_shape[1]),
  41. 0, 0, cv::INTER_LINEAR);
  42. }
  43. } else if (shape_info.transforms[j] == "Padding") {
  44. if (last_shape[0] < label_mat->cols || last_shape[1] < label_mat->rows) {
  45. *label_mat = (*label_mat)(cv::Rect(0, 0, last_shape[0], last_shape[1]));
  46. *score_mat = (*score_mat)(cv::Rect(0, 0, last_shape[0], last_shape[1]));
  47. }
  48. }
  49. }
  50. result->label_map.data.assign(
  51. label_mat->begin<uint8_t>(), label_mat->end<uint8_t>());
  52. result->score_map.data.assign(
  53. score_mat->begin<float>(), score_mat->end<float>());
  54. }
  55. bool SegPostprocess::RunV2(const DataBlob& output,
  56. const std::vector<ShapeInfo>& shape_infos,
  57. std::vector<Result>* results, int thread_num) {
  58. int batch_size = shape_infos.size();
  59. std::vector<int> score_map_shape = output.shape;
  60. int score_map_size = std::accumulate(output.shape.begin() + 1,
  61. output.shape.end(), 1,
  62. std::multiplies<int>());
  63. const uint8_t* score_map_data =
  64. reinterpret_cast<const uint8_t*>(output.data.data());
  65. int num_map_pixels = output.shape[1] * output.shape[2];
  66. for (int i = 0; i < batch_size; ++i) {
  67. (*results)[i].model_type = "seg";
  68. (*results)[i].seg_result = new SegResult();
  69. const uint8_t* current_start_ptr = score_map_data + i * score_map_size;
  70. cv::Mat score_mat(output.shape[1], output.shape[2],
  71. CV_32FC1, cv::Scalar(1.0));
  72. cv::Mat label_mat(output.shape[1], output.shape[2],
  73. CV_8UC1, const_cast<uint8_t*>(current_start_ptr));
  74. RestoreSegMap(shape_infos[i], &label_mat,
  75. &score_mat, (*results)[i].seg_result);
  76. }
  77. return true;
  78. }
  79. bool SegPostprocess::Run(const std::vector<DataBlob>& outputs,
  80. const std::vector<ShapeInfo>& shape_infos,
  81. std::vector<Result>* results, int thread_num) {
  82. if (outputs.size() == 0) {
  83. std::cerr << "empty output on SegPostprocess" << std::endl;
  84. return true;
  85. }
  86. results->clear();
  87. int batch_size = shape_infos.size();
  88. results->resize(batch_size);
  89. // tricks for PaddleX, which segmentation model has two outputs
  90. int index = 0;
  91. if (outputs.size() == 2) {
  92. index = 1;
  93. }
  94. std::vector<int> score_map_shape = outputs[index].shape;
  95. // ppseg version >= 2.1 shape = [b, w, h]
  96. if (score_map_shape.size() == 3) {
  97. return RunV2(outputs[index], shape_infos, results, thread_num);
  98. }
  99. int score_map_size = std::accumulate(score_map_shape.begin() + 1,
  100. score_map_shape.end(), 1, std::multiplies<int>());
  101. const float* score_map_data =
  102. reinterpret_cast<const float*>(outputs[index].data.data());
  103. int num_map_pixels = score_map_shape[2] * score_map_shape[3];
  104. for (int i = 0; i < batch_size; ++i) {
  105. (*results)[i].model_type = "seg";
  106. (*results)[i].seg_result = new SegResult();
  107. const float* current_start_ptr = score_map_data + i * score_map_size;
  108. cv::Mat ori_score_mat(score_map_shape[1],
  109. score_map_shape[2] * score_map_shape[3],
  110. CV_32FC1, const_cast<float*>(current_start_ptr));
  111. ori_score_mat = ori_score_mat.t();
  112. cv::Mat score_mat(score_map_shape[2], score_map_shape[3], CV_32FC1);
  113. cv::Mat label_mat(score_map_shape[2], score_map_shape[3], CV_8UC1);
  114. for (int j = 0; j < ori_score_mat.rows; ++j) {
  115. double max_value;
  116. cv::Point max_id;
  117. minMaxLoc(ori_score_mat.row(j), 0, &max_value, 0, &max_id);
  118. score_mat.at<float>(j) = max_value;
  119. label_mat.at<uchar>(j) = max_id.x;
  120. }
  121. RestoreSegMap(shape_infos[i], &label_mat,
  122. &score_mat, (*results)[i].seg_result);
  123. }
  124. return true;
  125. }
  126. } // namespace PaddleDeploy