Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / fluid / modules / gapi / test / gapi_fluid_test.cpp
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-2019 Intel Corporation
6
7
8 #include "test_precomp.hpp"
9
10 #include "opencv2/gapi/core.hpp"
11
12 #include "opencv2/gapi/fluid/gfluidbuffer.hpp"
13 #include "opencv2/gapi/fluid/gfluidkernel.hpp"
14
15  // FIXME: move these tests with priv() to internal suite
16 #include "backends/fluid/gfluidbuffer_priv.hpp"
17
18 #include "gapi_fluid_test_kernels.hpp"
19 #include "logger.hpp"
20
21 namespace opencv_test
22 {
23
24 using namespace cv::gapi_test_kernels;
25
26 namespace
27 {
28     void WriteFunction(uint8_t* row, int nr, int w) {
29         for (int i = 0; i < w; i++)
30             row[i] = static_cast<uint8_t>(nr+i);
31     };
32     void ReadFunction1x1(const uint8_t* row, int w) {
33         for (int i = 0; i < w; i++)
34             std::cout << std::setw(4) << static_cast<int>(row[i]) << " ";
35         std::cout << "\n";
36     };
37     void ReadFunction3x3(const uint8_t* rows[3], int w) {
38         for (int i = 0; i < 3; i++) {
39             for (int j = -1; j < w+1; j++) {
40                 std::cout << std::setw(4) << static_cast<int>(rows[i][j]) << " ";
41             }
42             std::cout << "\n";
43         }
44         std::cout << "\n";
45     };
46 }
47
48 TEST(FluidBuffer, InputTest)
49 {
50     const cv::Size buffer_size = {8,8};
51     cv::Mat in_mat = cv::Mat::eye(buffer_size, CV_8U);
52
53     cv::gapi::fluid::Buffer buffer(to_own(in_mat), true);
54     cv::gapi::fluid::View  view = buffer.mkView(0, false);
55     view.priv().allocate(1, {});
56     view.priv().reset(1);
57     int this_y = 0;
58
59     while (this_y < buffer_size.height)
60     {
61         view.priv().prepareToRead();
62         const uint8_t* rrow = view.InLine<uint8_t>(0);
63         ReadFunction1x1(rrow, buffer_size.width);
64         view.priv().readDone(1,1);
65
66         cv::Mat from_buffer(1, buffer_size.width, CV_8U, const_cast<uint8_t*>(rrow));
67         EXPECT_EQ(0, cv::countNonZero(in_mat.row(this_y) != from_buffer));
68
69         this_y++;
70     }
71 }
72
73 TEST(FluidBuffer, CircularTest)
74 {
75     const cv::Size buffer_size = {8,16};
76
77     cv::gapi::fluid::Buffer buffer(cv::GMatDesc{CV_8U,1,buffer_size}, 3, 1, 0, 1,
78         util::make_optional(cv::gapi::fluid::Border{cv::BORDER_CONSTANT, cv::gapi::own::Scalar(255)}));
79     cv::gapi::fluid::View view = buffer.mkView(1, {});
80     view.priv().reset(3);
81     view.priv().allocate(3, {});
82     buffer.debug(std::cout);
83
84     const auto whole_line_is = [](const uint8_t *line, int len, int value)
85     {
86         return std::all_of(line, line+len, [&](const uint8_t v){return v == value;});
87     };
88
89     // Store all read/written data in separate Mats to compare with
90     cv::Mat written_data(buffer_size, CV_8U);
91
92     // Simulate write/read process
93     int num_reads = 0, num_writes = 0;
94     while (num_reads < buffer_size.height)
95     {
96         if (num_writes < buffer_size.height)
97         {
98             uint8_t* wrow = buffer.OutLine<uint8_t>();
99             WriteFunction(wrow, num_writes, buffer_size.width);
100             buffer.priv().writeDone();
101
102             cv::Mat(1, buffer_size.width, CV_8U, wrow)
103                 .copyTo(written_data.row(num_writes));
104             num_writes++;
105         }
106         buffer.debug(std::cout);
107
108         if (view.ready())
109         {
110             view.priv().prepareToRead();
111             const uint8_t* rrow[3] = {
112                 view.InLine<uint8_t>(-1),
113                 view.InLine<uint8_t>( 0),
114                 view.InLine<uint8_t>( 1),
115             };
116             ReadFunction3x3(rrow, buffer_size.width);
117             view.priv().readDone(1,3);
118             buffer.debug(std::cout);
119
120             // Check borders right here
121             EXPECT_EQ(255u, rrow[0][-1]);
122             EXPECT_EQ(255u, rrow[0][buffer_size.width]);
123             if (num_reads == 0)
124             {
125                 EXPECT_TRUE(whole_line_is(rrow[0]-1, buffer_size.width+2, 255u));
126             }
127             if (num_reads == buffer_size.height-1)
128             {
129                 EXPECT_TRUE(whole_line_is(rrow[2]-1, buffer_size.width+2, 255u));
130             }
131
132             // Check window (without borders)
133             if (num_reads > 0 && num_reads < buffer_size.height-1)
134             {
135                 // +1 everywhere since num_writes was just incremented above
136                 cv::Mat written_lastLine2 = written_data.row(num_writes - (2+1));
137                 cv::Mat written_lastLine1 = written_data.row(num_writes - (1+1));
138                 cv::Mat written_lastLine0 = written_data.row(num_writes - (0+1));
139
140                 cv::Mat read_prevLine(1, buffer_size.width, CV_8U, const_cast<uint8_t*>(rrow[0]));
141                 cv::Mat read_thisLine(1, buffer_size.width, CV_8U, const_cast<uint8_t*>(rrow[1]));
142                 cv::Mat read_nextLine(1, buffer_size.width, CV_8U, const_cast<uint8_t*>(rrow[2]));
143
144                 EXPECT_EQ(0, cv::countNonZero(written_lastLine2 != read_prevLine));
145                 EXPECT_EQ(0, cv::countNonZero(written_lastLine1 != read_thisLine));
146                 EXPECT_EQ(0, cv::countNonZero(written_lastLine0 != read_nextLine));
147             }
148             num_reads++;
149         }
150     }
151 }
152
153 TEST(FluidBuffer, OutputTest)
154 {
155     const cv::Size buffer_size = {8,16};
156     cv::Mat out_mat = cv::Mat(buffer_size, CV_8U);
157
158     cv::gapi::fluid::Buffer buffer(to_own(out_mat), false);
159     int num_writes = 0;
160     while (num_writes < buffer_size.height)
161     {
162         uint8_t* wrow = buffer.OutLine<uint8_t>();
163         WriteFunction(wrow, num_writes, buffer_size.width);
164         buffer.priv().writeDone();
165         num_writes++;
166     }
167
168     GAPI_LOG_INFO(NULL, "\n" << out_mat);
169
170     // Validity check
171     for (int r = 0; r < buffer_size.height; r++)
172     {
173         for (int c = 0; c < buffer_size.width; c++)
174         {
175             EXPECT_EQ(r+c, out_mat.at<uint8_t>(r, c));
176         }
177     }
178 }
179
180 TEST(Fluid, AddC_WithScalar)
181 {
182     cv::GMat in;
183     cv::GScalar s;
184
185     cv::GComputation c(cv::GIn(in, s), cv::GOut(TAddScalar::on(in, s)));
186     cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1), out_mat(3, 3, CV_8UC1), ref_mat;
187     cv::Scalar in_s(100);
188
189     auto cc = c.compile(cv::descr_of(in_mat), cv::descr_of(in_s), cv::compile_args(fluidTestPackage));
190
191     cc(cv::gin(in_mat, in_s), cv::gout(out_mat));
192     ref_mat = in_mat + in_s;
193     EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
194 }
195
196 TEST(Fluid, Scalar_In_Middle_Graph)
197 {
198     cv::GMat in;
199     cv::GScalar s;
200
201     cv::GComputation c(cv::GIn(in, s), cv::GOut(TAddScalar::on(TAddCSimple::on(in, 5), s)));
202     cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1), out_mat(3, 3, CV_8UC1), ref_mat;
203     cv::Scalar in_s(100);
204
205     auto cc = c.compile(cv::descr_of(in_mat), cv::descr_of(in_s), cv::compile_args(fluidTestPackage));
206
207     cc(cv::gin(in_mat, in_s), cv::gout(out_mat));
208     ref_mat = (in_mat + 5) + in_s;
209     EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
210 }
211
212 TEST(Fluid, Add_Scalar_To_Mat)
213 {
214     cv::GMat in;
215     cv::GScalar s;
216
217     cv::GComputation c(cv::GIn(s, in), cv::GOut(TAddScalarToMat::on(s, in)));
218     cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1), out_mat(3, 3, CV_8UC1), ref_mat;
219     cv::Scalar in_s(100);
220
221     auto cc = c.compile(cv::descr_of(in_s), cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
222
223     cc(cv::gin(in_s, in_mat), cv::gout(out_mat));
224     ref_mat = in_mat + in_s;
225     EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
226 }
227
228 TEST(Fluid, Sum_2_Mats_And_Scalar)
229 {
230     cv::GMat a, b;
231     cv::GScalar s;
232
233     cv::GComputation c(cv::GIn(a, s, b), cv::GOut(TSum2MatsAndScalar::on(a, s, b)));
234     cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
235             in_mat2 = cv::Mat::eye(3, 3, CV_8UC1),
236             out_mat(3, 3, CV_8UC1),
237             ref_mat;
238     cv::Scalar in_s(100);
239
240     auto cc = c.compile(cv::descr_of(in_mat1), cv::descr_of(in_s), cv::descr_of(in_mat2), cv::compile_args(fluidTestPackage));
241
242     cc(cv::gin(in_mat1, in_s, in_mat2), cv::gout(out_mat));
243     ref_mat = in_mat1 + in_mat2 + in_s;
244     EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
245 }
246
247 TEST(Fluid, Split3)
248 {
249     cv::GMat bgr;
250     cv::GMat r,g,b;
251     std::tie(b,g,r) = cv::gapi::split3(bgr);
252     auto rr = TAddSimple::on(r, TId::on(b));
253     auto rrr = TAddSimple::on(TId::on(rr), g);
254     cv::GComputation c(bgr, TId::on(rrr));
255
256     cv::Size sz(5120, 5120);
257     cv::Mat eye_1 = cv::Mat::eye(sz, CV_8UC1);
258     std::vector<cv::Mat> eyes = {eye_1, eye_1, eye_1};
259     cv::Mat in_mat;
260     cv::merge(eyes, in_mat);
261     cv::Mat out_mat(sz, CV_8UC1);
262
263     // G-API
264     auto cc = c.compile(cv::descr_of(in_mat),
265                         cv::compile_args(fluidTestPackage));
266     cc(in_mat, out_mat);
267
268     // OCV
269     std::vector<cv::Mat> chans;
270     cv::split(in_mat, chans);
271
272     // Compare
273     EXPECT_EQ(0, cv::countNonZero(out_mat != (chans[2]*3)));
274 }
275
276 TEST(Fluid, ScratchTest)
277 {
278     cv::GMat in;
279     cv::GMat out = TPlusRow0::on(TPlusRow0::on(in));
280     cv::GComputation c(in, out);
281
282     cv::Size sz(8, 8);
283     cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
284     cv::Mat out_mat(sz, CV_8UC1);
285
286     // OpenCV (reference)
287     cv::Mat ref;
288     {
289         cv::Mat first_row = cv::Mat::zeros(1, sz.width, CV_8U);
290         cv::Mat remaining = cv::repeat(in_mat.row(0), sz.height-1, 1);
291         cv::Mat operand;
292         cv::vconcat(first_row, 2*remaining, operand);
293         ref = in_mat + operand;
294     }
295     GAPI_LOG_INFO(NULL, "\n" << ref);
296
297     // G-API
298     auto cc = c.compile(cv::descr_of(in_mat),
299                         cv::compile_args(fluidTestPackage));
300     cc(in_mat, out_mat);
301     GAPI_LOG_INFO(NULL, "\n" << out_mat);
302     EXPECT_EQ(0, cv::countNonZero(ref != out_mat));
303
304     cc(in_mat, out_mat);
305     GAPI_LOG_INFO(NULL, "\n" << out_mat);
306     EXPECT_EQ(0, cv::countNonZero(ref != out_mat));
307 }
308
309 TEST(Fluid, MultipleOutRowsTest)
310 {
311     cv::GMat in;
312     cv::GMat out = TAddCSimple::on(TAddCSimple::on(in, 1), 2);
313     cv::GComputation c(in, out);
314
315     cv::Size sz(4, 4);
316     cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
317     cv::Mat out_mat(sz, CV_8UC1);
318
319     auto cc = c.compile(cv::descr_of(in_mat),
320                         cv::compile_args(fluidTestPackage));
321     cc(in_mat, out_mat);
322
323     std::cout << out_mat << std::endl;
324
325     cv::Mat ocv_ref = in_mat + 1 + 2;
326     EXPECT_EQ(0, cv::countNonZero(ocv_ref != out_mat));
327 }
328
329
330 TEST(Fluid, LPIWindow)
331 {
332     cv::GMat in;
333     cv::GMat r,g,b;
334     std::tie(r,g,b) = cv::gapi::split3(in);
335     cv::GMat rr = TId7x7::on(r);
336     cv::GMat tmp = TAddSimple::on(rr, g);
337     cv::GMat out = TAddSimple::on(tmp, b);
338
339     cv::GComputation c(in, out);
340
341     cv::Size sz(8, 8);
342
343     cv::Mat eye_1 = cv::Mat::eye(sz, CV_8UC1);
344     std::vector<cv::Mat> eyes = {eye_1, eye_1, eye_1};
345     cv::Mat in_mat;
346     cv::merge(eyes, in_mat);
347
348     cv::Mat out_mat(sz, CV_8U);
349     auto cc = c.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
350     cc(in_mat, out_mat);
351
352     //std::cout << out_mat << std::endl;
353
354     // OpenCV reference
355     cv::Mat ocv_ref = eyes[0]+eyes[1]+eyes[2];
356
357     EXPECT_EQ(0, cv::countNonZero(ocv_ref != out_mat));
358 }
359
360 TEST(Fluid, MultipleReaders_SameLatency)
361 {
362     //  in -> AddC -> a -> AddC -> b -> Add -> out
363     //                '--> AddC -> c -'
364     //
365     // b and c have the same skew
366
367     cv::GMat in;
368     cv::GMat a = TAddCSimple::on(in, 1); // FIXME - align naming (G, non-G)
369     cv::GMat b = TAddCSimple::on(a,  2);
370     cv::GMat c = TAddCSimple::on(a,  3);
371     cv::GMat out = TAddSimple::on(b, c);
372     cv::GComputation comp(in, out);
373
374     const auto sz = cv::Size(32, 32);
375     cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
376     cv::Mat out_mat_gapi(sz, CV_8UC1);
377     cv::Mat out_mat_ocv (sz, CV_8UC1);
378
379     // Run G-API
380     auto cc = comp.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
381     cc(in_mat, out_mat_gapi);
382
383     // Check with OpenCV
384     cv::Mat tmp = in_mat + 1;
385     out_mat_ocv = (tmp+2) + (tmp+3);
386     EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
387 }
388
389 TEST(Fluid, MultipleReaders_DifferentLatency)
390 {
391     //  in1 -> AddC -> a -> AddC -------------> b -> Add -> out
392     //                 '--------------> Add --> c -'
393     //                 '--> Id7x7-> d -'
394     //
395     // b and c have different skew (due to latency introduced by Id7x7)
396     // a is ready by multiple views with different latency.
397
398     cv::GMat in;
399     cv::GMat a   = TAddCSimple::on(in, 1); // FIXME - align naming (G, non-G)
400     cv::GMat b   = TAddCSimple::on(a,  2);
401     cv::GMat d   = TId7x7::on(a);
402     cv::GMat c   = TAddSimple::on(a, d);
403     cv::GMat out = TAddSimple::on(b, c);
404     cv::GComputation comp(in, out);
405
406     const auto sz = cv::Size(32, 32);
407     cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
408     cv::Mat out_mat_gapi(sz, CV_8UC1);
409
410     // Run G-API
411     auto cc = comp.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
412     cc(in_mat, out_mat_gapi);
413
414     // Check with OpenCV
415     cv::Mat ocv_a = in_mat + 1;
416     cv::Mat ocv_b = ocv_a + 2;
417     cv::Mat ocv_d = ocv_a;
418     cv::Mat ocv_c = ocv_a + ocv_d;
419     cv::Mat out_mat_ocv = ocv_b + ocv_c;
420     EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
421 }
422
423 TEST(Fluid, MultipleOutputs)
424 {
425     // in -> AddC -> a -> AddC ------------------> out1
426     //               `--> Id7x7  --> b --> AddC -> out2
427
428     cv::GMat in;
429     cv::GMat a    = TAddCSimple::on(in, 1);
430     cv::GMat b    = TId7x7::on(a);
431     cv::GMat out1 = TAddCSimple::on(a, 2);
432     cv::GMat out2 = TAddCSimple::on(b, 7);
433     cv::GComputation comp(cv::GIn(in), cv::GOut(out1, out2));
434
435     const auto sz = cv::Size(32, 32);
436     cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
437     cv::Mat out_mat_gapi1(sz, CV_8UC1), out_mat_gapi2(sz, CV_8UC1);
438     cv::Mat out_mat_ocv1(sz, CV_8UC1), out_mat_ocv2(sz, CV_8UC1);
439
440     // Run G-API
441     auto cc = comp.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
442     cc(cv::gin(in_mat), cv::gout(out_mat_gapi1, out_mat_gapi2));
443
444     // Check with OpenCV
445     out_mat_ocv1 = in_mat + 1 + 2;
446     out_mat_ocv2 = in_mat + 1 + 7;
447     EXPECT_EQ(0, cv::countNonZero(out_mat_gapi1 != out_mat_ocv1));
448     EXPECT_EQ(0, cv::countNonZero(out_mat_gapi2 != out_mat_ocv2));
449 }
450
451 TEST(Fluid, EmptyOutputMatTest)
452 {
453     cv::GMat in;
454     cv::GMat out = TAddCSimple::on(in, 2);
455     cv::GComputation c(in, out);
456
457     cv::Mat in_mat = cv::Mat::eye(cv::Size(32, 24), CV_8UC1);
458     cv::Mat out_mat;
459
460     auto cc = c.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
461
462     cc(in_mat,    out_mat);
463     EXPECT_EQ(CV_8UC1, out_mat.type());
464     EXPECT_EQ(32, out_mat.cols);
465     EXPECT_EQ(24, out_mat.rows);
466     EXPECT_TRUE(out_mat.ptr() != nullptr);
467 }
468
469 struct LPISequenceTest : public TestWithParam<int>{};
470 TEST_P(LPISequenceTest, LPISequenceTest)
471 {
472     // in -> AddC -> a -> Blur (2lpi) -> out
473
474     int kernelSize = GetParam();
475     cv::GMat in;
476     cv::GMat a = TAddCSimple::on(in, 1);
477     auto blur = kernelSize == 3 ? &TBlur3x3_2lpi::on : &TBlur5x5_2lpi::on;
478     cv::GMat out = blur(a, cv::BORDER_CONSTANT, cv::Scalar(0));
479     cv::GComputation comp(cv::GIn(in), cv::GOut(out));
480
481     const auto sz = cv::Size(8, 10);
482     cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
483     cv::Mat out_mat_gapi(sz, CV_8UC1);
484     cv::Mat out_mat_ocv(sz, CV_8UC1);
485
486     // Run G-API
487     auto cc = comp.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
488     cc(cv::gin(in_mat), cv::gout(out_mat_gapi));
489
490     // Check with OpenCV
491     cv::blur(in_mat + 1, out_mat_ocv, {kernelSize,kernelSize}, {-1,-1}, cv::BORDER_CONSTANT);
492     EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
493 }
494
495 INSTANTIATE_TEST_CASE_P(Fluid, LPISequenceTest,
496                         Values(3, 5));
497
498 struct InputImageBorderTest : public TestWithParam <std::tuple<int, int>> {};
499 TEST_P(InputImageBorderTest, InputImageBorderTest)
500 {
501     cv::Size sz_in = { 320, 240 };
502
503     int ks         = 0;
504     int borderType = 0;
505     std::tie(ks, borderType) = GetParam();
506     cv::Mat in_mat1(sz_in, CV_8UC1);
507     cv::Scalar mean   = cv::Scalar(127.0f);
508     cv::Scalar stddev = cv::Scalar(40.f);
509
510     cv::randn(in_mat1, mean, stddev);
511
512     cv::Size kernelSize = {ks, ks};
513     cv::Point anchor = {-1, -1};
514     cv::Scalar borderValue(0);
515
516     auto gblur = ks == 3 ? &TBlur3x3::on : &TBlur5x5::on;
517
518     GMat in;
519     auto out = gblur(in, borderType, borderValue);
520
521     Mat out_mat_gapi = Mat::zeros(sz_in, CV_8UC1);
522
523     GComputation c(GIn(in), GOut(out));
524     auto cc = c.compile(descr_of(in_mat1), cv::compile_args(fluidTestPackage));
525     cc(gin(in_mat1), gout(out_mat_gapi));
526
527     cv::Mat out_mat_ocv = Mat::zeros(sz_in, CV_8UC1);
528     cv::blur(in_mat1, out_mat_ocv, kernelSize, anchor, borderType);
529
530     EXPECT_EQ(0, countNonZero(out_mat_ocv != out_mat_gapi));
531 }
532
533 INSTANTIATE_TEST_CASE_P(Fluid, InputImageBorderTest,
534                         Combine(Values(3, 5),
535                                 Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT_101)));
536
537 struct SequenceOfBlursTest : public TestWithParam <std::tuple<int>> {};
538 TEST_P(SequenceOfBlursTest, Test)
539 {
540     cv::Size sz_in = { 320, 240 };
541
542     int borderType = 0;;
543     std::tie(borderType) = GetParam();
544     cv::Mat in_mat(sz_in, CV_8UC1);
545     cv::Scalar mean   = cv::Scalar(127.0f);
546     cv::Scalar stddev = cv::Scalar(40.f);
547
548     cv::randn(in_mat, mean, stddev);
549
550     cv::Point anchor = {-1, -1};
551     cv::Scalar borderValue(0);
552
553     GMat in;
554     auto mid = TBlur3x3::on(in,  borderType, borderValue);
555     auto out = TBlur5x5::on(mid, borderType, borderValue);
556
557     Mat out_mat_gapi = Mat::zeros(sz_in, CV_8UC1);
558
559     GComputation c(GIn(in), GOut(out));
560     auto cc = c.compile(descr_of(in_mat), cv::compile_args(fluidTestPackage));
561     cc(gin(in_mat), gout(out_mat_gapi));
562
563     cv::Mat mid_mat_ocv = Mat::zeros(sz_in, CV_8UC1);
564     cv::Mat out_mat_ocv = Mat::zeros(sz_in, CV_8UC1);
565     cv::blur(in_mat, mid_mat_ocv, {3,3}, anchor, borderType);
566     cv::blur(mid_mat_ocv, out_mat_ocv, {5,5}, anchor, borderType);
567
568     EXPECT_EQ(0, countNonZero(out_mat_ocv != out_mat_gapi));
569 }
570
571 INSTANTIATE_TEST_CASE_P(Fluid, SequenceOfBlursTest,
572                                Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT_101));
573
574 struct TwoBlursTest : public TestWithParam <std::tuple<int, int, int, int, int, int, bool>> {};
575 TEST_P(TwoBlursTest, Test)
576 {
577     cv::Size sz_in = { 320, 240 };
578
579     int kernelSize1 = 0, kernelSize2 = 0;
580     int borderType1 = -1, borderType2 = -1;
581     cv::Scalar borderValue1{}, borderValue2{};
582     bool readFromInput = false;
583     std::tie(kernelSize1, borderType1, borderValue1, kernelSize2, borderType2, borderValue2, readFromInput) = GetParam();
584     cv::Mat in_mat(sz_in, CV_8UC1);
585     cv::Scalar mean   = cv::Scalar(127.0f);
586     cv::Scalar stddev = cv::Scalar(40.f);
587
588     cv::randn(in_mat, mean, stddev);
589
590     cv::Point anchor = {-1, -1};
591
592     auto blur1 = kernelSize1 == 3 ? &TBlur3x3::on : TBlur5x5::on;
593     auto blur2 = kernelSize2 == 3 ? &TBlur3x3::on : TBlur5x5::on;
594
595     GMat in, out1, out2;
596     if (readFromInput)
597     {
598         out1 = blur1(in, borderType1, borderValue1);
599         out2 = blur2(in, borderType2, borderValue2);
600     }
601     else
602     {
603         auto mid = TAddCSimple::on(in, 0);
604         out1 = blur1(mid, borderType1, borderValue1);
605         out2 = blur2(mid, borderType2, borderValue2);
606     }
607
608     Mat out_mat_gapi1 = Mat::zeros(sz_in, CV_8UC1);
609     Mat out_mat_gapi2 = Mat::zeros(sz_in, CV_8UC1);
610
611     GComputation c(GIn(in), GOut(out1, out2));
612     auto cc = c.compile(descr_of(in_mat), cv::compile_args(fluidTestPackage));
613     cc(gin(in_mat), gout(out_mat_gapi1, out_mat_gapi2));
614
615     cv::Mat out_mat_ocv1 = Mat::zeros(sz_in, CV_8UC1);
616     cv::Mat out_mat_ocv2 = Mat::zeros(sz_in, CV_8UC1);
617     cv::blur(in_mat, out_mat_ocv1, {kernelSize1, kernelSize1}, anchor, borderType1);
618     cv::blur(in_mat, out_mat_ocv2, {kernelSize2, kernelSize2}, anchor, borderType2);
619
620     EXPECT_EQ(0, countNonZero(out_mat_ocv1 != out_mat_gapi1));
621     EXPECT_EQ(0, countNonZero(out_mat_ocv2 != out_mat_gapi2));
622 }
623
624 INSTANTIATE_TEST_CASE_P(Fluid, TwoBlursTest,
625                                Combine(Values(3, 5),
626                                        Values(cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_REFLECT_101),
627                                        Values(0),
628                                        Values(3, 5),
629                                        Values(cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_REFLECT_101),
630                                        Values(0),
631                                        testing::Bool())); // Read from input directly or place a copy node at start
632
633 struct TwoReadersTest : public TestWithParam <std::tuple<int, int, int, bool>> {};
634 TEST_P(TwoReadersTest, Test)
635 {
636     cv::Size sz_in = { 320, 240 };
637
638     int kernelSize = 0;
639     int borderType = -1;
640     cv::Scalar borderValue;
641     bool readFromInput = false;
642     std::tie(kernelSize, borderType, borderValue, readFromInput) = GetParam();
643     cv::Mat in_mat(sz_in, CV_8UC1);
644     cv::Scalar mean   = cv::Scalar(127.0f);
645     cv::Scalar stddev = cv::Scalar(40.f);
646
647     cv::randn(in_mat, mean, stddev);
648
649     cv::Point anchor = {-1, -1};
650
651     auto blur = kernelSize == 3 ? &TBlur3x3::on : TBlur5x5::on;
652
653     GMat in, out1, out2;
654     if (readFromInput)
655     {
656         out1 = TAddCSimple::on(in, 0);
657         out2 = blur(in, borderType, borderValue);
658     }
659     else
660     {
661         auto mid = TAddCSimple::on(in, 0);
662         out1 = TAddCSimple::on(mid, 0);
663         out2 = blur(mid, borderType, borderValue);
664     }
665
666     Mat out_mat_gapi1 = Mat::zeros(sz_in, CV_8UC1);
667     Mat out_mat_gapi2 = Mat::zeros(sz_in, CV_8UC1);
668
669     GComputation c(GIn(in), GOut(out1, out2));
670     auto cc = c.compile(descr_of(in_mat), cv::compile_args(fluidTestPackage));
671     cc(gin(in_mat), gout(out_mat_gapi1, out_mat_gapi2));
672
673     cv::Mat out_mat_ocv1 = Mat::zeros(sz_in, CV_8UC1);
674     cv::Mat out_mat_ocv2 = Mat::zeros(sz_in, CV_8UC1);
675     out_mat_ocv1 = in_mat;
676     cv::blur(in_mat, out_mat_ocv2, {kernelSize, kernelSize}, anchor, borderType);
677
678     EXPECT_EQ(0, countNonZero(out_mat_ocv1 != out_mat_gapi1));
679     EXPECT_EQ(0, countNonZero(out_mat_ocv2 != out_mat_gapi2));
680 }
681
682 INSTANTIATE_TEST_CASE_P(Fluid, TwoReadersTest,
683                                Combine(Values(3, 5),
684                                        Values(cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_REFLECT_101),
685                                        Values(0),
686                                        testing::Bool())); // Read from input directly or place a copy node at start
687
688 TEST(FluidTwoIslands, SanityTest)
689 {
690     cv::Size sz_in{8,8};
691
692     GMat in1, in2;
693     auto out1 = TAddScalar::on(in1, {0});
694     auto out2 = TAddScalar::on(in2, {0});
695
696     cv::Mat in_mat1(sz_in, CV_8UC1);
697     cv::Mat in_mat2(sz_in, CV_8UC1);
698     cv::Scalar mean   = cv::Scalar(127.0f);
699     cv::Scalar stddev = cv::Scalar(40.f);
700
701     cv::randn(in_mat1, mean, stddev);
702     cv::randn(in_mat2, mean, stddev);
703
704     Mat out_mat1 = Mat::zeros(sz_in, CV_8UC1);
705     Mat out_mat2 = Mat::zeros(sz_in, CV_8UC1);
706
707     GComputation c(GIn(in1, in2), GOut(out1, out2));
708     EXPECT_NO_THROW(c.apply(gin(in_mat1, in_mat2), gout(out_mat1, out_mat2), cv::compile_args(fluidTestPackage)));
709     EXPECT_EQ(0, countNonZero(in_mat1 != out_mat1));
710     EXPECT_EQ(0, countNonZero(in_mat2 != out_mat2));
711 }
712
713 } // namespace opencv_test