Skip to content

Commit a660d70

Browse files
committed
Test code - GpuMatND & Mat interoperability
1 parent 33ae078 commit a660d70

File tree

1 file changed

+247
-0
lines changed

1 file changed

+247
-0
lines changed

modules/cudev/test/test_nd.cu

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

0 commit comments

Comments
 (0)