sp_image.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #include "sp_image.h"
  2. #include "core/math_helper.hpp"
  3. #include "third_party/static_block.hpp"
  4. #include <opencv2/imgcodecs.hpp>
  5. #include <unordered_map>
  6. namespace {
  7. struct type_info {
  8. size_t size = {};
  9. int cv_type = {};
  10. };
  11. struct cv_info {
  12. size_t size = {};
  13. std::type_index type = typeid(void);
  14. template<typename T>
  15. static cv_info create() {
  16. return {sizeof(T), typeid(T)};
  17. }
  18. };
  19. template<typename Key, typename Value>
  20. struct map_proxy : std::unordered_map<Key, Value> {
  21. template<typename T>
  22. auto query(T &&key) const {
  23. const auto iter = this->find(key);
  24. assert(iter != this->end());
  25. return iter->second;
  26. }
  27. };
  28. using type_map_type = map_proxy<std::type_index, type_info>;
  29. type_map_type type_map;
  30. static_block {
  31. type_map[typeid(uchar1)] = {sizeof(uchar1), CV_8UC1};
  32. type_map[typeid(uchar2)] = {sizeof(uchar2), CV_8UC2};
  33. type_map[typeid(uchar3)] = {sizeof(uchar3), CV_8UC3};
  34. type_map[typeid(uchar4)] = {sizeof(uchar4), CV_8UC4};
  35. type_map[typeid(ushort1)] = {sizeof(ushort1), CV_16UC1};
  36. type_map[typeid(float1)] = {sizeof(float1), CV_32FC1};
  37. type_map[typeid(float2)] = {sizeof(float2), CV_32FC2};
  38. }
  39. using cv_map_type = map_proxy<int, cv_info>;
  40. cv_map_type cv_map;
  41. static_block {
  42. cv_map[CV_8UC1] = cv_info::create<uchar1>();
  43. cv_map[CV_8UC2] = cv_info::create<uchar2>();
  44. cv_map[CV_8UC3] = cv_info::create<uchar3>();
  45. cv_map[CV_8UC4] = cv_info::create<uchar4>();
  46. cv_map[CV_16UC1] = cv_info::create<ushort1>();
  47. cv_map[CV_32FC1] = cv_info::create<float1>();
  48. cv_map[CV_32FC2] = cv_info::create<float2>();
  49. }
  50. auto to_index_pack(const cv::Size size) {
  51. auto ret = index_pack<image_rank>();
  52. ret[0] = size.width;
  53. ret[1] = size.height;
  54. return ret;
  55. }
  56. }
  57. cv::Size sp_image::cv_size() const {
  58. return cv::Size(width(), height());
  59. }
  60. int sp_image::cv_type() const {
  61. return type_map.query(type).cv_type;
  62. }
  63. int sp_image::channels() const {
  64. return CV_MAT_CN(cv_type());
  65. }
  66. cv::Mat sp_image::cv_mat(void *ptr) const {
  67. return cv::Mat(cv_size(), cv_type(), start_ptr(ptr), pitch());
  68. }
  69. cv::cuda::GpuMat sp_image::cv_gpu_mat(void *ptr) const {
  70. return cv::cuda::GpuMat(cv_size(), cv_type(), start_ptr(ptr), pitch());
  71. }
  72. sp_image sp_image::sub_view(const cv::Size size, const cv::Size start) const {
  73. auto ret = *this;
  74. *ret.array_base() = base_type::sub_view(
  75. to_index_pack(size), to_index_pack(start));
  76. return ret;
  77. }
  78. sp_image sp_image::create_impl(const cv::Size size, const size_t align,
  79. const std::type_index type) {
  80. const auto type_size = type_map.query(type).size;
  81. const auto pitch = alignment_round(size.width * type_size, align);
  82. auto ret = sp_image();
  83. *ret.array_base() = base_type::create(
  84. to_index_pack(size), pitch, type_size);
  85. ret.type = type;
  86. return ret;
  87. }
  88. sp_image sp_image::create_impl(const cv::Size size, const size_t align, int cv_type) {
  89. return create_impl(size, align, cv_map.query(cv_type).type);
  90. }
  91. sp_image sp_image::create_impl(const cv::Size size, const void *ptr,
  92. const std::type_index type) {
  93. auto ret = create_impl(size, 1, type);
  94. const auto write_helper = write_access_helper(ret.host());
  95. memcpy(ret.start_ptr(write_helper.ptr()), ptr, ret.byte_size());
  96. return ret;
  97. }
  98. sp_image sp_image::create_impl(const cv::Size size, const void *ptr, int cv_type) {
  99. return create_impl(size, ptr, cv_map.query(cv_type).type);
  100. }
  101. sp_image sp_image::cast_view_impl(const std::type_index type) const {
  102. auto ret = *this;
  103. const auto type_size = type_map.query(type).size;
  104. *ret.array_base() = base_type::cast_view(type_size);
  105. ret.type = type;
  106. return ret;
  107. }
  108. sp_image sp_image::cast_view(int cv_type) const {
  109. return cast_view_impl(cv_map.query(cv_type).type);
  110. }
  111. sp_image sp_image::create(const cv::Mat &mat) {
  112. assert(mat.size.dims() == image_rank);
  113. assert(mat.isContinuous());
  114. return create_impl(mat.size(), mat.data,
  115. cv_map.query(mat.type()).type);
  116. }
  117. sp_image sp_image::create_like(const sp_image &img, int cv_type) {
  118. if (cv_type == 0) {
  119. cv_type = img.cv_type();
  120. }
  121. return create(cv_type, img.cv_size());
  122. }
  123. sp_image sp_image::from_file(const std::string &path) {
  124. return create(cv::imread(path));
  125. }
  126. using image_ndarray_proxy = ndarray_proxy<image_rank>;
  127. using image_index_pack = index_pack<image_rank>;
  128. template<>
  129. void copy_ndarray(const image_ndarray_proxy &src, image_ndarray_proxy &dst, cudaMemcpyKind kind) {
  130. assert(src.shape_array() == dst.shape_array());
  131. assert(src.byte_width() == dst.byte_width());
  132. if (kind == cudaMemcpyDefault) { kind = determine_copy_kind(src, dst); }
  133. switch (kind) {
  134. #define TEMPLATE(src_loc, dst_loc) \
  135. auto access = pair_access_helper(src.src_loc(), dst.dst_loc()); \
  136. const auto src_ptr = src.start_ptr(access.read_ptr()); \
  137. const auto dst_ptr = dst.start_ptr(access.write_ptr()); \
  138. CUDA_API_CHECK(cudaMemcpy2DAsync( \
  139. dst_ptr, dst.pitch(), src_ptr, src.pitch(), \
  140. src.byte_width(), src.height(), kind, current_cuda_stream())); (void) 0
  141. //@formatter:off
  142. case cudaMemcpyDeviceToDevice: { TEMPLATE(cuda, cuda); break; }
  143. case cudaMemcpyDeviceToHost: { TEMPLATE(cuda, host); break; }
  144. case cudaMemcpyHostToDevice: { TEMPLATE(host, cuda); break; }
  145. case cudaMemcpyHostToHost: { TEMPLATE(host, host); break; }
  146. default: { assert(false); }
  147. //@formatter:on
  148. #undef TEMPLATE
  149. }
  150. }
  151. void copy_sp_image(const sp_image &src, sp_image &dst, const cudaMemcpyKind kind) {
  152. assert(src.type == dst.type);
  153. copy_ndarray(src, dst, kind);
  154. dst.merge_meta(src);
  155. }
  156. sp_image create_dense(const sp_image &src) {
  157. sp_image ret = src;
  158. *ret.array_base() = create_dense(*src.array_base());
  159. return ret;
  160. }
  161. image_mem_info to_mem_v1(const sp_image &img, void *ptr,
  162. const memory_location loc) {
  163. auto ret = image_mem_info();
  164. ret.ptr = std::shared_ptr<void>(
  165. img.start_ptr(ptr), [](void *) { (void) 0; });
  166. ret.loc = loc;
  167. ret.width = img.byte_width();
  168. ret.pitch = img.pitch();
  169. ret.height = img.height();
  170. return ret;
  171. }