Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp
16344 views
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
//
5
// Copyright (C) 2018 Intel Corporation
6
7
8
#include "test_precomp.hpp"
9
10
#include <ade/util/zip_range.hpp> // util::indexed
11
12
#include "opencv2/gapi/gkernel.hpp"
13
#include "compiler/gmodelbuilder.hpp"
14
#include "compiler/gmodel.hpp" // RcDesc, GModel::init
15
16
namespace opencv_test
17
{
18
19
namespace test
20
{
21
22
namespace
23
{
24
cv::GMat unaryOp(cv::GMat m)
25
{
26
return cv::GCall(cv::GKernel{"gapi.test.unaryop", nullptr, { GShape::GMAT } }).pass(m).yield(0);
27
}
28
29
cv::GMat binaryOp(cv::GMat m1, cv::GMat m2)
30
{
31
return cv::GCall(cv::GKernel{"gapi.test.binaryOp", nullptr, { GShape::GMAT } }).pass(m1, m2).yield(0);
32
}
33
34
std::vector<ade::NodeHandle> collectOperations(const cv::gimpl::GModel::Graph& gr)
35
{
36
std::vector<ade::NodeHandle> ops;
37
for (const auto& nh : gr.nodes())
38
{
39
if (gr.metadata(nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP)
40
ops.push_back(nh);
41
}
42
return ops;
43
}
44
45
ade::NodeHandle inputOf(cv::gimpl::GModel::Graph& gm, ade::NodeHandle nh, std::size_t port)
46
{
47
for (const auto& eh : nh->inEdges())
48
{
49
if (gm.metadata(eh).get<cv::gimpl::Input>().port == port)
50
{
51
return eh->srcNode();
52
}
53
}
54
util::throw_error(std::logic_error("port " + std::to_string(port) + " not found"));
55
}
56
}
57
}// namespace opencv_test::test
58
59
TEST(GModelBuilder, Unroll_TestUnary)
60
{
61
cv::GMat in;
62
cv::GMat out = test::unaryOp(in);
63
64
auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args);
65
66
EXPECT_EQ(1u, unrolled.all_ops.size()); // There is one operation
67
EXPECT_EQ(2u, unrolled.all_data.size()); // And two data objects (in, out)
68
69
// TODO check what the operation is, and so on, and so on
70
}
71
72
TEST(GModelBuilder, Unroll_TestUnaryOfUnary)
73
{
74
cv::GMat in;
75
cv::GMat out = test::unaryOp(test::unaryOp(in));
76
77
auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args);
78
79
EXPECT_EQ(2u, unrolled.all_ops.size()); // There're two operations
80
EXPECT_EQ(3u, unrolled.all_data.size()); // And three data objects (in, out)
81
82
// TODO check what the operation is, and so on, and so on
83
}
84
85
TEST(GModelBuilder, Unroll_Not_All_Protocol_Inputs_Are_Reached)
86
{
87
cv::GMat in1, in2; // in1 -> unaryOp() -> u_op1 -> unaryOp() -> out
88
auto u_op1 = test::unaryOp(in1); // in2 -> unaryOp() -> u_op2
89
auto u_op2 = test::unaryOp(in2);
90
auto out = test::unaryOp(u_op1);
91
92
EXPECT_THROW(cv::gimpl::unrollExpr(cv::GIn(in1, in2).m_args, cv::GOut(out).m_args), std::logic_error);
93
}
94
95
TEST(GModelBuilder, Unroll_Parallel_Path)
96
{
97
cv::GMat in1, in2; // in1 -> unaryOp() -> out1
98
auto out1 = test::unaryOp(in1); // in2 -> unaryOp() -> out2
99
auto out2 = test::unaryOp(in2);
100
101
auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in1, in2).m_args, cv::GOut(out1, out2).m_args);
102
103
EXPECT_EQ(unrolled.all_ops.size(), 2u);
104
EXPECT_EQ(unrolled.all_data.size(), 4u);
105
}
106
107
TEST(GModelBuilder, Unroll_WithBranch)
108
{
109
// in -> unaryOp() -> tmp -->unaryOp() -> out1
110
// `---->unaryOp() -> out2
111
112
GMat in;
113
auto tmp = test::unaryOp(in);
114
auto out1 = test::unaryOp(tmp);
115
auto out2 = test::unaryOp(tmp);
116
117
auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out1, out2).m_args);
118
119
EXPECT_EQ(unrolled.all_ops.size(), 3u);
120
EXPECT_EQ(unrolled.all_data.size(), 4u);
121
}
122
123
TEST(GModelBuilder, Build_Unary)
124
{
125
cv::GMat in;
126
cv::GMat out = test::unaryOp(in);
127
128
ade::Graph g;
129
cv::gimpl::GModel::Graph gm(g);
130
cv::gimpl::GModel::init(gm);
131
cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out).m_args);
132
133
EXPECT_EQ(3u, static_cast<std::size_t>(g.nodes().size())); // Generated graph should have three nodes
134
135
// TODO: Check what the nodes are
136
}
137
138
TEST(GModelBuilder, Constant_GScalar)
139
{
140
// in -> addC()-----(GMat)---->mulC()-----(GMat)---->unaryOp()----out
141
// ^ ^
142
// | |
143
// 3-------` c_s-------'
144
145
cv::GMat in;
146
cv::GScalar c_s = 5;
147
auto out = test::unaryOp((in + 3) * c_s); // 3 converted to GScalar
148
149
ade::Graph g;
150
cv::gimpl::GModel::Graph gm(g);
151
cv::gimpl::GModel::init(gm);
152
auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out).m_args);
153
cv::gimpl::Protocol p;
154
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
155
156
auto in_nh = p.in_nhs.front();
157
auto addC_nh = in_nh->outNodes().front();
158
auto mulC_nh = addC_nh->outNodes().front()->outNodes().front();
159
160
ASSERT_TRUE(gm.metadata(addC_nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP);
161
ASSERT_TRUE(gm.metadata(mulC_nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP);
162
163
auto s_3 = test::inputOf(gm, addC_nh, 1);
164
auto s_5 = test::inputOf(gm, mulC_nh, 1);
165
166
EXPECT_EQ(9u, static_cast<std::size_t>(g.nodes().size())); // 6 data nodes (1 -input, 1 output, 2 constant, 2 temp) and 3 op nodes
167
EXPECT_EQ(2u, static_cast<std::size_t>(addC_nh->inNodes().size())); // in and 3
168
EXPECT_EQ(2u, static_cast<std::size_t>(mulC_nh->inNodes().size())); // addC output and c_s
169
EXPECT_EQ(3, (util::get<cv::gapi::own::Scalar>(gm.metadata(s_3).get<cv::gimpl::ConstValue>().arg))[0]);
170
EXPECT_EQ(5, (util::get<cv::gapi::own::Scalar>(gm.metadata(s_5).get<cv::gimpl::ConstValue>().arg))[0]);
171
}
172
173
TEST(GModelBuilder, Check_Multiple_Outputs)
174
{
175
// ------------------------------> r
176
// '
177
// ' -----------> i_out1
178
// ' '
179
// in ----> split3() ---> g ---> integral()
180
// ' '
181
// ' -----------> i_out2
182
// '
183
// '---------> b ---> unaryOp() ---> u_out
184
185
cv::GMat in, r, g, b, i_out1, i_out2, u_out;
186
std::tie(r, g, b) = cv::gapi::split3(in);
187
std::tie(i_out1, i_out2) = cv::gapi::integral(g, 1, 1);
188
u_out = test::unaryOp(b);
189
190
ade::Graph gr;
191
cv::gimpl::GModel::Graph gm(gr);
192
cv::gimpl::GModel::init(gm);
193
auto proto_slots = cv::gimpl::GModelBuilder(gr).put(cv::GIn(in).m_args, cv::GOut(r, i_out1, i_out2, u_out).m_args);
194
cv::gimpl::Protocol p;
195
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
196
197
EXPECT_EQ(4u, static_cast<std::size_t>(p.out_nhs.size()));
198
EXPECT_EQ(0u, gm.metadata(p.out_nhs[0]->inEdges().front()).get<cv::gimpl::Output>().port);
199
EXPECT_EQ(0u, gm.metadata(p.out_nhs[1]->inEdges().front()).get<cv::gimpl::Output>().port);
200
EXPECT_EQ(1u, gm.metadata(p.out_nhs[2]->inEdges().front()).get<cv::gimpl::Output>().port);
201
EXPECT_EQ(0u, gm.metadata(p.out_nhs[3]->inEdges().front()).get<cv::gimpl::Output>().port);
202
for (const auto& it : ade::util::indexed(p.out_nhs))
203
{
204
const auto& out_nh = ade::util::value(it);
205
206
EXPECT_EQ(cv::gimpl::NodeType::DATA, gm.metadata(out_nh).get<cv::gimpl::NodeType>().t);
207
EXPECT_EQ(GShape::GMAT, gm.metadata(out_nh).get<cv::gimpl::Data>().shape);
208
}
209
}
210
211
TEST(GModelBuilder, Unused_Outputs)
212
{
213
cv::GMat in;
214
auto yuv_p = cv::gapi::split3(in);
215
216
ade::Graph g;
217
cv::gimpl::GModel::Graph gm(g);
218
cv::gimpl::GModel::init(gm);
219
cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(std::get<0>(yuv_p)).m_args);
220
221
EXPECT_EQ(5u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 1 operation, 3 outputs
222
}
223
224
TEST(GModelBuilder, Work_With_One_Channel_From_Split3)
225
{
226
cv::GMat in, y, u, v;
227
std::tie(y, u, v) = cv::gapi::split3(in);
228
auto y_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
229
230
ade::Graph g;
231
cv::gimpl::GModel::Graph gm(g);
232
cv::gimpl::GModel::init(gm);
233
cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(y_blur).m_args);
234
235
EXPECT_EQ(7u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 2 operation, 3 nodes from split3, 1 output
236
}
237
238
TEST(GModelBuilder, Add_Nodes_To_Unused_Nodes)
239
{
240
cv::GMat in, y, u, v;
241
std::tie(y, u, v) = cv::gapi::split3(in);
242
auto y_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
243
// unused nodes
244
auto u_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
245
auto v_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
246
247
ade::Graph g;
248
cv::gimpl::GModel::Graph gm(g);
249
cv::gimpl::GModel::init(gm);
250
cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(y_blur).m_args);
251
252
EXPECT_EQ(7u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 2 operation, 3 nodes from split3, 1 output
253
}
254
255
TEST(GModelBuilder, Unlisted_Inputs)
256
{
257
// in1 -> binaryOp() -> out
258
// ^
259
// |
260
// in2 ----'
261
262
cv::GMat in1, in2;
263
auto out = test::binaryOp(in1, in2);
264
265
ade::Graph g;
266
cv::gimpl::GModel::Graph gm(g);
267
cv::gimpl::GModel::init(gm);
268
// add required 2 inputs but pass 1
269
EXPECT_THROW(cv::gimpl::GModelBuilder(g).put(cv::GIn(in1).m_args, cv::GOut(out).m_args), std::logic_error);
270
}
271
272
TEST(GModelBuilder, Unroll_No_Link_Between_In_And_Out)
273
{
274
// in -> unaryOp() -> u_op
275
// other -> unaryOp() -> out
276
277
cv::GMat in, other;
278
auto u_op = test::unaryOp(in);
279
auto out = test::unaryOp(other);
280
281
EXPECT_THROW(cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args), std::logic_error);
282
}
283
284
285
TEST(GModel_builder, Check_Binary_Op)
286
{
287
// in1 -> binaryOp() -> out
288
// ^
289
// |
290
// in2 -----'
291
292
cv::GMat in1, in2;
293
auto out = test::binaryOp(in1, in2);
294
295
ade::Graph g;
296
cv::gimpl::GModel::Graph gm(g);
297
cv::gimpl::GModel::init(gm);
298
auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in1, in2).m_args, cv::GOut(out).m_args);
299
300
cv::gimpl::Protocol p;
301
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
302
auto ops = test::collectOperations(g);
303
304
EXPECT_EQ(1u, ops.size());
305
EXPECT_EQ("gapi.test.binaryOp", gm.metadata(ops.front()).get<cv::gimpl::Op>().k.name);
306
EXPECT_EQ(2u, static_cast<std::size_t>(ops.front()->inEdges().size()));
307
EXPECT_EQ(1u, static_cast<std::size_t>(ops.front()->outEdges().size()));
308
EXPECT_EQ(1u, static_cast<std::size_t>(ops.front()->outNodes().size()));
309
}
310
311
TEST(GModelBuilder, Add_Operation_With_Two_Out_One_Time)
312
{
313
// in -> integral() --> out_b1 -> unaryOp() -> out1
314
// |
315
// '-------> out_b2 -> unaryOp() -> out2
316
317
cv::GMat in, out_b1, out_b2;
318
std::tie(out_b1, out_b2) = cv::gapi::integral(in, 1, 1);
319
auto out1 = test::unaryOp(out_b1);
320
auto out2 = test::unaryOp(out_b1);
321
322
ade::Graph g;
323
cv::gimpl::GModel::Graph gm(g);
324
cv::gimpl::GModel::init(gm);
325
auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out1, out2).m_args);
326
327
auto ops = test::collectOperations(gm);
328
329
cv::gimpl::Protocol p;
330
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
331
auto integral_nh = p.in_nhs.front()->outNodes().front();
332
333
EXPECT_EQ(3u, ops.size());
334
EXPECT_EQ("org.opencv.core.matrixop.integral", gm.metadata(integral_nh).get<cv::gimpl::Op>().k.name);
335
EXPECT_EQ(1u, static_cast<std::size_t>(integral_nh->inEdges().size()));
336
EXPECT_EQ(2u, static_cast<std::size_t>(integral_nh->outEdges().size()));
337
EXPECT_EQ(2u, static_cast<std::size_t>(integral_nh->outNodes().size()));
338
}
339
TEST(GModelBuilder, Add_Operation_With_One_Out_One_Time)
340
{
341
// in1 -> binaryOp() -> b_out -> unaryOp() -> out1
342
// ^ |
343
// | |
344
// in2 ------- '----> unaryOp() -> out2
345
346
cv::GMat in1, in2;
347
auto b_out = test::binaryOp(in1, in2);
348
auto out1 = test::unaryOp(b_out);
349
auto out2 = test::unaryOp(b_out);
350
351
ade::Graph g;
352
cv::gimpl::GModel::Graph gm(g);
353
cv::gimpl::GModel::init(gm);
354
auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in1, in2).m_args, cv::GOut(out1, out2).m_args);
355
cv::gimpl::Protocol p;
356
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
357
cv::gimpl::GModel::Graph gr(g);
358
auto binaryOp_nh = p.in_nhs.front()->outNodes().front();
359
360
EXPECT_EQ(2u, static_cast<std::size_t>(binaryOp_nh->inEdges().size()));
361
EXPECT_EQ(1u, static_cast<std::size_t>(binaryOp_nh->outEdges().size()));
362
EXPECT_EQ(8u, static_cast<std::size_t>(g.nodes().size()));
363
}
364
} // namespace opencv_test
365
366