paddlex.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. #include "include/paddlex/paddlex.h"
  15. #include <iostream>
  16. #include <fstream>
  17. namespace PaddleX {
  18. void Model::create_predictor(const std::string& model_dir,
  19. const std::string& cfg_file,
  20. std::string device) {
  21. InferenceEngine::Core ie;
  22. network_ = ie.ReadNetwork(
  23. model_dir, model_dir.substr(0, model_dir.size() - 4) + ".bin");
  24. network_.setBatchSize(1);
  25. InferenceEngine::InputsDataMap inputInfo(network_.getInputsInfo());
  26. std::string imageInputName;
  27. for (const auto & inputInfoItem : inputInfo) {
  28. if (inputInfoItem.second->getTensorDesc().getDims().size() == 4) {
  29. imageInputName = inputInfoItem.first;
  30. inputInfoItem.second->setPrecision(InferenceEngine::Precision::FP32);
  31. inputInfoItem.second->getPreProcess().setResizeAlgorithm(
  32. InferenceEngine::RESIZE_BILINEAR);
  33. inputInfoItem.second->setLayout(InferenceEngine::Layout::NCHW);
  34. }
  35. if (inputInfoItem.second->getTensorDesc().getDims().size() == 2) {
  36. imageInputName = inputInfoItem.first;
  37. inputInfoItem.second->setPrecision(InferenceEngine::Precision::FP32);
  38. }
  39. }
  40. if (device == "MYRIAD") {
  41. std::map<std::string, std::string> networkConfig;
  42. networkConfig["VPU_HW_STAGES_OPTIMIZATION"] = "ON";
  43. executable_network_ = ie.LoadNetwork(network_, device, networkConfig);
  44. } else {
  45. executable_network_ = ie.LoadNetwork(network_, device);
  46. }
  47. load_config(cfg_file);
  48. }
  49. bool Model::load_config(const std::string& cfg_file) {
  50. YAML::Node config = YAML::LoadFile(cfg_file);
  51. type = config["_Attributes"]["model_type"].as<std::string>();
  52. name = config["Model"].as<std::string>();
  53. bool to_rgb = true;
  54. if (config["TransformsMode"].IsDefined()) {
  55. std::string mode = config["TransformsMode"].as<std::string>();
  56. if (mode == "BGR") {
  57. to_rgb = false;
  58. } else if (mode != "RGB") {
  59. std::cerr << "[Init] Only 'RGB' or 'BGR' is supported for TransformsMode"
  60. << std::endl;
  61. return false;
  62. }
  63. }
  64. // init preprocess ops
  65. transforms_.Init(config["Transforms"], type, to_rgb);
  66. // read label list
  67. for (const auto& item : config["_Attributes"]["labels"]) {
  68. int index = labels.size();
  69. labels[index] = item.as<std::string>();
  70. }
  71. return true;
  72. }
  73. bool Model::preprocess(cv::Mat* input_im, ImageBlob* inputs) {
  74. if (!transforms_.Run(input_im, inputs)) {
  75. return false;
  76. }
  77. return true;
  78. }
  79. bool Model::predict(const cv::Mat& im, ClsResult* result) {
  80. inputs_.clear();
  81. if (type == "detector") {
  82. std::cerr << "Loading model is a 'detector', DetResult should be passed to "
  83. "function predict()!"
  84. << std::endl;
  85. return false;
  86. } else if (type == "segmenter") {
  87. std::cerr << "Loading model is a 'segmenter', SegResult should be passed "
  88. "to function predict()!"
  89. << std::endl;
  90. return false;
  91. }
  92. // preprocess
  93. InferenceEngine::InferRequest infer_request =
  94. executable_network_.CreateInferRequest();
  95. std::string input_name = network_.getInputsInfo().begin()->first;
  96. inputs_.blob = infer_request.GetBlob(input_name);
  97. cv::Mat im_clone = im.clone();
  98. if (!preprocess(&im_clone, &inputs_)) {
  99. std::cerr << "Preprocess failed!" << std::endl;
  100. return false;
  101. }
  102. // predict
  103. infer_request.Infer();
  104. std::string output_name = network_.getOutputsInfo().begin()->first;
  105. output_ = infer_request.GetBlob(output_name);
  106. InferenceEngine::MemoryBlob::CPtr moutput =
  107. InferenceEngine::as<InferenceEngine::MemoryBlob>(output_);
  108. auto moutputHolder = moutput->rmap();
  109. float* outputs_data = moutputHolder.as<float *>();
  110. // post process
  111. auto ptr = std::max_element(outputs_data, outputs_data+sizeof(outputs_data));
  112. result->category_id = std::distance(outputs_data, ptr);
  113. result->score = *ptr;
  114. result->category = labels[result->category_id];
  115. return true;
  116. }
  117. bool Model::predict(const cv::Mat& im, DetResult* result) {
  118. inputs_.clear();
  119. result->clear();
  120. if (type == "classifier") {
  121. std::cerr << "Loading model is a 'classifier', ClsResult should be passed "
  122. "to function predict()!" << std::endl;
  123. return false;
  124. } else if (type == "segmenter") {
  125. std::cerr << "Loading model is a 'segmenter', SegResult should be passed "
  126. "to function predict()!" << std::endl;
  127. return false;
  128. }
  129. InferenceEngine::InferRequest infer_request =
  130. executable_network_.CreateInferRequest();
  131. InferenceEngine::InputsDataMap input_maps = network_.getInputsInfo();
  132. std::string inputName;
  133. for (const auto & input_map : input_maps) {
  134. if (input_map.second->getTensorDesc().getDims().size() == 4) {
  135. inputName = input_map.first;
  136. inputs_.blob = infer_request.GetBlob(inputName);
  137. }
  138. if (input_map.second->getTensorDesc().getDims().size() == 2) {
  139. inputName = input_map.first;
  140. inputs_.ori_im_size_ = infer_request.GetBlob(inputName);
  141. }
  142. }
  143. cv::Mat im_clone = im.clone();
  144. if (!preprocess(&im_clone, &inputs_)) {
  145. std::cerr << "Preprocess failed!" << std::endl;
  146. return false;
  147. }
  148. infer_request.Infer();
  149. InferenceEngine::OutputsDataMap out_maps = network_.getOutputsInfo();
  150. std::string outputName;
  151. for (const auto & output_map : out_maps) {
  152. if (output_map.second->getTensorDesc().getDims().size() == 3) {
  153. outputName = output_map.first;
  154. }
  155. }
  156. if (outputName.empty()) {
  157. std::cerr << "get result node failed!" << std::endl:
  158. return false;
  159. }
  160. InferenceEngine::Blob::Ptr output = infer_request.GetBlob(outputName);
  161. InferenceEngine::MemoryBlob::CPtr moutput =
  162. InferenceEngine::as<InferenceEngine::MemoryBlob>(output);
  163. InferenceEngine::TensorDesc blob_output = moutput->getTensorDesc();
  164. std::vector<size_t> output_shape = blob_output.getDims();
  165. auto moutputHolder = moutput->rmap();
  166. float* data = moutputHolder.as<float *>();
  167. int size = 1;
  168. for (auto& i : output_shape) {
  169. size *= static_cast<int>(i);
  170. }
  171. int num_boxes = size / 6;
  172. for (int i = 0; i < num_boxes; ++i) {
  173. if (data[i * 6] > 0) {
  174. Box box;
  175. box.category_id = static_cast<int>(data[i * 6]);
  176. box.category = labels[box.category_id];
  177. box.score = data[i * 6 + 1];
  178. float xmin = data[i * 6 + 2];
  179. float ymin = data[i * 6 + 3];
  180. float xmax = data[i * 6 + 4];
  181. float ymax = data[i * 6 + 5];
  182. float w = xmax - xmin + 1;
  183. float h = ymax - ymin + 1;
  184. box.coordinate = {xmin, ymin, w, h};
  185. result->boxes.push_back(std::move(box));
  186. }
  187. }
  188. }
  189. bool Model::predict(const cv::Mat& im, SegResult* result) {
  190. result->clear();
  191. inputs_.clear();
  192. if (type == "classifier") {
  193. std::cerr << "Loading model is a 'classifier', ClsResult should be passed "
  194. "to function predict()!" << std::endl;
  195. return false;
  196. } else if (type == "detector") {
  197. std::cerr << "Loading model is a 'detector', DetResult should be passed to "
  198. "function predict()!" << std::endl;
  199. return false;
  200. }
  201. // init infer
  202. InferenceEngine::InferRequest infer_request =
  203. executable_network_.CreateInferRequest();
  204. std::string input_name = network_.getInputsInfo().begin()->first;
  205. inputs_.blob = infer_request.GetBlob(input_name);
  206. // preprocess
  207. cv::Mat im_clone = im.clone();
  208. if (!preprocess(&im_clone, &inputs_)) {
  209. std::cerr << "Preprocess failed!" << std::endl;
  210. return false;
  211. }
  212. // predict
  213. infer_request.Infer();
  214. InferenceEngine::OutputsDataMap out_map = network_.getOutputsInfo();
  215. auto iter = out_map.begin();
  216. iter++;
  217. std::string output_name_label = iter->first;
  218. InferenceEngine::Blob::Ptr output_label =
  219. infer_request.GetBlob(output_name_label);
  220. InferenceEngine::MemoryBlob::CPtr moutput_label =
  221. InferenceEngine::as<InferenceEngine::MemoryBlob>(output_label);
  222. InferenceEngine::TensorDesc blob_label = moutput_label->getTensorDesc();
  223. std::vector<size_t> output_label_shape = blob_label.getDims();
  224. int size = 1;
  225. for (auto& i : output_label_shape) {
  226. size *= static_cast<int>(i);
  227. result->label_map.shape.push_back(static_cast<int>(i));
  228. }
  229. result->label_map.data.resize(size);
  230. auto moutputHolder_label = moutput_label->rmap();
  231. int* label_data = moutputHolder_label.as<int *>();
  232. memcpy(result->label_map.data.data(), label_data, moutput_label->byteSize());
  233. iter++;
  234. std::string output_name_score = iter->first;
  235. InferenceEngine::Blob::Ptr output_score =
  236. infer_request.GetBlob(output_name_score);
  237. InferenceEngine::MemoryBlob::CPtr moutput_score =
  238. InferenceEngine::as<InferenceEngine::MemoryBlob>(output_score);
  239. InferenceEngine::TensorDesc blob_score = moutput_score->getTensorDesc();
  240. std::vector<size_t> output_score_shape = blob_score.getDims();
  241. size = 1;
  242. for (auto& i : output_score_shape) {
  243. size *= static_cast<int>(i);
  244. result->score_map.shape.push_back(static_cast<int>(i));
  245. }
  246. result->score_map.data.resize(size);
  247. auto moutputHolder_score = moutput_score->rmap();
  248. float* score_data = moutputHolder_score.as<float *>();
  249. memcpy(result->score_map.data.data(), score_data, moutput_score->byteSize());
  250. std::vector<uint8_t> label_map(result->label_map.data.begin(),
  251. result->label_map.data.end());
  252. cv::Mat mask_label(result->label_map.shape[1],
  253. result->label_map.shape[2],
  254. CV_8UC1,
  255. label_map.data());
  256. cv::Mat mask_score(result->score_map.shape[2],
  257. result->score_map.shape[3],
  258. CV_32FC1,
  259. result->score_map.data.data());
  260. int idx = 1;
  261. int len_postprocess = inputs_.im_size_before_resize_.size();
  262. for (std::vector<std::string>::reverse_iterator iter =
  263. inputs_.reshape_order_.rbegin();
  264. iter != inputs_.reshape_order_.rend();
  265. ++iter) {
  266. if (*iter == "padding") {
  267. auto before_shape = inputs_.im_size_before_resize_[len_postprocess - idx];
  268. inputs_.im_size_before_resize_.pop_back();
  269. auto padding_w = before_shape[0];
  270. auto padding_h = before_shape[1];
  271. mask_label = mask_label(cv::Rect(0, 0, padding_h, padding_w));
  272. mask_score = mask_score(cv::Rect(0, 0, padding_h, padding_w));
  273. } else if (*iter == "resize") {
  274. auto before_shape = inputs_.im_size_before_resize_[len_postprocess - idx];
  275. inputs_.im_size_before_resize_.pop_back();
  276. auto resize_w = before_shape[0];
  277. auto resize_h = before_shape[1];
  278. cv::resize(mask_label,
  279. mask_label,
  280. cv::Size(resize_h, resize_w),
  281. 0,
  282. 0,
  283. cv::INTER_NEAREST);
  284. cv::resize(mask_score,
  285. mask_score,
  286. cv::Size(resize_h, resize_w),
  287. 0,
  288. 0,
  289. cv::INTER_LINEAR);
  290. }
  291. ++idx;
  292. }
  293. result->label_map.data.assign(mask_label.begin<uint8_t>(),
  294. mask_label.end<uint8_t>());
  295. result->label_map.shape = {mask_label.rows, mask_label.cols};
  296. result->score_map.data.assign(mask_score.begin<float>(),
  297. mask_score.end<float>());
  298. result->score_map.shape = {mask_score.rows, mask_score.cols};
  299. return true;
  300. }
  301. } // namespace PaddleX