paddlex.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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"] = "NO";
  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. InferenceEngine::TensorDesc blob_output = moutput->getTensorDesc();
  109. std::vector<size_t> output_shape = blob_output.getDims();
  110. auto moutputHolder = moutput->rmap();
  111. float* outputs_data = moutputHolder.as<float *>();
  112. int size = 1;
  113. for (auto& i : output_shape) {
  114. size *= static_cast<int>(i);
  115. }
  116. // post process
  117. auto ptr = std::max_element(outputs_data, outputs_data + size);
  118. result->category_id = std::distance(outputs_data, ptr);
  119. result->score = *ptr;
  120. result->category = labels[result->category_id];
  121. return true;
  122. }
  123. bool Model::predict(const cv::Mat& im, DetResult* result) {
  124. inputs_.clear();
  125. result->clear();
  126. if (type == "classifier") {
  127. std::cerr << "Loading model is a 'classifier', ClsResult should be passed "
  128. "to function predict()!" << std::endl;
  129. return false;
  130. } else if (type == "segmenter") {
  131. std::cerr << "Loading model is a 'segmenter', SegResult should be passed "
  132. "to function predict()!" << std::endl;
  133. return false;
  134. }
  135. InferenceEngine::InferRequest infer_request =
  136. executable_network_.CreateInferRequest();
  137. InferenceEngine::InputsDataMap input_maps = network_.getInputsInfo();
  138. std::string inputName;
  139. for (const auto & input_map : input_maps) {
  140. if (input_map.second->getTensorDesc().getDims().size() == 4) {
  141. inputName = input_map.first;
  142. inputs_.blob = infer_request.GetBlob(inputName);
  143. }
  144. if (input_map.second->getTensorDesc().getDims().size() == 2) {
  145. inputName = input_map.first;
  146. inputs_.ori_im_size_ = infer_request.GetBlob(inputName);
  147. }
  148. }
  149. cv::Mat im_clone = im.clone();
  150. if (!preprocess(&im_clone, &inputs_)) {
  151. std::cerr << "Preprocess failed!" << std::endl;
  152. return false;
  153. }
  154. infer_request.Infer();
  155. InferenceEngine::OutputsDataMap out_maps = network_.getOutputsInfo();
  156. std::string outputName;
  157. for (const auto & output_map : out_maps) {
  158. if (output_map.second->getTensorDesc().getDims().size() == 2) {
  159. outputName = output_map.first;
  160. }
  161. }
  162. if (outputName.empty()) {
  163. std::cerr << "get result node failed!" << std::endl;
  164. return false;
  165. }
  166. InferenceEngine::Blob::Ptr output = infer_request.GetBlob(outputName);
  167. InferenceEngine::MemoryBlob::CPtr moutput =
  168. InferenceEngine::as<InferenceEngine::MemoryBlob>(output);
  169. InferenceEngine::TensorDesc blob_output = moutput->getTensorDesc();
  170. std::vector<size_t> output_shape = blob_output.getDims();
  171. auto moutputHolder = moutput->rmap();
  172. float* data = moutputHolder.as<float *>();
  173. int size = 1;
  174. for (auto& i : output_shape) {
  175. size *= static_cast<int>(i);
  176. }
  177. int num_boxes = size / 6;
  178. for (int i = 0; i < num_boxes; ++i) {
  179. if (data[i * 6] >= 0) {
  180. Box box;
  181. box.category_id = static_cast<int>(data[i * 6]);
  182. box.category = labels[box.category_id];
  183. box.score = data[i * 6 + 1];
  184. float xmin = data[i * 6 + 2];
  185. float ymin = data[i * 6 + 3];
  186. float xmax = data[i * 6 + 4];
  187. float ymax = data[i * 6 + 5];
  188. float w = xmax - xmin + 1;
  189. float h = ymax - ymin + 1;
  190. box.coordinate = {xmin, ymin, w, h};
  191. result->boxes.push_back(std::move(box));
  192. }
  193. }
  194. return true;
  195. }
  196. bool Model::predict(const cv::Mat& im, SegResult* result) {
  197. result->clear();
  198. inputs_.clear();
  199. if (type == "classifier") {
  200. std::cerr << "Loading model is a 'classifier', ClsResult should be passed "
  201. "to function predict()!" << std::endl;
  202. return false;
  203. } else if (type == "detector") {
  204. std::cerr << "Loading model is a 'detector', DetResult should be passed to "
  205. "function predict()!" << std::endl;
  206. return false;
  207. }
  208. // init infer
  209. InferenceEngine::InferRequest infer_request =
  210. executable_network_.CreateInferRequest();
  211. std::string input_name = network_.getInputsInfo().begin()->first;
  212. inputs_.blob = infer_request.GetBlob(input_name);
  213. // preprocess
  214. cv::Mat im_clone = im.clone();
  215. if (!preprocess(&im_clone, &inputs_)) {
  216. std::cerr << "Preprocess failed!" << std::endl;
  217. return false;
  218. }
  219. // predict
  220. infer_request.Infer();
  221. InferenceEngine::OutputsDataMap out_map = network_.getOutputsInfo();
  222. auto iter = out_map.begin();
  223. iter++;
  224. std::string output_name_label = iter->first;
  225. InferenceEngine::Blob::Ptr output_label =
  226. infer_request.GetBlob(output_name_label);
  227. InferenceEngine::MemoryBlob::CPtr moutput_label =
  228. InferenceEngine::as<InferenceEngine::MemoryBlob>(output_label);
  229. InferenceEngine::TensorDesc blob_label = moutput_label->getTensorDesc();
  230. std::vector<size_t> output_label_shape = blob_label.getDims();
  231. int size = 1;
  232. for (auto& i : output_label_shape) {
  233. size *= static_cast<int>(i);
  234. result->label_map.shape.push_back(static_cast<int>(i));
  235. }
  236. result->label_map.data.resize(size);
  237. auto moutputHolder_label = moutput_label->rmap();
  238. int* label_data = moutputHolder_label.as<int *>();
  239. memcpy(result->label_map.data.data(), label_data, moutput_label->byteSize());
  240. iter++;
  241. std::string output_name_score = iter->first;
  242. InferenceEngine::Blob::Ptr output_score =
  243. infer_request.GetBlob(output_name_score);
  244. InferenceEngine::MemoryBlob::CPtr moutput_score =
  245. InferenceEngine::as<InferenceEngine::MemoryBlob>(output_score);
  246. InferenceEngine::TensorDesc blob_score = moutput_score->getTensorDesc();
  247. std::vector<size_t> output_score_shape = blob_score.getDims();
  248. size = 1;
  249. for (auto& i : output_score_shape) {
  250. size *= static_cast<int>(i);
  251. result->score_map.shape.push_back(static_cast<int>(i));
  252. }
  253. result->score_map.data.resize(size);
  254. auto moutputHolder_score = moutput_score->rmap();
  255. float* score_data = moutputHolder_score.as<float *>();
  256. memcpy(result->score_map.data.data(), score_data, moutput_score->byteSize());
  257. std::vector<uint8_t> label_map(result->label_map.data.begin(),
  258. result->label_map.data.end());
  259. cv::Mat mask_label(result->label_map.shape[1],
  260. result->label_map.shape[2],
  261. CV_8UC1,
  262. label_map.data());
  263. cv::Mat mask_score(result->score_map.shape[2],
  264. result->score_map.shape[3],
  265. CV_32FC1,
  266. result->score_map.data.data());
  267. int idx = 1;
  268. int len_postprocess = inputs_.im_size_before_resize_.size();
  269. for (std::vector<std::string>::reverse_iterator iter =
  270. inputs_.reshape_order_.rbegin();
  271. iter != inputs_.reshape_order_.rend();
  272. ++iter) {
  273. if (*iter == "padding") {
  274. auto before_shape = inputs_.im_size_before_resize_[len_postprocess - idx];
  275. inputs_.im_size_before_resize_.pop_back();
  276. auto padding_w = before_shape[0];
  277. auto padding_h = before_shape[1];
  278. mask_label = mask_label(cv::Rect(0, 0, padding_h, padding_w));
  279. mask_score = mask_score(cv::Rect(0, 0, padding_h, padding_w));
  280. } else if (*iter == "resize") {
  281. auto before_shape = inputs_.im_size_before_resize_[len_postprocess - idx];
  282. inputs_.im_size_before_resize_.pop_back();
  283. auto resize_w = before_shape[0];
  284. auto resize_h = before_shape[1];
  285. cv::resize(mask_label,
  286. mask_label,
  287. cv::Size(resize_h, resize_w),
  288. 0,
  289. 0,
  290. cv::INTER_NEAREST);
  291. cv::resize(mask_score,
  292. mask_score,
  293. cv::Size(resize_h, resize_w),
  294. 0,
  295. 0,
  296. cv::INTER_LINEAR);
  297. }
  298. ++idx;
  299. }
  300. result->label_map.data.assign(mask_label.begin<uint8_t>(),
  301. mask_label.end<uint8_t>());
  302. result->label_map.shape = {mask_label.rows, mask_label.cols};
  303. result->score_map.data.assign(mask_score.begin<float>(),
  304. mask_score.end<float>());
  305. result->score_map.shape = {mask_score.rows, mask_score.cols};
  306. return true;
  307. }
  308. } // namespace PaddleX