test_nd.cu 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. #include "test_precomp.hpp"
  5. namespace opencv_test { namespace {
  6. template <typename ElemType>
  7. class GpuMatNDTest : public ::testing::Test
  8. {
  9. public:
  10. using MatType = Mat_<ElemType>;
  11. using CnType = typename Mat_<ElemType>::channel_type;
  12. static constexpr int cn = DataType<ElemType>::channels;
  13. using SizeArray = GpuMatND::SizeArray;
  14. static MatType RandomMat(const SizeArray& size)
  15. {
  16. const auto dims = static_cast<int>(size.size());
  17. MatType ret(dims, size.data());
  18. for (ElemType& elem : ret)
  19. for (int i = 0; i < cn; ++i)
  20. elem[i] = cv::randu<CnType>();
  21. return ret;
  22. }
  23. static std::vector<Range> RandomRange(const SizeArray& size)
  24. {
  25. const auto dims = static_cast<int>(size.size());
  26. std::vector<Range> ret;
  27. const auto margin = cv::randu<int>() & 0x1 + 1; // 1 or 2
  28. for (int s : size)
  29. if (s > margin * 2)
  30. ret.emplace_back(margin, s-margin);
  31. else
  32. ret.push_back(Range::all());
  33. if (dims == 1)
  34. {
  35. // Mat expects two ranges even in this case
  36. ret.push_back(Range::all());
  37. }
  38. return ret;
  39. }
  40. static std::vector<Range> RandomRange2D(const SizeArray& size)
  41. {
  42. const auto dims = static_cast<int>(size.size());
  43. std::vector<Range> ret = RandomRange(size);
  44. for (int i = 0; i < dims - 2; ++i)
  45. {
  46. const auto start = cv::randu<unsigned int>() % size[i];
  47. ret[i] = Range(static_cast<int>(start), static_cast<int>(start) + 1);
  48. }
  49. return ret;
  50. }
  51. static void doTest1(const SizeArray& size)
  52. {
  53. const MatType gold = RandomMat(size);
  54. MatType dst;
  55. GpuMatND gmat;
  56. // simple upload, download test for GpuMatND
  57. gmat.upload(gold);
  58. gmat.download(dst);
  59. EXPECT_TRUE(std::equal(gold.begin(), gold.end(), dst.begin()));
  60. }
  61. static void doTest2(const SizeArray& size)
  62. {
  63. const MatType gold = RandomMat(size);
  64. const std::vector<Range> ranges = RandomRange(size);
  65. const MatType goldSub = gold(ranges);
  66. MatType dst;
  67. GpuMatND gmat;
  68. // upload partial mat, download it, and compare
  69. gmat.upload(goldSub);
  70. gmat.download(dst);
  71. EXPECT_TRUE(std::equal(goldSub.begin(), goldSub.end(), dst.begin()));
  72. // upload full mat, extract partial mat from it, download it, and compare
  73. gmat.upload(gold);
  74. gmat = gmat(ranges);
  75. gmat.download(dst);
  76. EXPECT_TRUE(std::equal(goldSub.begin(), goldSub.end(), dst.begin()));
  77. }
  78. static void doTest3(const SizeArray& size)
  79. {
  80. if (std::is_same<CnType, float16_t>::value) // GpuMat::convertTo is not implemented for CV_16F
  81. return;
  82. const MatType gold = RandomMat(size);
  83. const std::vector<Range> ranges = RandomRange2D(size);
  84. MatType dst;
  85. GpuMatND gmat;
  86. // Test GpuMatND to GpuMat conversion:
  87. // extract a 2D-plane and set its elements in the extracted region to 1
  88. // compare the values of the full mat between Mat and GpuMatND
  89. gmat.upload(gold);
  90. GpuMat plane = gmat(ranges).createGpuMatHeader();
  91. EXPECT_TRUE(!plane.refcount); // plane points to externally allocated memory(a part of gmat)
  92. const GpuMat dummy = plane.clone();
  93. EXPECT_TRUE(dummy.refcount); // dummy is clone()-ed from plane, so it manages its memory
  94. // currently, plane(GpuMat) points to a sub-matrix of gmat(GpuMatND)
  95. // in this case, dummy and plane have same size and type,
  96. // so plane does not get reallocated inside convertTo,
  97. // so this convertTo sets a sub-matrix region of gmat to 1
  98. dummy.convertTo(plane, -1, 0, 1);
  99. EXPECT_TRUE(!plane.refcount); // plane still points to externally allocated memory(a part of gmat)
  100. gmat.download(dst);
  101. // set a sub-matrix region of gold to 1
  102. Mat plane_ = gold(ranges);
  103. const Mat dummy_ = plane_.clone();
  104. dummy_.convertTo(plane_, -1, 0, 1);
  105. EXPECT_TRUE(std::equal(gold.begin(), gold.end(), dst.begin()));
  106. }
  107. static void doTest4(const SizeArray& size)
  108. {
  109. if (std::is_same<CnType, float16_t>::value) // GpuMat::convertTo is not implemented for CV_16F
  110. return;
  111. const MatType gold = RandomMat(size);
  112. const std::vector<Range> ranges = RandomRange2D(size);
  113. MatType dst;
  114. GpuMatND gmat;
  115. // Test handling external memory
  116. gmat.upload(gold);
  117. const GpuMatND external(gmat.size, gmat.type(), gmat.getDevicePtr(), {gmat.step.begin(), gmat.step.end() - 1});
  118. // set a sub-matrix region of external to 2
  119. GpuMat plane = external(ranges).createGpuMatHeader();
  120. const GpuMat dummy = plane.clone();
  121. dummy.convertTo(plane, -1, 0, 2);
  122. external.download(dst);
  123. // set a sub-matrix region of gold to 2
  124. Mat plane_ = gold(ranges);
  125. const Mat dummy_ = plane_.clone();
  126. dummy_.convertTo(plane_, -1, 0, 2);
  127. EXPECT_TRUE(std::equal(gold.begin(), gold.end(), dst.begin()));
  128. }
  129. static void doTest5(const SizeArray& size)
  130. {
  131. if (std::is_same<CnType, float16_t>::value) // GpuMat::convertTo is not implemented for CV_16F
  132. return;
  133. const MatType gold = RandomMat(size);
  134. const std::vector<Range> ranges = RandomRange(size);
  135. MatType goldSub = gold(ranges);
  136. MatType dst;
  137. GpuMatND gmat;
  138. // Upload a sub-mat, set a sub-region of the sub-mat to 3, download, and compare
  139. gmat.upload(goldSub);
  140. const std::vector<Range> rangesInRanges = RandomRange2D(gmat.size);
  141. GpuMat plane = gmat(rangesInRanges).createGpuMatHeader();
  142. const GpuMat dummy = plane.clone();
  143. dummy.convertTo(plane, -1, 0, 3);
  144. gmat.download(dst);
  145. Mat plane_ = goldSub(rangesInRanges);
  146. const Mat dummy_ = plane_.clone();
  147. dummy_.convertTo(plane_, -1, 0, 3);
  148. EXPECT_TRUE(std::equal(goldSub.begin(), goldSub.end(), dst.begin()));
  149. }
  150. };
  151. using ElemTypes = ::testing::Types<
  152. Vec<uchar, 1>, Vec<uchar, 2>, Vec<uchar, 3>, Vec<uchar, 4>, // CV_8U
  153. Vec<schar, 1>, Vec<schar, 2>, Vec<schar, 3>, Vec<schar, 4>, // CV_8S
  154. Vec<ushort, 1>, Vec<ushort, 2>, Vec<ushort, 3>, Vec<ushort, 4>, // CV_16U
  155. Vec<short, 1>, Vec<short, 2>, Vec<short, 3>, Vec<short, 4>, // CV_16S
  156. Vec<int, 1>, Vec<int, 2>, Vec<int, 3>, Vec<int, 4>, // CV_32S
  157. Vec<float, 1>, Vec<float, 2>, Vec<float, 3>, Vec<float, 4>, // CV_32F
  158. Vec<double, 1>, Vec<double, 2>, Vec<double, 3>, Vec<double, 4>, //CV_64F
  159. Vec<float16_t, 1>, Vec<float16_t, 2>, Vec<float16_t, 3>, Vec<float16_t, 4> // CV_16F
  160. >;
  161. using SizeArray = GpuMatND::SizeArray;
  162. #define DIFFERENT_SIZES_ND std::vector<SizeArray>{ \
  163. SizeArray{2, 1}, SizeArray{3, 2, 1}, SizeArray{1, 3, 2, 1}, SizeArray{2, 1, 3, 2, 1}, SizeArray{3, 2, 1, 3, 2, 1}, \
  164. SizeArray{1}, SizeArray{1, 1}, SizeArray{1, 1, 1}, SizeArray{1, 1, 1, 1}, \
  165. SizeArray{4}, SizeArray{4, 4}, SizeArray{4, 4, 4}, SizeArray{4, 4, 4, 4}, \
  166. SizeArray{11}, SizeArray{13, 11}, SizeArray{17, 13, 11}, SizeArray{19, 17, 13, 11}}
  167. TYPED_TEST_CASE(GpuMatNDTest, ElemTypes);
  168. TYPED_TEST(GpuMatNDTest, Test1)
  169. {
  170. for (auto& size : DIFFERENT_SIZES_ND)
  171. GpuMatNDTest<TypeParam>::doTest1(size);
  172. }
  173. TYPED_TEST(GpuMatNDTest, Test2)
  174. {
  175. for (auto& size : DIFFERENT_SIZES_ND)
  176. GpuMatNDTest<TypeParam>::doTest2(size);
  177. }
  178. TYPED_TEST(GpuMatNDTest, Test3)
  179. {
  180. for (auto& size : DIFFERENT_SIZES_ND)
  181. GpuMatNDTest<TypeParam>::doTest3(size);
  182. }
  183. TYPED_TEST(GpuMatNDTest, Test4)
  184. {
  185. for (auto& size : DIFFERENT_SIZES_ND)
  186. GpuMatNDTest<TypeParam>::doTest4(size);
  187. }
  188. TYPED_TEST(GpuMatNDTest, Test5)
  189. {
  190. for (auto& size : DIFFERENT_SIZES_ND)
  191. GpuMatNDTest<TypeParam>::doTest5(size);
  192. }
  193. }} // namespace