mat.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. // Copyright (c) 2022 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 "ultra_infer/vision/common/processors/mat.h"
  15. #include "ultra_infer/utils/utils.h"
  16. #include "ultra_infer/vision/common/processors/utils.h"
  17. namespace ultra_infer {
  18. namespace vision {
  19. cv::Mat *Mat::GetOpenCVMat() {
  20. if (mat_type == ProcLib::OPENCV) {
  21. return &cpu_mat;
  22. } else if (mat_type == ProcLib::FLYCV) {
  23. #ifdef ENABLE_FLYCV
  24. // Just a reference to fcv_mat, zero copy. After you
  25. // call this method, cpu_mat and fcv_mat will point
  26. // to the same memory buffer.
  27. cpu_mat = ConvertFlyCVMatToOpenCV(fcv_mat);
  28. mat_type = ProcLib::OPENCV;
  29. return &cpu_mat;
  30. #else
  31. FDASSERT(false, "UltraInfer didn't compiled with FlyCV!");
  32. #endif
  33. } else if (mat_type == ProcLib::CUDA || mat_type == ProcLib::CVCUDA) {
  34. #ifdef WITH_GPU
  35. FDASSERT(cudaStreamSynchronize(stream) == cudaSuccess,
  36. "[ERROR] Error occurs while sync cuda stream.");
  37. cpu_mat = CreateZeroCopyOpenCVMatFromTensor(*fd_tensor, layout);
  38. mat_type = ProcLib::OPENCV;
  39. device = Device::CPU;
  40. return &cpu_mat;
  41. #else
  42. FDASSERT(false, "UltraInfer didn't compiled with -DWITH_GPU=ON");
  43. #endif
  44. } else {
  45. FDASSERT(false, "The mat_type of custom Mat can not be ProcLib::DEFAULT");
  46. }
  47. }
  48. #ifdef ENABLE_FLYCV
  49. fcv::Mat *Mat::GetFlyCVMat() {
  50. if (mat_type == ProcLib::FLYCV) {
  51. return &fcv_mat;
  52. } else if (mat_type == ProcLib::OPENCV) {
  53. // Just a reference to cpu_mat, zero copy. After you
  54. // call this method, fcv_mat and cpu_mat will point
  55. // to the same memory buffer.
  56. fcv_mat = ConvertOpenCVMatToFlyCV(cpu_mat);
  57. mat_type = ProcLib::FLYCV;
  58. return &fcv_mat;
  59. } else {
  60. FDASSERT(false, "The mat_type of custom Mat can not be ProcLib::DEFAULT");
  61. }
  62. }
  63. #endif
  64. void *Mat::Data() {
  65. if (mat_type == ProcLib::FLYCV) {
  66. #ifdef ENABLE_FLYCV
  67. return fcv_mat.data();
  68. #else
  69. FDASSERT(false,
  70. "UltraInfer didn't compile with FlyCV, but met data type with "
  71. "fcv::Mat.");
  72. #endif
  73. } else if (device == Device::GPU) {
  74. return fd_tensor->Data();
  75. }
  76. return cpu_mat.ptr();
  77. }
  78. FDTensor *Mat::Tensor() {
  79. if (mat_type == ProcLib::OPENCV) {
  80. ShareWithTensor(fd_tensor.get());
  81. } else if (mat_type == ProcLib::FLYCV) {
  82. #ifdef ENABLE_FLYCV
  83. cpu_mat = ConvertFlyCVMatToOpenCV(fcv_mat);
  84. mat_type = ProcLib::OPENCV;
  85. ShareWithTensor(fd_tensor.get());
  86. #else
  87. FDASSERT(false, "UltraInfer didn't compiled with FlyCV!");
  88. #endif
  89. }
  90. return fd_tensor.get();
  91. }
  92. void Mat::SetTensor(FDTensor *tensor) {
  93. fd_tensor->SetExternalData(tensor->Shape(), tensor->Dtype(), tensor->Data(),
  94. tensor->device, tensor->device_id);
  95. device = tensor->device;
  96. if (layout == Layout::HWC) {
  97. height = tensor->Shape()[0];
  98. width = tensor->Shape()[1];
  99. channels = tensor->Shape()[2];
  100. } else if (layout == Layout::CHW) {
  101. channels = tensor->Shape()[0];
  102. height = tensor->Shape()[1];
  103. width = tensor->Shape()[2];
  104. }
  105. }
  106. void Mat::SetTensor(std::shared_ptr<FDTensor> &tensor) {
  107. fd_tensor = tensor;
  108. device = tensor->device;
  109. if (layout == Layout::HWC) {
  110. height = tensor->Shape()[0];
  111. width = tensor->Shape()[1];
  112. channels = tensor->Shape()[2];
  113. } else if (layout == Layout::CHW) {
  114. channels = tensor->Shape()[0];
  115. height = tensor->Shape()[1];
  116. width = tensor->Shape()[2];
  117. }
  118. }
  119. void Mat::ShareWithTensor(FDTensor *tensor) {
  120. tensor->SetExternalData({Channels(), Height(), Width()}, Type(), Data());
  121. tensor->device = device;
  122. if (layout == Layout::HWC) {
  123. tensor->shape = {Height(), Width(), Channels()};
  124. }
  125. }
  126. bool Mat::CopyToTensor(FDTensor *tensor) {
  127. int total_bytes = Height() * Width() * Channels() * FDDataTypeSize(Type());
  128. if (total_bytes != tensor->Nbytes()) {
  129. FDERROR << "While copy Mat to Tensor, requires the memory size be same, "
  130. "but now size of Tensor = "
  131. << tensor->Nbytes() << ", size of Mat = " << total_bytes << "."
  132. << std::endl;
  133. return false;
  134. }
  135. memcpy(tensor->MutableData(), Data(), total_bytes);
  136. return true;
  137. }
  138. void Mat::PrintInfo(const std::string &flag) {
  139. std::cout << flag << ": "
  140. << "DataType=" << Type() << ", "
  141. << "Channel=" << Channels() << ", "
  142. << "Height=" << Height() << ", "
  143. << "Width=" << Width() << ", "
  144. << "Mean=";
  145. if (mat_type == ProcLib::FLYCV) {
  146. #ifdef ENABLE_FLYCV
  147. fcv::Scalar mean = fcv::mean(fcv_mat);
  148. for (int i = 0; i < Channels(); ++i) {
  149. std::cout << mean[i] << " ";
  150. }
  151. std::cout << std::endl;
  152. #else
  153. FDASSERT(false,
  154. "UltraInfer didn't compile with FlyCV, but met data type with "
  155. "fcv::Mat.");
  156. #endif
  157. } else if (mat_type == ProcLib::OPENCV) {
  158. cv::Scalar mean = cv::mean(cpu_mat);
  159. for (int i = 0; i < Channels(); ++i) {
  160. std::cout << mean[i] << " ";
  161. }
  162. std::cout << std::endl;
  163. } else if (mat_type == ProcLib::CUDA || mat_type == ProcLib::CVCUDA) {
  164. #ifdef WITH_GPU
  165. FDASSERT(cudaStreamSynchronize(stream) == cudaSuccess,
  166. "[ERROR] Error occurs while sync cuda stream.");
  167. cv::Mat tmp_mat = CreateZeroCopyOpenCVMatFromTensor(*fd_tensor, layout);
  168. cv::Scalar mean = cv::mean(tmp_mat);
  169. for (int i = 0; i < Channels(); ++i) {
  170. std::cout << mean[i] << " ";
  171. }
  172. std::cout << std::endl;
  173. #else
  174. FDASSERT(false, "UltraInfer didn't compiled with -DWITH_GPU=ON");
  175. #endif
  176. }
  177. }
  178. FDDataType Mat::Type() {
  179. int type = -1;
  180. if (mat_type == ProcLib::FLYCV) {
  181. #ifdef ENABLE_FLYCV
  182. return FlyCVDataTypeToFD(fcv_mat.type());
  183. #else
  184. FDASSERT(false,
  185. "UltraInfer didn't compile with FlyCV, but met data type with "
  186. "fcv::Mat.");
  187. #endif
  188. } else if (mat_type == ProcLib::CUDA || mat_type == ProcLib::CVCUDA) {
  189. return fd_tensor->Dtype();
  190. }
  191. return OpenCVDataTypeToFD(cpu_mat.type());
  192. }
  193. Mat Mat::Create(const FDTensor &tensor) {
  194. if (DefaultProcLib::default_lib == ProcLib::FLYCV) {
  195. #ifdef ENABLE_FLYCV
  196. fcv::Mat tmp_fcv_mat = CreateZeroCopyFlyCVMatFromTensor(tensor);
  197. Mat mat = Mat(tmp_fcv_mat);
  198. return mat;
  199. #else
  200. FDASSERT(false, "UltraInfer didn't compiled with FlyCV!");
  201. #endif
  202. }
  203. cv::Mat tmp_ocv_mat = CreateZeroCopyOpenCVMatFromTensor(tensor);
  204. Mat mat = Mat(tmp_ocv_mat);
  205. return mat;
  206. }
  207. Mat Mat::Create(const FDTensor &tensor, ProcLib lib) {
  208. if (lib == ProcLib::DEFAULT) {
  209. return Create(tensor);
  210. }
  211. if (lib == ProcLib::FLYCV) {
  212. #ifdef ENABLE_FLYCV
  213. fcv::Mat tmp_fcv_mat = CreateZeroCopyFlyCVMatFromTensor(tensor);
  214. Mat mat = Mat(tmp_fcv_mat);
  215. return mat;
  216. #else
  217. FDASSERT(false, "UltraInfer didn't compiled with FlyCV!");
  218. #endif
  219. }
  220. cv::Mat tmp_ocv_mat = CreateZeroCopyOpenCVMatFromTensor(tensor);
  221. Mat mat = Mat(tmp_ocv_mat);
  222. return mat;
  223. }
  224. Mat Mat::Create(int height, int width, int channels, FDDataType type,
  225. void *data) {
  226. if (DefaultProcLib::default_lib == ProcLib::FLYCV) {
  227. #ifdef ENABLE_FLYCV
  228. fcv::Mat tmp_fcv_mat =
  229. CreateZeroCopyFlyCVMatFromBuffer(height, width, channels, type, data);
  230. Mat mat = Mat(tmp_fcv_mat);
  231. return mat;
  232. #else
  233. FDASSERT(false, "UltraInfer didn't compiled with FlyCV!");
  234. #endif
  235. }
  236. cv::Mat tmp_ocv_mat =
  237. CreateZeroCopyOpenCVMatFromBuffer(height, width, channels, type, data);
  238. Mat mat = Mat(tmp_ocv_mat);
  239. return mat;
  240. }
  241. Mat Mat::Create(int height, int width, int channels, FDDataType type,
  242. void *data, ProcLib lib) {
  243. if (lib == ProcLib::DEFAULT) {
  244. return Create(height, width, channels, type, data);
  245. }
  246. if (lib == ProcLib::FLYCV) {
  247. #ifdef ENABLE_FLYCV
  248. fcv::Mat tmp_fcv_mat =
  249. CreateZeroCopyFlyCVMatFromBuffer(height, width, channels, type, data);
  250. Mat mat = Mat(tmp_fcv_mat);
  251. return mat;
  252. #else
  253. FDASSERT(false, "UltraInfer didn't compiled with FlyCV!");
  254. #endif
  255. }
  256. cv::Mat tmp_ocv_mat =
  257. CreateZeroCopyOpenCVMatFromBuffer(height, width, channels, type, data);
  258. Mat mat = Mat(tmp_ocv_mat);
  259. return mat;
  260. }
  261. FDMat WrapMat(const cv::Mat &image) {
  262. FDMat mat(image);
  263. return mat;
  264. }
  265. std::vector<FDMat> WrapMat(const std::vector<cv::Mat> &images) {
  266. std::vector<FDMat> mats;
  267. for (size_t i = 0; i < images.size(); ++i) {
  268. mats.emplace_back(FDMat(images[i]));
  269. }
  270. return mats;
  271. }
  272. bool CheckShapeConsistency(std::vector<Mat> *mats) {
  273. if (mats == nullptr) {
  274. return true;
  275. }
  276. for (size_t i = 1; i < mats->size(); ++i) {
  277. if ((*mats)[i].Channels() != (*mats)[0].Channels() ||
  278. (*mats)[i].Width() != (*mats)[0].Width() ||
  279. (*mats)[i].Height() != (*mats)[0].Height()) {
  280. return false;
  281. }
  282. }
  283. return true;
  284. }
  285. FDTensor *CreateCachedGpuInputTensor(Mat *mat) {
  286. #ifdef WITH_GPU
  287. FDTensor *src = mat->Tensor();
  288. // Need to make sure the tensor is pointed to the input_cache.
  289. if (src->Data() == mat->output_cache->Data()) {
  290. std::swap(mat->input_cache, mat->output_cache);
  291. std::swap(mat->input_cache->name, mat->output_cache->name);
  292. }
  293. if (src->device == Device::GPU) {
  294. return src;
  295. } else if (src->device == Device::CPU) {
  296. // Tensor on CPU, we need copy it from CPU to GPU
  297. FDASSERT(src->Shape().size() == 3, "The CPU tensor must has 3 dims.")
  298. mat->output_cache->Resize(src->Shape(), src->Dtype(), "output_cache",
  299. Device::GPU);
  300. FDASSERT(cudaMemcpyAsync(mat->output_cache->Data(), src->Data(),
  301. src->Nbytes(), cudaMemcpyHostToDevice,
  302. mat->Stream()) == 0,
  303. "[ERROR] Error occurs while copy memory from CPU to GPU.");
  304. std::swap(mat->input_cache, mat->output_cache);
  305. std::swap(mat->input_cache->name, mat->output_cache->name);
  306. return mat->input_cache;
  307. } else {
  308. FDASSERT(false, "FDMat is on unsupported device: %d", src->device);
  309. }
  310. #else
  311. FDASSERT(false, "UltraInfer didn't compile with WITH_GPU.");
  312. #endif
  313. return nullptr;
  314. }
  315. } // namespace vision
  316. } // namespace ultra_infer