sp_image.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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. cv::Mat sp_image::cv_mat(void *ptr) const {
  64. return cv::Mat(cv_size(), cv_type(), start_ptr(ptr), pitch());
  65. }
  66. cv::cuda::GpuMat sp_image::cv_gpu_mat(void *ptr) const {
  67. return cv::cuda::GpuMat(cv_size(), cv_type(), start_ptr(ptr), pitch());
  68. }
  69. sp_image sp_image::sub_view(const cv::Size size, const cv::Size start) const {
  70. auto ret = *this;
  71. *ret.array_base() = base_type::sub_view(
  72. to_index_pack(size), to_index_pack(start));
  73. return ret;
  74. }
  75. sp_image sp_image::create_impl(const cv::Size size, const size_t align,
  76. const std::type_index type) {
  77. const auto type_size = type_map.query(type).size;
  78. const auto pitch = alignment_round(size.width * type_size, align);
  79. auto ret = sp_image();
  80. *ret.array_base() = base_type::create(
  81. to_index_pack(size), pitch, type_size);
  82. ret.type = type;
  83. return ret;
  84. }
  85. sp_image sp_image::create_impl(const cv::Size size, const size_t align, int cv_type) {
  86. return create_impl(size, align, cv_map.query(cv_type).type);
  87. }
  88. sp_image sp_image::create_impl(const cv::Size size, const void *ptr,
  89. const std::type_index type) {
  90. auto ret = create_impl(size, 1, type);
  91. const auto write_helper = write_access_helper(ret.host());
  92. memcpy(ret.start_ptr(write_helper.ptr()), ptr, ret.byte_size());
  93. return ret;
  94. }
  95. sp_image sp_image::create_impl(const cv::Size size, const void *ptr, int cv_type) {
  96. return create_impl(size, ptr, cv_map.query(cv_type).type);
  97. }
  98. sp_image sp_image::cast_view_impl(const std::type_index type) const {
  99. auto ret = *this;
  100. const auto type_size = type_map.query(type).size;
  101. *ret.array_base() = base_type::cast_view(type_size);
  102. ret.type = type;
  103. return ret;
  104. }
  105. sp_image sp_image::cast_view(int cv_type) const {
  106. return cast_view_impl(cv_map.query(cv_type).type);
  107. }
  108. sp_image sp_image::create(const cv::Mat &mat) {
  109. assert(mat.size.dims() == image_rank);
  110. assert(mat.isContinuous());
  111. return create_impl(mat.size(), mat.data,
  112. cv_map.query(mat.type()).type);
  113. }
  114. sp_image sp_image::create_like(const sp_image &img, int cv_type) {
  115. if (cv_type == 0) {
  116. cv_type = img.cv_type();
  117. }
  118. return create(cv_type, img.cv_size());
  119. }
  120. sp_image sp_image::from_file(const std::string &path) {
  121. return create(cv::imread(path));
  122. }
  123. using image_ndarray_proxy = ndarray_proxy<image_rank>;
  124. using image_index_pack = index_pack<image_rank>;
  125. template<>
  126. void copy_ndarray(const image_ndarray_proxy &src, image_ndarray_proxy &dst, cudaMemcpyKind kind) {
  127. assert(src.shape_array() == dst.shape_array());
  128. assert(src.byte_width() == dst.byte_width());
  129. if (kind == cudaMemcpyDefault) { kind = determine_copy_kind(src, dst); }
  130. switch (kind) {
  131. #define TEMPLATE(src_loc, dst_loc) \
  132. auto access = pair_access_helper(src.src_loc(), dst.dst_loc()); \
  133. const auto src_ptr = src.start_ptr(access.read_ptr()); \
  134. const auto dst_ptr = dst.start_ptr(access.write_ptr()); \
  135. CUDA_API_CHECK(cudaMemcpy2DAsync( \
  136. dst_ptr, dst.pitch(), src_ptr, src.pitch(), \
  137. src.byte_width(), src.height(), kind, current_cuda_stream())); (void) 0
  138. //@formatter:off
  139. case cudaMemcpyDeviceToDevice: { TEMPLATE(cuda, cuda); break; }
  140. case cudaMemcpyDeviceToHost: { TEMPLATE(cuda, host); break; }
  141. case cudaMemcpyHostToDevice: { TEMPLATE(host, cuda); break; }
  142. case cudaMemcpyHostToHost: { TEMPLATE(host, host); break; }
  143. default: { assert(false); }
  144. //@formatter:on
  145. #undef TEMPLATE
  146. }
  147. }
  148. void copy_sp_image(const sp_image &src, sp_image &dst, const cudaMemcpyKind kind) {
  149. assert(src.type == dst.type);
  150. copy_ndarray(src, dst, kind);
  151. dst.merge_meta(src);
  152. }
  153. sp_image create_dense(const sp_image &src) {
  154. sp_image ret = src;
  155. *ret.array_base() = create_dense(*src.array_base());
  156. return ret;
  157. }
  158. image_mem_info to_mem_v1(const sp_image &img, void *ptr,
  159. const memory_location loc) {
  160. auto ret = image_mem_info();
  161. ret.ptr = std::shared_ptr<void>(
  162. img.start_ptr(ptr), [](void *) { (void) 0; });
  163. ret.loc = loc;
  164. ret.width = img.byte_width();
  165. ret.pitch = img.pitch();
  166. ret.height = img.height();
  167. return ret;
  168. }