preprocess_op.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Copyright (c) 2020 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. #pragma once
  15. #include <glog/logging.h>
  16. #include <yaml-cpp/yaml.h>
  17. #include <iostream>
  18. #include <memory>
  19. #include <string>
  20. #include <unordered_map>
  21. #include <utility>
  22. #include <vector>
  23. #include <opencv2/core/core.hpp>
  24. #include <opencv2/highgui/highgui.hpp>
  25. #include <opencv2/imgproc/imgproc.hpp>
  26. namespace PaddleDetection {
  27. // Object for storing all preprocessed data
  28. class ImageBlob {
  29. public:
  30. // image width and height
  31. std::vector<float> im_shape_;
  32. // Buffer for image data after preprocessing
  33. std::vector<float> im_data_;
  34. // in net data shape(after pad)
  35. std::vector<float> in_net_shape_;
  36. // Evaluation image width and height
  37. // std::vector<float> eval_im_size_f_;
  38. // Scale factor for image size to origin image size
  39. std::vector<float> scale_factor_;
  40. // in net image after preprocessing
  41. cv::Mat in_net_im_;
  42. };
  43. // Abstraction of preprocessing opration class
  44. class PreprocessOp {
  45. public:
  46. virtual void Init(const YAML::Node& item) = 0;
  47. virtual void Run(cv::Mat* im, ImageBlob* data) = 0;
  48. };
  49. class InitInfo : public PreprocessOp {
  50. public:
  51. virtual void Init(const YAML::Node& item) {}
  52. virtual void Run(cv::Mat* im, ImageBlob* data);
  53. };
  54. class NormalizeImage : public PreprocessOp {
  55. public:
  56. virtual void Init(const YAML::Node& item) {
  57. mean_ = item["mean"].as<std::vector<float>>();
  58. scale_ = item["std"].as<std::vector<float>>();
  59. is_scale_ = item["is_scale"].as<bool>();
  60. }
  61. virtual void Run(cv::Mat* im, ImageBlob* data);
  62. private:
  63. // CHW or HWC
  64. std::vector<float> mean_;
  65. std::vector<float> scale_;
  66. bool is_scale_ = true;
  67. };
  68. class Permute : public PreprocessOp {
  69. public:
  70. virtual void Init(const YAML::Node& item) {}
  71. virtual void Run(cv::Mat* im, ImageBlob* data);
  72. };
  73. class Resize : public PreprocessOp {
  74. public:
  75. virtual void Init(const YAML::Node& item) {
  76. interp_ = item["interp"].as<int>();
  77. keep_ratio_ = item["keep_ratio"].as<bool>();
  78. target_size_ = item["target_size"].as<std::vector<int>>();
  79. }
  80. // Compute best resize scale for x-dimension, y-dimension
  81. std::pair<float, float> GenerateScale(const cv::Mat& im);
  82. virtual void Run(cv::Mat* im, ImageBlob* data);
  83. private:
  84. int interp_;
  85. bool keep_ratio_;
  86. std::vector<int> target_size_;
  87. std::vector<int> in_net_shape_;
  88. };
  89. class LetterBoxResize : public PreprocessOp {
  90. public:
  91. virtual void Init(const YAML::Node& item) {
  92. target_size_ = item["target_size"].as<std::vector<int>>();
  93. }
  94. float GenerateScale(const cv::Mat& im);
  95. virtual void Run(cv::Mat* im, ImageBlob* data);
  96. private:
  97. std::vector<int> target_size_;
  98. std::vector<int> in_net_shape_;
  99. };
  100. // Models with FPN need input shape % stride == 0
  101. class PadStride : public PreprocessOp {
  102. public:
  103. virtual void Init(const YAML::Node& item) {
  104. stride_ = item["stride"].as<int>();
  105. }
  106. virtual void Run(cv::Mat* im, ImageBlob* data);
  107. private:
  108. int stride_;
  109. };
  110. class TopDownEvalAffine : public PreprocessOp {
  111. public:
  112. virtual void Init(const YAML::Node& item) {
  113. trainsize_ = item["trainsize"].as<std::vector<int>>();
  114. }
  115. virtual void Run(cv::Mat* im, ImageBlob* data);
  116. private:
  117. int interp_ = 1;
  118. std::vector<int> trainsize_;
  119. };
  120. class WarpAffine : public PreprocessOp {
  121. public:
  122. virtual void Init(const YAML::Node& item) {
  123. input_h_ = item["input_h"].as<int>();
  124. input_w_ = item["input_w"].as<int>();
  125. keep_res_ = item["keep_res"].as<bool>();
  126. }
  127. virtual void Run(cv::Mat* im, ImageBlob* data);
  128. private:
  129. int input_h_;
  130. int input_w_;
  131. int interp_ = 1;
  132. bool keep_res_ = true;
  133. int pad_ = 31;
  134. };
  135. class Pad : public PreprocessOp {
  136. public:
  137. virtual void Init(const YAML::Node& item) {
  138. size_ = item["size"].as<std::vector<int>>();
  139. fill_value_ = item["fill_value"].as<std::vector<float>>();
  140. }
  141. virtual void Run(cv::Mat* im, ImageBlob* data);
  142. private:
  143. std::vector<int> size_;
  144. std::vector<float> fill_value_;
  145. };
  146. void CropImg(cv::Mat& img,
  147. cv::Mat& crop_img,
  148. std::vector<int>& area,
  149. std::vector<float>& center,
  150. std::vector<float>& scale,
  151. float expandratio = 0.15);
  152. // check whether the input size is dynamic
  153. bool CheckDynamicInput(const std::vector<cv::Mat>& imgs);
  154. // Pad images in batch
  155. std::vector<cv::Mat> PadBatch(const std::vector<cv::Mat>& imgs);
  156. class Preprocessor {
  157. public:
  158. void Init(const YAML::Node& config_node) {
  159. // initialize image info at first
  160. ops_["InitInfo"] = std::make_shared<InitInfo>();
  161. for (const auto& item : config_node) {
  162. auto op_name = item["type"].as<std::string>();
  163. ops_[op_name] = CreateOp(op_name);
  164. ops_[op_name]->Init(item);
  165. }
  166. }
  167. std::shared_ptr<PreprocessOp> CreateOp(const std::string& name) {
  168. if (name == "Resize") {
  169. return std::make_shared<Resize>();
  170. } else if (name == "LetterBoxResize") {
  171. return std::make_shared<LetterBoxResize>();
  172. } else if (name == "Permute") {
  173. return std::make_shared<Permute>();
  174. } else if (name == "NormalizeImage") {
  175. return std::make_shared<NormalizeImage>();
  176. } else if (name == "PadStride") {
  177. // use PadStride instead of PadBatch
  178. return std::make_shared<PadStride>();
  179. } else if (name == "TopDownEvalAffine") {
  180. return std::make_shared<TopDownEvalAffine>();
  181. } else if (name == "WarpAffine") {
  182. return std::make_shared<WarpAffine>();
  183. }else if (name == "Pad") {
  184. return std::make_shared<Pad>();
  185. }
  186. std::cerr << "can not find function of OP: " << name
  187. << " and return: nullptr" << std::endl;
  188. return nullptr;
  189. }
  190. void Run(cv::Mat* im, ImageBlob* data);
  191. public:
  192. static const std::vector<std::string> RUN_ORDER;
  193. private:
  194. std::unordered_map<std::string, std::shared_ptr<PreprocessOp>> ops_;
  195. };
  196. } // namespace PaddleDetection