Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / fluid / modules / gapi / test / gapi_basic_hetero_tests.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 #include "gapi_mock_kernels.hpp"
10
11 #include "opencv2/gapi/fluid/gfluidkernel.hpp"
12
13 namespace opencv_test
14 {
15
16 namespace
17 {
18     GAPI_OCV_KERNEL(OCVFoo, I::Foo)
19     {
20         static void run(const cv::Mat &in, cv::Mat &out)
21         {
22             out = in + 2;
23         }
24     };
25
26     GAPI_OCV_KERNEL(OCVBar, I::Bar)
27     {
28         static void run(const cv::Mat &a, const cv::Mat &b, cv::Mat &out)
29         {
30             out = 4*(a + b);
31         }
32     };
33
34     void FluidFooRow(const uint8_t* in, uint8_t* out, int length)
35     {
36         for (int i = 0; i < length; i++)
37         {
38             out[i] = in[i] + 3;
39         }
40     }
41
42     void FluidBarRow(const uint8_t* in1, const uint8_t* in2, uint8_t* out, int length)
43     {
44         for (int i = 0; i < length; i++)
45         {
46             out[i] = 3*(in1[i] + in2[i]);
47         }
48     }
49
50     GAPI_FLUID_KERNEL(FFoo, I::Foo, false)
51     {
52         static const int Window = 1;
53
54         static void run(const cv::gapi::fluid::View   &in,
55                               cv::gapi::fluid::Buffer &out)
56         {
57             FluidFooRow(in.InLineB(0), out.OutLineB(), in.length());
58         }
59     };
60
61     GAPI_FLUID_KERNEL(FBar, I::Bar, false)
62     {
63         static const int Window = 1;
64
65         static void run(const cv::gapi::fluid::View   &in1,
66                         const cv::gapi::fluid::View   &in2,
67                               cv::gapi::fluid::Buffer &out)
68         {
69             FluidBarRow(in1.InLineB(0), in2.InLineB(0), out.OutLineB(), in1.length());
70         }
71     };
72
73     G_TYPED_KERNEL(FluidFooI, <cv::GMat(cv::GMat)>, "test.kernels.fluid_foo")
74     {
75         static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
76     };
77
78     G_TYPED_KERNEL(FluidBarI, <cv::GMat(cv::GMat,cv::GMat)>, "test.kernels.fluid_bar")
79     {
80         static cv::GMatDesc outMeta(const cv::GMatDesc &in, const cv::GMatDesc &) { return in; }
81     };
82
83     GAPI_FLUID_KERNEL(FluidFoo, FluidFooI, false)
84     {
85         static const int Window = 1;
86
87         static void run(const cv::gapi::fluid::View   &in,
88                               cv::gapi::fluid::Buffer &out)
89         {
90             FluidFooRow(in.InLineB(0), out.OutLineB(), in.length());
91         }
92     };
93
94     GAPI_FLUID_KERNEL(FluidBar, FluidBarI, false)
95     {
96         static const int Window = 1;
97
98         static void run(const cv::gapi::fluid::View   &in1,
99                         const cv::gapi::fluid::View   &in2,
100                               cv::gapi::fluid::Buffer &out)
101         {
102             FluidBarRow(in1.InLineB(0), in2.InLineB(0), out.OutLineB(), in1.length());
103         }
104     };
105
106     GAPI_FLUID_KERNEL(FluidFoo2lpi, FluidFooI, false)
107     {
108         static const int Window = 1;
109         static const int LPI    = 2;
110
111         static void run(const cv::gapi::fluid::View   &in,
112                               cv::gapi::fluid::Buffer &out)
113         {
114             for (int l = 0; l < out.lpi(); l++)
115             {
116                 FluidFooRow(in.InLineB(l), out.OutLineB(l), in.length());
117             }
118         }
119     };
120
121     cv::Mat ocvFoo(const cv::Mat &in)
122     {
123         cv::Mat out;
124         OCVFoo::run(in, out);
125         return out;
126     }
127     cv::Mat ocvBar(const cv::Mat &in1, const cv::Mat &in2)
128     {
129         cv::Mat out;
130         OCVBar::run(in1, in2, out);
131         return out;
132     }
133     cv::Mat fluidFoo(const cv::Mat &in)
134     {
135         cv::Mat out(in.rows, in.cols, in.type());
136         for (int y = 0; y < in.rows; y++)
137         {
138             FluidFooRow(in.ptr(y), out.ptr(y), in.cols);
139         }
140         return out;
141     }
142     cv::Mat fluidBar(const cv::Mat &in1, const cv::Mat &in2)
143     {
144         cv::Mat out(in1.rows, in1.cols, in1.type());
145         for (int y = 0; y < in1.rows; y++)
146         {
147             FluidBarRow(in1.ptr(y), in2.ptr(y), out.ptr(y), in1.cols);
148         }
149         return out;
150     }
151 } // anonymous namespace
152
153 struct GAPIHeteroTest: public ::testing::Test
154 {
155     cv::GComputation m_comp;
156     cv::gapi::GKernelPackage m_ocv_kernels;
157     cv::gapi::GKernelPackage m_fluid_kernels;
158     cv::gapi::GKernelPackage m_hetero_kernels;
159
160     cv::Mat m_in_mat;
161     cv::Mat m_out_mat;
162
163     GAPIHeteroTest();
164 };
165
166 GAPIHeteroTest::GAPIHeteroTest()
167     : m_comp([](){
168             cv::GMat in;
169             cv::GMat out = I::Bar::on(I::Foo::on(in),
170                                       I::Foo::on(in));
171             return cv::GComputation(in, out);
172         })
173     , m_ocv_kernels(cv::gapi::kernels<OCVFoo, OCVBar>())
174     , m_fluid_kernels(cv::gapi::kernels<FFoo, FBar>())
175     , m_hetero_kernels(cv::gapi::kernels<OCVFoo, FBar>())
176     , m_in_mat(cv::Mat::eye(cv::Size(64, 64), CV_8UC1))
177 {
178 }
179
180 TEST_F(GAPIHeteroTest, TestOCV)
181 {
182     EXPECT_TRUE(cv::gapi::cpu::backend() == m_ocv_kernels.lookup<I::Foo>());
183     EXPECT_TRUE(cv::gapi::cpu::backend() == m_ocv_kernels.lookup<I::Bar>());
184
185     cv::Mat ref = ocvBar(ocvFoo(m_in_mat), ocvFoo(m_in_mat));
186     EXPECT_NO_THROW(m_comp.apply(m_in_mat, m_out_mat, cv::compile_args(m_ocv_kernels)));
187     EXPECT_EQ(0, cv::countNonZero(ref != m_out_mat));
188 }
189
190 TEST_F(GAPIHeteroTest, TestFluid)
191 {
192     EXPECT_TRUE(cv::gapi::fluid::backend() == m_fluid_kernels.lookup<I::Foo>());
193     EXPECT_TRUE(cv::gapi::fluid::backend() == m_fluid_kernels.lookup<I::Bar>());
194
195     cv::Mat ref = fluidBar(fluidFoo(m_in_mat), fluidFoo(m_in_mat));
196     EXPECT_NO_THROW(m_comp.apply(m_in_mat, m_out_mat, cv::compile_args(m_fluid_kernels)));
197     EXPECT_EQ(0, cv::countNonZero(ref != m_out_mat));
198 }
199
200 TEST_F(GAPIHeteroTest, TestBoth)
201 {
202     EXPECT_TRUE(cv::gapi::cpu::backend()   == m_hetero_kernels.lookup<I::Foo>());
203     EXPECT_TRUE(cv::gapi::fluid::backend() == m_hetero_kernels.lookup<I::Bar>());
204
205     cv::Mat ref = fluidBar(ocvFoo(m_in_mat), ocvFoo(m_in_mat));
206     EXPECT_NO_THROW(m_comp.apply(m_in_mat, m_out_mat, cv::compile_args(m_hetero_kernels)));
207     EXPECT_EQ(0, cv::countNonZero(ref != m_out_mat));
208 }
209
210 struct GAPIBigHeteroTest : public ::testing::TestWithParam<std::array<int, 9>>
211 {
212     cv::GComputation m_comp;
213     cv::gapi::GKernelPackage m_kernels;
214
215     cv::Mat m_in_mat;
216     cv::Mat m_out_mat1;
217     cv::Mat m_out_mat2;
218
219     cv::Mat m_ref_mat1;
220     cv::Mat m_ref_mat2;
221
222     GAPIBigHeteroTest();
223 };
224
225 //                                    Foo7
226 //                .-> Foo2 -> Foo3 -<
227 //   Foo0 -> Foo1                     Bar -> Foo6
228 //                `-> Foo4 -> Foo5 -`
229
230 GAPIBigHeteroTest::GAPIBigHeteroTest()
231     : m_comp([&](){
232         auto flags = GetParam();
233         std::array<std::function<cv::GMat(cv::GMat)>, 8> foos;
234
235         for (int i = 0; i < 8; i++)
236         {
237             foos[i] = flags[i] ? &I::Foo::on : &FluidFooI::on;
238         }
239         auto bar = flags[8] ? &I::Bar::on : &FluidBarI::on;
240
241         cv::GMat in;
242         auto foo1Out = foos[1](foos[0](in));
243         auto foo3Out = foos[3](foos[2](foo1Out));
244         auto foo6Out = foos[6](bar(foo3Out,
245                                foos[5](foos[4](foo1Out))));
246         auto foo7Out = foos[7](foo3Out);
247
248         return cv::GComputation(GIn(in), GOut(foo6Out, foo7Out));
249     })
250     , m_kernels(cv::gapi::kernels<OCVFoo, OCVBar, FluidFoo, FluidBar>())
251     , m_in_mat(cv::Mat::eye(cv::Size(64, 64), CV_8UC1))
252 {
253     auto flags = GetParam();
254     std::array<std::function<cv::Mat(cv::Mat)>, 8> foos;
255
256     for (int i = 0; i < 8; i++)
257     {
258         foos[i] = flags[i] ? ocvFoo : fluidFoo;
259     }
260     auto bar = flags[8] ? ocvBar : fluidBar;
261
262     cv::Mat foo1OutMat = foos[1](foos[0](m_in_mat));
263     cv::Mat foo3OutMat = foos[3](foos[2](foo1OutMat));
264
265     m_ref_mat1 = foos[6](bar(foo3OutMat,
266                              foos[5](foos[4](foo1OutMat))));
267
268     m_ref_mat2 = foos[7](foo3OutMat);
269 }
270
271 TEST_P(GAPIBigHeteroTest, Test)
272 {
273     EXPECT_NO_THROW(m_comp.apply(gin(m_in_mat), gout(m_out_mat1, m_out_mat2), cv::compile_args(m_kernels)));
274     EXPECT_EQ(0, cv::countNonZero(m_ref_mat1 != m_out_mat1));
275     EXPECT_EQ(0, cv::countNonZero(m_ref_mat2 != m_out_mat2));
276 }
277
278 static auto configurations = []()
279 {
280     // Fill all possible configurations
281     // from 000000000 to 111111111
282     std::array<std::array<int, 9>, 512> arr;
283     for (auto n = 0; n < 512; n++)
284     {
285         for (auto i = 0; i < 9; i++)
286         {
287             arr[n][i] = (n >> (8 - i)) & 1;
288         }
289     }
290     return arr;
291 }();
292
293 INSTANTIATE_TEST_CASE_P(GAPIBigHeteroTest, GAPIBigHeteroTest,
294                         ::testing::ValuesIn(configurations));
295
296 TEST(GAPIHeteroTestLPI, Test)
297 {
298     cv::GMat in;
299     auto mid = FluidFooI::on(in);
300     auto out = FluidFooI::on(mid);
301     cv::gapi::island("isl0", GIn(in),  GOut(mid));
302     cv::gapi::island("isl1", GIn(mid), GOut(out));
303     cv::GComputation c(in, out);
304
305     cv::Mat in_mat = cv::Mat::eye(cv::Size(64, 64), CV_8UC1);
306     cv::Mat out_mat;
307     EXPECT_NO_THROW(c.apply(in_mat, out_mat, cv::compile_args(cv::gapi::kernels<FluidFoo2lpi>())));
308     cv::Mat ref = fluidFoo(fluidFoo(in_mat));
309     EXPECT_EQ(0, cv::countNonZero(ref != out_mat));
310 }
311
312 }  // namespace opencv_test