gsd_InferPlugin.cc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /**
  2. *
  3. * gsd_InferPlugin.cc
  4. *
  5. */
  6. #include "gsd_InferPlugin.h"
  7. using namespace drogon;
  8. using namespace gsd;
  9. #define CLIP(x) x < 0 ? 0 : (x > 1 ? 1 : x)
  10. /**
  11. * @description: 初始化
  12. * @param {Value} &config
  13. * @return {*}
  14. */
  15. void InferPlugin::initAndStart(const Json::Value &config)
  16. {
  17. /// Initialize and start the plugin
  18. InfoL;
  19. if(m_InferTools == nullptr) m_InferTools = InferTools::getPtr();
  20. auto *plugin = app().getPlugin<CenterGroup>();
  21. if(m_InferTools->Init(plugin->getInferEngine()) != false) {
  22. InfoL << "初始化成功" << endl;
  23. }else{
  24. WarnL << "初始化失败" << endl;
  25. }
  26. if(this->pool == nullptr) this->pool = std::make_shared<ThreadPool>(5,ThreadPool::PRIORITY_HIGHEST, false);
  27. }
  28. /**
  29. * @description: 关闭
  30. * @return {*}
  31. */
  32. void InferPlugin::shutdown()
  33. {
  34. /// Shutdown the plugin
  35. InfoL;
  36. this->Destroy();
  37. }
  38. /**
  39. * @description: 启动任务
  40. * @return {*}
  41. */
  42. void InferPlugin::StartTask(){
  43. InfoL;
  44. }
  45. /**
  46. * @description: 创建任务
  47. * @param {HttpRequestPtr&} req
  48. * @return {*}
  49. */
  50. std::future<std::pair<bool, std::string>> InferPlugin::CreateTask(const drogon::HttpRequestPtr& req, InferPluginTaskType type){
  51. std::shared_ptr<std::packaged_task<std::pair<bool, std::string>()>> task = std::make_shared<std::packaged_task<std::pair<bool, std::string>()>>([&, req, type]{
  52. std::string images_base64 = req->getParameter("image");
  53. std::string datas = req->getParameter("datas");
  54. std::pair<bool, std::string> result(false, "");
  55. if(images_base64 == "" || datas == "") return result;
  56. std::string decode_str = base64_decode(images_base64);
  57. vector<uint8_t> img_data(decode_str.begin(), decode_str.end());
  58. std::shared_ptr<cv::Mat> img = std::make_shared<cv::Mat>();
  59. *img = cv::imdecode(cv::Mat(img_data), cv::IMREAD_COLOR);
  60. CNStreamInferData::Ptr data = std::make_shared<CNStreamInferData>();
  61. try
  62. {
  63. if(type == InferPluginTaskType::CHECKT_TASK){
  64. if(data->jsonToObject(datas)) {
  65. return this->CheckTask(img, data);
  66. }
  67. else return this->CheckTask(img);
  68. }else if(type == InferPluginTaskType::CLASSIFY_TASK){
  69. if(data->jsonToObject(datas)) {
  70. return this->CheckTask(img, data);
  71. }
  72. else return this->CheckTask(img);
  73. }
  74. }
  75. catch(const std::exception& e)
  76. {
  77. ErrorL << e.what() << endl;
  78. }
  79. });
  80. this->pool->async([task](){
  81. if(task->valid()){
  82. (*task)();
  83. }
  84. });
  85. this->pool->start();
  86. return task->get_future();
  87. }
  88. /**
  89. * @description: 推理任务
  90. * @param {Mat&} img
  91. * @param {CNStreamInferData&} data
  92. * @return {*}
  93. */
  94. std::pair<bool, std::string> InferPlugin::CheckTask(std::shared_ptr<cv::Mat> img, CNStreamInferData::Ptr data){
  95. CNStreamInferData::Ptr result = std::make_shared<CNStreamInferData>();
  96. this->m_InferTools->Inference(img, result);
  97. return this->getInfoResult(img, data, result);
  98. }
  99. /**
  100. * @description: 获取结果
  101. * @param {CNStreamInferData&} data1
  102. * @param {CNStreamInferData&} data2
  103. * @return {*}
  104. */
  105. std::pair<bool, std::string> InferPlugin::getInfoResult(std::shared_ptr<cv::Mat> img, CNStreamInferData::Ptr data1, CNStreamInferData::Ptr data2){
  106. static std::shared_ptr<ThreadPool> save_pool = nullptr;
  107. std::string json;
  108. data2->objectToJson(json);
  109. bool result;
  110. if(data2->Objects.size()) result = true;
  111. else result = false;
  112. std::pair<bool, std::string> dates(result, json);
  113. auto *plugin = app().getPlugin<CenterGroup>();
  114. // 判断是否保存结果
  115. if(plugin->getInferSave()){
  116. if(save_pool == nullptr) save_pool = std::make_shared<ThreadPool>(1,ThreadPool::PRIORITY_HIGHEST, false);
  117. save_pool->async([img, data1, data2](){
  118. auto *plugin = app().getPlugin<CenterGroup>();
  119. std::string dir = plugin->getSavePath();
  120. DIR *dirp = opendir(dir.c_str());
  121. if(dirp == NULL){
  122. mkdir(dir.c_str(),S_IRWXU | S_IRWXG | S_IRWXO);
  123. }else{
  124. closedir(dirp);
  125. }
  126. std::string video = dir + utility::uuid::generate() + ".jpg";
  127. cv::Mat result;
  128. img->copyTo(result);
  129. if(data1 != nullptr){
  130. // MLU220
  131. for(auto iter : data1->Objects){
  132. std::pair<cv::Point, cv::Point> corner = InferPlugin::GetBboxCorner(iter, img->cols, img->rows);
  133. cv::Point top_left = corner.first;
  134. cv::Point bottom_right = corner.second;
  135. cv::Point bottom_left(top_left.x, bottom_right.y);
  136. InferPlugin::DrawBox(*img, top_left, bottom_right, cv::Scalar(0,255,255));
  137. std::string text = iter.Label + " " + std::to_string(iter.Score);
  138. top_left.y = top_left.y - 2;
  139. cv::putText(*img, text, top_left, cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(0xFF, 0xFF, 0xFF), 2);
  140. }
  141. cv::putText(*img, "MLU220 " + data1->videoPath, cv::Point(0, 15), cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(0xFF, 0xFF, 0xFF), 2);
  142. }
  143. if(data2 != nullptr){
  144. // Jetson NX
  145. for(auto iter : data2->Objects){
  146. std::pair<cv::Point, cv::Point> corner = InferPlugin::GetBboxCorner(iter, img->cols, img->rows);
  147. cv::Point top_left = corner.first;
  148. cv::Point bottom_right = corner.second;
  149. cv::Point bottom_left(top_left.x, bottom_right.y);
  150. InferPlugin::DrawBox(result, top_left, bottom_right, cv::Scalar(255,255,0));
  151. std::string text = iter.Label + " " + std::to_string(iter.Score);
  152. top_left.y = top_left.y - 2;
  153. cv::putText(result, text, top_left, cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(0xFF, 0xFF, 0xFF), 2);
  154. }
  155. cv::putText(result, "Jetson NX", cv::Point(0, 15), cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(0xFF, 0xFF, 0xFF), 4);
  156. }
  157. cv::hconcat(*img, result, *img);
  158. //cv::resize(*img, *img, cv::Size(960, 540));
  159. cv::imwrite(video, *img);
  160. });
  161. save_pool->start();
  162. }
  163. return dates;
  164. }
  165. /**
  166. * @description: Destroy
  167. * @return {*}
  168. */
  169. void InferPlugin::Destroy(){
  170. m_InferTools->Destroy();
  171. }
  172. /**
  173. * @description: GetBboxCorner
  174. * @param {*}
  175. * @return {*}
  176. */
  177. std::pair<cv::Point, cv::Point> InferPlugin::GetBboxCorner(const InferInfo object, int img_width, int img_height) {
  178. float x = CLIP(object.BBox.x);
  179. float y = CLIP(object.BBox.y);
  180. float w = CLIP(object.BBox.w);
  181. float h = CLIP(object.BBox.h);
  182. w = (x + w > 1) ? (1 - x) : w;
  183. h = (y + h > 1) ? (1 - y) : h;
  184. cv::Point top_left(x * img_width, y * img_height);
  185. cv::Point bottom_right((x + w) * img_width, (y + h) * img_height);
  186. return std::make_pair(top_left, bottom_right);
  187. }
  188. /**
  189. * @description: CalcThickness
  190. * @param {int} image_width
  191. * @param {float} thickness
  192. * @return {*}
  193. */
  194. int InferPlugin::CalcThickness(int image_width, float thickness) {
  195. int result = thickness * image_width / 300;
  196. if (result <= 0) result = 1;
  197. return result;
  198. }
  199. /**
  200. * @description: DrawBox
  201. * @param {*}
  202. * @return {*}
  203. */
  204. void InferPlugin::DrawBox(cv::Mat& image, const cv::Point& top_left, const cv::Point& bottom_right,
  205. const cv::Scalar color) {
  206. float w =bottom_right.x - top_left.x;
  207. float h =bottom_right.y - top_left.y;
  208. float box_thickness_ = 1;
  209. int wscale = w * .25f;
  210. int hscale = h * .25f;
  211. cv::Point top_right(bottom_right.x,top_left.y);
  212. cv::Point bottom_left(top_left.x,bottom_right.y);
  213. // --
  214. cv::line(image,top_left,cv::Point(top_left.x + wscale,top_left.y),color, CalcThickness(image.cols, box_thickness_));
  215. // |
  216. cv::line(image,top_left,cv::Point(top_left.x ,top_left.y + hscale),color, CalcThickness(image.cols, box_thickness_));
  217. // --
  218. cv::line(image,cv::Point(top_right.x - wscale,top_right.y),top_right,color, CalcThickness(image.cols, box_thickness_));
  219. // |
  220. cv::line(image,top_right,cv::Point(top_right.x,top_right.y + hscale),color, CalcThickness(image.cols, box_thickness_));
  221. //
  222. // __
  223. cv::line(image,bottom_left,cv::Point(bottom_left.x+wscale,bottom_left.y),color, CalcThickness(image.cols, box_thickness_));
  224. //
  225. //|
  226. cv::line(image,bottom_left,cv::Point(bottom_left.x,bottom_left.y - hscale),color, CalcThickness(image.cols, box_thickness_));
  227. //
  228. // |
  229. cv::line(image,bottom_right,cv::Point(bottom_right.x,bottom_right.y - hscale),color, CalcThickness(image.cols, box_thickness_));
  230. cv::line(image,bottom_right,cv::Point(bottom_right.x - wscale,bottom_right.y),color, CalcThickness(image.cols, box_thickness_));
  231. // cv::rectangle(image, top_left, bottom_right, color, CalcThickness(image.cols, box_thickness_));
  232. }