Skip to content

Commit c918b08

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

File tree

1 file changed

+250
-0
lines changed

1 file changed

+250
-0
lines changed

modules/cudev/test/test_nd.cu

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

0 commit comments

Comments
 (0)