preprocess_op.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. if (item["is_scale"]) is_scale_ = item["is_scale"].as<bool>();
  60. if (item["norm_type"]) norm_type_ = item["norm_type"].as<std::string>();
  61. }
  62. virtual void Run(cv::Mat* im, ImageBlob* data);
  63. private:
  64. // CHW or HWC
  65. std::vector<float> mean_;
  66. std::vector<float> scale_;
  67. bool is_scale_ = true;
  68. std::string norm_type_ = "mean_std";
  69. };
  70. class Permute : public PreprocessOp {
  71. public:
  72. virtual void Init(const YAML::Node& item) {}
  73. virtual void Run(cv::Mat* im, ImageBlob* data);
  74. };
  75. class Resize : public PreprocessOp {
  76. public:
  77. virtual void Init(const YAML::Node& item) {
  78. interp_ = item["interp"].as<int>();
  79. keep_ratio_ = item["keep_ratio"].as<bool>();
  80. target_size_ = item["target_size"].as<std::vector<int>>();
  81. }
  82. // Compute best resize scale for x-dimension, y-dimension
  83. std::pair<float, float> GenerateScale(const cv::Mat& im);
  84. virtual void Run(cv::Mat* im, ImageBlob* data);
  85. private:
  86. int interp_;
  87. bool keep_ratio_;
  88. std::vector<int> target_size_;
  89. std::vector<int> in_net_shape_;
  90. };
  91. class LetterBoxResize : public PreprocessOp {
  92. public:
  93. virtual void Init(const YAML::Node& item) {
  94. target_size_ = item["target_size"].as<std::vector<int>>();
  95. }
  96. float GenerateScale(const cv::Mat& im);
  97. virtual void Run(cv::Mat* im, ImageBlob* data);
  98. private:
  99. std::vector<int> target_size_;
  100. std::vector<int> in_net_shape_;
  101. };
  102. // Models with FPN need input shape % stride == 0
  103. class PadStride : public PreprocessOp {
  104. public:
  105. virtual void Init(const YAML::Node& item) {
  106. stride_ = item["stride"].as<int>();
  107. }
  108. virtual void Run(cv::Mat* im, ImageBlob* data);
  109. private:
  110. int stride_;
  111. };
  112. class TopDownEvalAffine : public PreprocessOp {
  113. public:
  114. virtual void Init(const YAML::Node& item) {
  115. trainsize_ = item["trainsize"].as<std::vector<int>>();
  116. }
  117. virtual void Run(cv::Mat* im, ImageBlob* data);
  118. private:
  119. int interp_ = 1;
  120. std::vector<int> trainsize_;
  121. };
  122. class WarpAffine : public PreprocessOp {
  123. public:
  124. virtual void Init(const YAML::Node& item) {
  125. input_h_ = item["input_h"].as<int>();
  126. input_w_ = item["input_w"].as<int>();
  127. keep_res_ = item["keep_res"].as<bool>();
  128. }
  129. virtual void Run(cv::Mat* im, ImageBlob* data);
  130. private:
  131. int input_h_;
  132. int input_w_;
  133. int interp_ = 1;
  134. bool keep_res_ = true;
  135. int pad_ = 31;
  136. };
  137. class Pad : public PreprocessOp {
  138. public:
  139. virtual void Init(const YAML::Node& item) {
  140. size_ = item["size"].as<std::vector<int>>();
  141. fill_value_ = item["fill_value"].as<std::vector<float>>();
  142. }
  143. virtual void Run(cv::Mat* im, ImageBlob* data);
  144. private:
  145. std::vector<int> size_;
  146. std::vector<float> fill_value_;
  147. };
  148. void CropImg(cv::Mat& img,
  149. cv::Mat& crop_img,
  150. std::vector<int>& area,
  151. std::vector<float>& center,
  152. std::vector<float>& scale,
  153. float expandratio = 0.15);
  154. // check whether the input size is dynamic
  155. bool CheckDynamicInput(const std::vector<cv::Mat>& imgs);
  156. // Pad images in batch
  157. std::vector<cv::Mat> PadBatch(const std::vector<cv::Mat>& imgs);
  158. class Preprocessor {
  159. public:
  160. void Init(const YAML::Node& config_node) {
  161. // initialize image info at first
  162. ops_["InitInfo"] = std::make_shared<InitInfo>();
  163. for (const auto& item : config_node) {
  164. auto op_name = item["type"].as<std::string>();
  165. ops_[op_name] = CreateOp(op_name);
  166. ops_[op_name]->Init(item);
  167. }
  168. }
  169. std::shared_ptr<PreprocessOp> CreateOp(const std::string& name) {
  170. if (name == "Resize") {
  171. return std::make_shared<Resize>();
  172. } else if (name == "LetterBoxResize") {
  173. return std::make_shared<LetterBoxResize>();
  174. } else if (name == "Permute") {
  175. return std::make_shared<Permute>();
  176. } else if (name == "NormalizeImage") {
  177. return std::make_shared<NormalizeImage>();
  178. } else if (name == "PadStride") {
  179. // use PadStride instead of PadBatch
  180. return std::make_shared<PadStride>();
  181. } else if (name == "TopDownEvalAffine") {
  182. return std::make_shared<TopDownEvalAffine>();
  183. } else if (name == "WarpAffine") {
  184. return std::make_shared<WarpAffine>();
  185. }else if (name == "Pad") {
  186. return std::make_shared<Pad>();
  187. }
  188. std::cerr << "can not find function of OP: " << name
  189. << " and return: nullptr" << std::endl;
  190. return nullptr;
  191. }
  192. void Run(cv::Mat* im, ImageBlob* data);
  193. public:
  194. static const std::vector<std::string> RUN_ORDER;
  195. private:
  196. std::unordered_map<std::string, std::shared_ptr<PreprocessOp>> ops_;
  197. };
  198. } // namespace PaddleDetection