preprocessor.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Copyright (c) 2022 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 "ultra_infer/vision/segmentation/ppseg/preprocessor.h"
  15. #include "ultra_infer/function/concat.h"
  16. #include "yaml-cpp/yaml.h"
  17. namespace ultra_infer {
  18. namespace vision {
  19. namespace segmentation {
  20. PaddleSegPreprocessor::PaddleSegPreprocessor(const std::string &config_file) {
  21. this->config_file_ = config_file;
  22. FDASSERT(BuildPreprocessPipelineFromConfig(),
  23. "Failed to create PaddleSegPreprocessor.");
  24. initialized_ = true;
  25. }
  26. bool PaddleSegPreprocessor::BuildPreprocessPipelineFromConfig() {
  27. processors_.clear();
  28. YAML::Node cfg;
  29. processors_.push_back(std::make_shared<BGR2RGB>());
  30. try {
  31. cfg = YAML::LoadFile(config_file_);
  32. } catch (YAML::BadFile &e) {
  33. FDERROR << "Failed to load yaml file " << config_file_
  34. << ", maybe you should check this file." << std::endl;
  35. return false;
  36. }
  37. if (cfg["Deploy"]["transforms"]) {
  38. auto preprocess_cfg = cfg["Deploy"]["transforms"];
  39. for (const auto &op : preprocess_cfg) {
  40. FDASSERT(op.IsMap(),
  41. "Require the transform information in yaml be Map type.");
  42. if (op["type"].as<std::string>() == "Normalize") {
  43. if (!disable_normalize_) {
  44. std::vector<float> mean = {0.5, 0.5, 0.5};
  45. std::vector<float> std = {0.5, 0.5, 0.5};
  46. if (op["mean"]) {
  47. mean = op["mean"].as<std::vector<float>>();
  48. }
  49. if (op["std"]) {
  50. std = op["std"].as<std::vector<float>>();
  51. }
  52. processors_.push_back(std::make_shared<Normalize>(mean, std));
  53. }
  54. } else if (op["type"].as<std::string>() == "Resize") {
  55. is_contain_resize_op_ = true;
  56. const auto &target_size = op["target_size"];
  57. int resize_width = target_size[0].as<int>();
  58. int resize_height = target_size[1].as<int>();
  59. processors_.push_back(
  60. std::make_shared<Resize>(resize_width, resize_height));
  61. } else {
  62. std::string op_name = op["type"].as<std::string>();
  63. FDERROR << "Unexcepted preprocess operator: " << op_name << "."
  64. << std::endl;
  65. return false;
  66. }
  67. }
  68. }
  69. if (cfg["Deploy"]["input_shape"]) {
  70. auto input_shape = cfg["Deploy"]["input_shape"];
  71. int input_height = input_shape[2].as<int>();
  72. int input_width = input_shape[3].as<int>();
  73. if (input_height != -1 && input_width != -1 && !is_contain_resize_op_) {
  74. is_contain_resize_op_ = true;
  75. processors_.insert(processors_.begin(),
  76. std::make_shared<Resize>(input_width, input_height));
  77. }
  78. }
  79. if (!disable_permute_) {
  80. processors_.push_back(std::make_shared<HWC2CHW>());
  81. }
  82. // Fusion will improve performance
  83. FuseTransforms(&processors_);
  84. return true;
  85. }
  86. bool PaddleSegPreprocessor::Apply(FDMatBatch *image_batch,
  87. std::vector<FDTensor> *outputs) {
  88. std::vector<FDMat> *images = image_batch->mats;
  89. if (!initialized_) {
  90. FDERROR << "The preprocessor is not initialized." << std::endl;
  91. return false;
  92. }
  93. if (images->size() == 0) {
  94. FDERROR << "The size of input images should be greater than 0."
  95. << std::endl;
  96. return false;
  97. }
  98. std::vector<std::array<int, 2>> shape_info;
  99. for (const auto &image : *images) {
  100. shape_info.push_back(
  101. {static_cast<int>(image.Height()), static_cast<int>(image.Width())});
  102. }
  103. (*imgs_info_)["shape_info"] = shape_info;
  104. for (size_t i = 0; i < processors_.size(); ++i) {
  105. if (processors_[i]->Name() == "Resize") {
  106. auto processor = dynamic_cast<Resize *>(processors_[i].get());
  107. int resize_width = -1;
  108. int resize_height = -1;
  109. std::tie(resize_width, resize_height) = processor->GetWidthAndHeight();
  110. if (is_vertical_screen_ && (resize_width > resize_height)) {
  111. if (!(processor->SetWidthAndHeight(resize_height, resize_width))) {
  112. FDERROR << "Failed to set width and height of "
  113. << processors_[i]->Name() << " processor." << std::endl;
  114. }
  115. }
  116. break;
  117. }
  118. }
  119. size_t img_num = images->size();
  120. // Batch preprocess : resize all images to the largest image shape in batch
  121. if (!is_contain_resize_op_ && img_num > 1) {
  122. int max_width = 0;
  123. int max_height = 0;
  124. for (size_t i = 0; i < img_num; ++i) {
  125. max_width = std::max(max_width, ((*images)[i]).Width());
  126. max_height = std::max(max_height, ((*images)[i]).Height());
  127. }
  128. pre_resize_op_->SetWidthAndHeight(max_width, max_height);
  129. for (size_t i = 0; i < img_num; ++i) {
  130. if (!(*pre_resize_op_)(&(*images)[i])) {
  131. FDERROR << "Failed to batch resize max_width and max_height"
  132. << std::endl;
  133. }
  134. }
  135. }
  136. for (size_t i = 0; i < img_num; ++i) {
  137. for (size_t j = 0; j < processors_.size(); ++j) {
  138. if (!(*(processors_[j].get()))(&((*images)[i]))) {
  139. FDERROR << "Failed to process image data in " << processors_[i]->Name()
  140. << "." << std::endl;
  141. return false;
  142. }
  143. }
  144. }
  145. outputs->resize(1);
  146. FDTensor *tensor = image_batch->Tensor();
  147. (*outputs)[0].SetExternalData(tensor->Shape(), tensor->Dtype(),
  148. tensor->Data(), tensor->device,
  149. tensor->device_id);
  150. return true;
  151. }
  152. void PaddleSegPreprocessor::DisableNormalize() {
  153. this->disable_normalize_ = true;
  154. // the DisableNormalize function will be invalid if the configuration file is
  155. // loaded during preprocessing
  156. if (!BuildPreprocessPipelineFromConfig()) {
  157. FDERROR << "Failed to build preprocess pipeline from configuration file."
  158. << std::endl;
  159. }
  160. }
  161. void PaddleSegPreprocessor::DisablePermute() {
  162. this->disable_permute_ = true;
  163. // the DisablePermute function will be invalid if the configuration file is
  164. // loaded during preprocessing
  165. if (!BuildPreprocessPipelineFromConfig()) {
  166. FDERROR << "Failed to build preprocess pipeline from configuration file."
  167. << std::endl;
  168. }
  169. }
  170. } // namespace segmentation
  171. } // namespace vision
  172. } // namespace ultra_infer