Skip to content

Commit e9cc229

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

File tree

1 file changed

+198
-0
lines changed

1 file changed

+198
-0
lines changed

modules/cudev/test/test_nd.cu

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

0 commit comments

Comments
 (0)