Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / fluid / modules / gapi / test / gapi_fluid_resize_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 "gapi_fluid_test_kernels.hpp"
11
12 namespace opencv_test
13 {
14
15 using namespace cv::gapi_test_kernels;
16
17 G_TYPED_KERNEL(TCopy, <GMat(GMat)>, "test.fluid.copy")
18 {
19     static GMatDesc outMeta(const cv::GMatDesc &in) {
20         return in;
21     }
22 };
23
24 GAPI_FLUID_KERNEL(FCopy, TCopy, false)
25 {
26     static const int Window = 1;
27
28     static void run(const cv::gapi::fluid::View   &in,
29                           cv::gapi::fluid::Buffer &out)
30     {
31         const uint8_t* in_row  = in .InLine <uint8_t>(0);
32         uint8_t* out_row = out.OutLine<uint8_t>();
33
34         for (int i = 0, w = in.length(); i < w; i++)
35         {
36             //std::cout << std::setw(4) << int(in_row[i]);
37             out_row[i] = in_row[i];
38         }
39         //std::cout << std::endl;
40     }
41 };
42
43 GAPI_FLUID_KERNEL(FResizeNN1Lpi, cv::gapi::core::GResize, false)
44 {
45     static const int Window = 1;
46     static const auto Kind = GFluidKernel::Kind::Resize;
47
48     static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
49                     cv::gapi::fluid::Buffer& out)
50
51     {
52         auto length = out.length();
53         double vRatio = (double)in.meta().size.height / out.meta().size.height;
54         double hRatio = (double)in.length() / length;
55         auto y = out.y();
56         auto inY = in.y();
57
58         for (int l = 0; l < out.lpi(); l++)
59         {
60             auto sy = static_cast<int>((y+l) * vRatio);
61             int idx = sy - inY;
62
63             const auto src = in.InLine <unsigned char>(idx);
64             auto dst = out.OutLine<unsigned char>(l);
65
66             for (int x = 0; x < length; x++)
67             {
68                 auto inX = static_cast<int>(x * hRatio);
69                 dst[x] = src[inX];
70             }
71         }
72     }
73 };
74
75 namespace
76 {
77 namespace func
78 {
79 template <class Mapper>
80 void initScratch(const cv::GMatDesc& in, cv::Size outSz, cv::gapi::fluid::Buffer &scratch)
81 {
82     CV_Assert(in.depth == CV_8U && in.chan == 1);
83
84     cv::Size scratch_size{static_cast<int>(outSz.width * sizeof(typename Mapper::Unit)), 1};
85
86     cv::GMatDesc desc;
87     desc.chan  = 1;
88     desc.depth = CV_8UC1;
89     desc.size  = scratch_size;
90
91     cv::gapi::fluid::Buffer buffer(desc);
92     scratch = std::move(buffer);
93
94     auto mapX = scratch.OutLine<typename Mapper::Unit>();
95     double hRatio = (double)in.size.width / outSz.width;
96
97     for (int x = 0, w = outSz.width; x < w; x++)
98     {
99         mapX[x] = Mapper::map(hRatio, 0, in.size.width, x);
100     }
101 }
102
103 template <class Mapper>
104 inline void calcRow(const cv::gapi::fluid::View& in, cv::gapi::fluid::Buffer& out, cv::gapi::fluid::Buffer &scratch)
105 {
106     double vRatio = (double)in.meta().size.height / out.meta().size.height;
107     auto mapX = scratch.OutLine<typename Mapper::Unit>();
108     auto inY = in.y();
109     auto inH = in.meta().size.height;
110     auto outY = out.y();
111     auto length = out.length();
112
113     for (int l = 0; l < out.lpi(); l++)
114     {
115         auto mapY = Mapper::map(vRatio, inY, inH, outY + l);
116
117         const auto src0 = in.InLine <unsigned char>(mapY.s0);
118         const auto src1 = in.InLine <unsigned char>(mapY.s1);
119
120         auto dst = out.OutLine<unsigned char>(l);
121
122         for (int x = 0; x < length; x++)
123         {
124             auto alpha0 = mapX[x].alpha0;
125             auto alpha1 = mapX[x].alpha1;
126             auto sx0 = mapX[x].s0;
127             auto sx1 = mapX[x].s1;
128
129             int res0 = src0[sx0]*alpha0 + src0[sx1]*alpha1;
130             int res1 = src1[sx0]*alpha0 + src1[sx1]*alpha1;
131
132             dst[x] = uchar(( ((mapY.alpha0 * (res0 >> 4)) >> 16) + ((mapY.alpha1 * (res1 >> 4)) >> 16) + 2)>>2);
133         }
134     }
135 }
136 } // namespace func
137
138 constexpr static const int INTER_RESIZE_COEF_BITS = 11;
139 constexpr static const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;
140
141 namespace linear
142 {
143 struct Mapper
144 {
145     struct Unit
146     {
147         short alpha0;
148         short alpha1;
149         int   s0;
150         int   s1;
151     };
152
153     static inline Unit map(double ratio, int start, int max, int outCoord)
154     {
155         auto f = static_cast<float>((outCoord + 0.5f) * ratio - 0.5f);
156         int s = cvFloor(f);
157         f -= s;
158
159         Unit u;
160
161         u.s0 = std::max(s - start, 0);
162         u.s1 = ((f == 0.0) || s + 1 >= max) ? s - start : s - start + 1;
163
164         u.alpha0 = saturate_cast<short>((1.0f - f) * INTER_RESIZE_COEF_SCALE);
165         u.alpha1 = saturate_cast<short>((f) * INTER_RESIZE_COEF_SCALE);
166
167         return u;
168     }
169 };
170
171 } // namespace linear
172
173 namespace areaUpscale
174 {
175 struct Mapper
176 {
177     struct Unit
178     {
179         short alpha0;
180         short alpha1;
181         int   s0;
182         int   s1;
183     };
184
185     static inline Unit map(double ratio, int start, int max, int outCoord)
186     {
187         int s = cvFloor(outCoord*ratio);
188         float f = (float)((outCoord+1) - (s+1)/ratio);
189         f = f <= 0 ? 0.f : f - cvFloor(f);
190
191         Unit u;
192
193         u.s0 = std::max(s - start, 0);
194         u.s1 = ((f == 0.0) || s + 1 >= max) ? s - start : s - start + 1;
195
196         u.alpha0 = saturate_cast<short>((1.0f - f) * INTER_RESIZE_COEF_SCALE);
197         u.alpha1 = saturate_cast<short>((f) * INTER_RESIZE_COEF_SCALE);
198
199         return u;
200     }
201 };
202 } // namespace areaUpscale
203 } // anonymous namespace
204
205 GAPI_FLUID_KERNEL(FResizeLinear1Lpi, cv::gapi::core::GResize, true)
206 {
207     static const int Window = 1;
208     static const auto Kind = GFluidKernel::Kind::Resize;
209
210     static void initScratch(const cv::GMatDesc& in,
211                             cv::Size outSz, double /*fx*/, double /*fy*/, int /*interp*/,
212                             cv::gapi::fluid::Buffer &scratch)
213     {
214         func::initScratch<linear::Mapper>(in, outSz, scratch);
215     }
216
217     static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
218     {}
219
220     static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
221                     cv::gapi::fluid::Buffer& out, cv::gapi::fluid::Buffer &scratch)
222
223     {
224         func::calcRow<linear::Mapper>(in, out, scratch);
225     }
226 };
227
228 namespace
229 {
230 // FIXME
231 // Move to some common place (to reuse/align with ResizeAgent)
232 auto startInCoord = [](int outCoord, double ratio) {
233     return static_cast<int>(outCoord * ratio + 1e-3);
234 };
235 auto endInCoord = [](int outCoord, double ratio) {
236     return static_cast<int>(std::ceil((outCoord + 1) * ratio - 1e-3));
237 };
238 } // namespace
239
240 GAPI_FLUID_KERNEL(FResizeArea1Lpi, cv::gapi::core::GResize, false)
241 {
242     static const int Window = 1;
243     static const auto Kind = GFluidKernel::Kind::Resize;
244
245     static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
246                     cv::gapi::fluid::Buffer& out)
247
248     {
249         auto firstOutLineIdx = out.y();
250         auto firstViewLineIdx = in.y();
251         auto length = out.length();
252         double vRatio = (double)in.meta().size.height / out.meta().size.height;
253         double hRatio = (double)in.length() / length;
254
255         for (int l = 0; l < out.lpi(); l++)
256         {
257             int outY = firstOutLineIdx + l;
258             int startY = startInCoord(outY, vRatio);
259             int endY   = endInCoord  (outY, vRatio);
260
261             auto dst = out.OutLine<unsigned char>(l);
262
263             for (int x = 0; x < length; x++)
264             {
265                 float res = 0.0;
266
267                 int startX = startInCoord(x, hRatio);
268                 int endX   = endInCoord  (x, hRatio);
269
270                 for (int inY = startY; inY < endY; inY++)
271                 {
272                     double startCoordY = inY / vRatio;
273                     double endCoordY = startCoordY + 1/vRatio;
274
275                     if (startCoordY < outY) startCoordY = outY;
276                     if (endCoordY > outY + 1) endCoordY = outY + 1;
277
278                     float fracY = static_cast<float>((inY == startY || inY == endY - 1) ? endCoordY - startCoordY : 1/vRatio);
279
280                     const auto src = in.InLine <unsigned char>(inY - firstViewLineIdx);
281
282                     float rowSum = 0.0f;
283
284                     for (int inX = startX; inX < endX; inX++)
285                     {
286                         double startCoordX = inX / hRatio;
287                         double endCoordX = startCoordX + 1/hRatio;
288
289                         if (startCoordX < x) startCoordX = x;
290                         if (endCoordX > x + 1) endCoordX = x + 1;
291
292                         float fracX = static_cast<float>((inX == startX || inX == endX - 1) ? endCoordX - startCoordX : 1/hRatio);
293
294                         rowSum += src[inX] * fracX;
295                     }
296                     res += rowSum * fracY;
297                 }
298                 dst[x] = static_cast<unsigned char>(std::rint(res));
299             }
300         }
301     }
302 };
303
304 GAPI_FLUID_KERNEL(FResizeAreaUpscale1Lpi, cv::gapi::core::GResize, true)
305 {
306     static const int Window = 1;
307     static const auto Kind = GFluidKernel::Kind::Resize;
308
309     static void initScratch(const cv::GMatDesc& in,
310                             cv::Size outSz, double /*fx*/, double /*fy*/, int /*interp*/,
311                             cv::gapi::fluid::Buffer &scratch)
312     {
313         func::initScratch<areaUpscale::Mapper>(in, outSz, scratch);
314     }
315
316     static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
317     {}
318
319     static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
320                     cv::gapi::fluid::Buffer& out, cv::gapi::fluid::Buffer &scratch)
321     {
322         func::calcRow<areaUpscale::Mapper>(in, out, scratch);
323     }
324 };
325
326 #define ADD_RESIZE_KERNEL_WITH_LPI(interp, lpi, scratch)                                                                           \
327 struct Resize##interp##lpi##LpiHelper : public FResize##interp##1Lpi { static const int LPI = lpi; };                              \
328 struct FResize##interp##lpi##Lpi : public cv::GFluidKernelImpl<Resize##interp##lpi##LpiHelper, cv::gapi::core::GResize, scratch>{};
329
330 ADD_RESIZE_KERNEL_WITH_LPI(NN, 2, false)
331 ADD_RESIZE_KERNEL_WITH_LPI(NN, 3, false)
332 ADD_RESIZE_KERNEL_WITH_LPI(NN, 4, false)
333
334 ADD_RESIZE_KERNEL_WITH_LPI(Linear, 2, true)
335 ADD_RESIZE_KERNEL_WITH_LPI(Linear, 3, true)
336 ADD_RESIZE_KERNEL_WITH_LPI(Linear, 4, true)
337
338 ADD_RESIZE_KERNEL_WITH_LPI(Area, 2, false)
339 ADD_RESIZE_KERNEL_WITH_LPI(Area, 3, false)
340 ADD_RESIZE_KERNEL_WITH_LPI(Area, 4, false)
341
342 ADD_RESIZE_KERNEL_WITH_LPI(AreaUpscale, 2, true)
343 ADD_RESIZE_KERNEL_WITH_LPI(AreaUpscale, 3, true)
344 ADD_RESIZE_KERNEL_WITH_LPI(AreaUpscale, 4, true)
345 #undef ADD_RESIZE_KERNEL_WITH_LPI
346
347 static auto fluidResizeTestPackage = [](int interpolation, cv::Size szIn, cv::Size szOut, int lpi = 1)
348 {
349     using namespace cv;
350     using namespace cv::gapi;
351     bool upscale = szIn.width < szOut.width || szIn.height < szOut.height;
352
353 #define RESIZE_CASE(interp, lpi) \
354     case lpi: pkg = kernels<FCopy, FResize##interp##lpi##Lpi>(); break;
355
356 #define RESIZE_SWITCH(interp)   \
357     switch(lpi)                 \
358     {                           \
359     RESIZE_CASE(interp, 1)      \
360     RESIZE_CASE(interp, 2)      \
361     RESIZE_CASE(interp, 3)      \
362     RESIZE_CASE(interp, 4)      \
363     default: CV_Assert(false);  \
364     }
365
366     GKernelPackage pkg;
367     switch (interpolation)
368     {
369     case INTER_NEAREST: RESIZE_SWITCH(NN); break;
370     case INTER_LINEAR:  RESIZE_SWITCH(Linear); break;
371     case INTER_AREA:
372     {
373         if (upscale)
374         {
375             RESIZE_SWITCH(AreaUpscale)
376         }
377         else
378         {
379             RESIZE_SWITCH(Area);
380         }
381     }break;
382     default: CV_Assert(false);
383     }
384     return combine(pkg, fluidTestPackage, unite_policy::KEEP);
385
386 #undef RESIZE_SWITCH
387 #undef RESIZE_CASE
388 };
389
390 struct ResizeTestFluid : public TestWithParam<std::tuple<int, int, cv::Size, std::tuple<cv::Size, cv::Rect>, int, double>> {};
391 TEST_P(ResizeTestFluid, SanityTest)
392 {
393     int type = 0, interp = 0;
394     cv::Size sz_in, sz_out;
395     int lpi = 0;
396     double tolerance = 0.0;
397     cv::Rect outRoi;
398     std::tuple<cv::Size, cv::Rect> outSizeAndRoi;
399     std::tie(type, interp, sz_in, outSizeAndRoi, lpi, tolerance) = GetParam();
400     std::tie(sz_out, outRoi) = outSizeAndRoi;
401     if (outRoi == cv::Rect{}) outRoi = {0,0,sz_out.width,sz_out.height};
402     if (outRoi.width == 0) outRoi.width = sz_out.width;
403     double fx = 0, fy = 0;
404
405     cv::Mat in_mat1 (sz_in, type );
406     cv::Scalar mean = cv::Scalar(127);
407     cv::Scalar stddev = cv::Scalar(40.f);
408
409     cv::randn(in_mat1, mean, stddev);
410
411     cv::Mat out_mat = cv::Mat::zeros(sz_out, type);
412     cv::Mat out_mat_ocv = cv::Mat::zeros(sz_out, type);
413
414     cv::GMat in;
415     auto mid = TBlur3x3::on(in, cv::BORDER_REPLICATE, {});
416     auto out = cv::gapi::resize(mid, sz_out, fx, fy, interp);
417
418     cv::GComputation c(in, out);
419     c.apply(in_mat1, out_mat, cv::compile_args(GFluidOutputRois{{outRoi}}, fluidResizeTestPackage(interp, sz_in, sz_out, lpi)));
420
421     cv::Mat mid_mat;
422     cv::blur(in_mat1, mid_mat, {3,3}, {-1,-1},  cv::BORDER_REPLICATE);
423     cv::resize(mid_mat, out_mat_ocv, sz_out, fx, fy, interp);
424
425     cv::Mat absDiff;
426     cv::absdiff(out_mat(outRoi), out_mat_ocv(outRoi), absDiff);
427     EXPECT_EQ(0, cv::countNonZero(absDiff > tolerance));
428 }
429
430 INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTestFluid,
431                         Combine(Values(CV_8UC1),
432                                 Values(cv::INTER_NEAREST, cv::INTER_LINEAR),
433                                 Values(cv::Size(8, 7),
434                                        cv::Size(8, 8),
435                                        cv::Size(8, 64),
436                                        cv::Size(8, 25),
437                                        cv::Size(16, 8),
438                                        cv::Size(16, 7)),
439                                 Values(std::make_tuple(cv::Size(5, 4), cv::Rect{}),
440                                        std::make_tuple(cv::Size(5, 4), cv::Rect{0, 0, 0, 2}),
441                                        std::make_tuple(cv::Size(5, 4), cv::Rect{0, 1, 0, 2}),
442                                        std::make_tuple(cv::Size(5, 4), cv::Rect{0, 2, 0, 2}),
443                                        std::make_tuple(cv::Size(7, 7), cv::Rect{}),
444                                        std::make_tuple(cv::Size(7, 7), cv::Rect{0, 0, 0, 3}),
445                                        std::make_tuple(cv::Size(7, 7), cv::Rect{0, 2, 0, 2}),
446                                        std::make_tuple(cv::Size(7, 7), cv::Rect{0, 4, 0, 3}),
447                                        std::make_tuple(cv::Size(8, 4), cv::Rect{}),
448                                        std::make_tuple(cv::Size(8, 4), cv::Rect{0, 0, 0, 3}),
449                                        std::make_tuple(cv::Size(8, 4), cv::Rect{0, 1, 0, 2}),
450                                        std::make_tuple(cv::Size(8, 4), cv::Rect{0, 3, 0, 1})),
451                                 Values(1, 2, 3, 4), // lpi
452                                 Values(0.0)));
453
454 INSTANTIATE_TEST_CASE_P(ResizeAreaTestCPU, ResizeTestFluid,
455                         Combine(Values(CV_8UC1),
456                                 Values(cv::INTER_AREA),
457                                 Values(cv::Size(8, 7),
458                                        cv::Size(8, 8),
459                                        cv::Size(8, 64),
460                                        cv::Size(8, 25),
461                                        cv::Size(16, 8),
462                                        cv::Size(16, 7)),
463                                 Values(std::make_tuple(cv::Size(5, 4), cv::Rect{}),
464                                        std::make_tuple(cv::Size(5, 4), cv::Rect{0, 0, 0, 2}),
465                                        std::make_tuple(cv::Size(5, 4), cv::Rect{0, 1, 0, 2}),
466                                        std::make_tuple(cv::Size(5, 4), cv::Rect{0, 2, 0, 2}),
467                                        std::make_tuple(cv::Size(7, 7), cv::Rect{}),
468                                        std::make_tuple(cv::Size(7, 7), cv::Rect{0, 0, 0, 3}),
469                                        std::make_tuple(cv::Size(7, 7), cv::Rect{0, 2, 0, 2}),
470                                        std::make_tuple(cv::Size(7, 7), cv::Rect{0, 4, 0, 3}),
471                                        std::make_tuple(cv::Size(8, 4), cv::Rect{}),
472                                        std::make_tuple(cv::Size(8, 4), cv::Rect{0, 0, 0, 3}),
473                                        std::make_tuple(cv::Size(8, 4), cv::Rect{0, 1, 0, 2}),
474                                        std::make_tuple(cv::Size(8, 4), cv::Rect{0, 3, 0, 1})),
475                                 Values(1, 2, 3, 4), // lpi
476                                 // Actually this tolerance only for cases where OpenCV
477                                 // uses ResizeAreaFast
478                                 Values(1.0)));
479
480 INSTANTIATE_TEST_CASE_P(ResizeUpscaleTestCPU, ResizeTestFluid,
481                         Combine(Values(CV_8UC1),
482                                 Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
483                                 Values(cv::Size(1, 5),
484                                        cv::Size(3, 5),
485                                        cv::Size(7, 5),
486                                        cv::Size(1, 7),
487                                        cv::Size(3, 7),
488                                        cv::Size(7, 7)),
489                                 Values(std::make_tuple(cv::Size(8, 8), cv::Rect{0,0,8,2}),
490                                        std::make_tuple(cv::Size(8, 8), cv::Rect{0,2,8,2}),
491                                        std::make_tuple(cv::Size(8, 8), cv::Rect{0,4,8,2}),
492                                        std::make_tuple(cv::Size(8, 8), cv::Rect{0,6,8,2}),
493                                        std::make_tuple(cv::Size(8, 8), cv::Rect{0,0,8,8}),
494                                        std::make_tuple(cv::Size(16, 8), cv::Rect{}),
495                                        std::make_tuple(cv::Size(16, 64), cv::Rect{0, 0,16,16}),
496                                        std::make_tuple(cv::Size(16, 64), cv::Rect{0,16,16,16}),
497                                        std::make_tuple(cv::Size(16, 64), cv::Rect{0,32,16,16}),
498                                        std::make_tuple(cv::Size(16, 64), cv::Rect{0,48,16,16}),
499                                        std::make_tuple(cv::Size(16, 64), cv::Rect{0, 0,16,64}),
500                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0, 0,16, 7}),
501                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0, 7,16, 6}),
502                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0,13,16, 6}),
503                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0,19,16, 6}),
504                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0, 0,16, 7}),
505                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0, 7,16, 7}),
506                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0,14,16, 7}),
507                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0,21,16, 4}),
508                                        std::make_tuple(cv::Size(16, 25), cv::Rect{0, 0,16,25}),
509                                        std::make_tuple(cv::Size(16, 7), cv::Rect{}),
510                                        std::make_tuple(cv::Size(16, 8), cv::Rect{})),
511                                 Values(1, 2, 3, 4), // lpi
512                                 Values(0.0)));
513
514 INSTANTIATE_TEST_CASE_P(ResizeUpscaleOneDimDownscaleAnother, ResizeTestFluid,
515                         Combine(Values(CV_8UC1),
516                                 Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
517                                 Values(cv::Size(6, 6),
518                                        cv::Size(8, 7),
519                                        cv::Size(8, 8),
520                                        cv::Size(8, 10),
521                                        cv::Size(10, 8),
522                                        cv::Size(10, 7)),
523                                 Values(std::make_tuple(cv::Size(11, 5), cv::Rect{}),
524                                        std::make_tuple(cv::Size(11, 5), cv::Rect{0, 0, 0, 2}),
525                                        std::make_tuple(cv::Size(11, 5), cv::Rect{0, 2, 0, 2}),
526                                        std::make_tuple(cv::Size(11, 5), cv::Rect{0, 4, 0, 1}),
527                                        std::make_tuple(cv::Size(12, 2), cv::Rect{}),
528                                        std::make_tuple(cv::Size(12, 2), cv::Rect{0, 0, 0, 1}),
529                                        std::make_tuple(cv::Size(12, 2), cv::Rect{0, 1, 0, 1}),
530                                        std::make_tuple(cv::Size(23, 3), cv::Rect{}),
531                                        std::make_tuple(cv::Size(23, 3), cv::Rect{0, 0, 0, 1}),
532                                        std::make_tuple(cv::Size(23, 3), cv::Rect{0, 1, 0, 1}),
533                                        std::make_tuple(cv::Size(23, 3), cv::Rect{0, 2, 0, 1}),
534                                        std::make_tuple(cv::Size(3, 24), cv::Rect{}),
535                                        std::make_tuple(cv::Size(3, 24), cv::Rect{0,  0, 0, 6}),
536                                        std::make_tuple(cv::Size(3, 24), cv::Rect{0,  6, 0, 6}),
537                                        std::make_tuple(cv::Size(3, 24), cv::Rect{0, 12, 0, 6}),
538                                        std::make_tuple(cv::Size(3, 24), cv::Rect{0, 18, 0, 6}),
539                                        std::make_tuple(cv::Size(5, 11), cv::Rect{}),
540                                        std::make_tuple(cv::Size(5, 11), cv::Rect{0, 0, 0, 3}),
541                                        std::make_tuple(cv::Size(5, 11), cv::Rect{0, 3, 0, 3}),
542                                        std::make_tuple(cv::Size(5, 11), cv::Rect{0, 6, 0, 3}),
543                                        std::make_tuple(cv::Size(5, 11), cv::Rect{0, 9, 0, 2})),
544                                 Values(1, 2, 3, 4), // lpi
545                                 Values(0.0)));
546
547 INSTANTIATE_TEST_CASE_P(Resize400_384TestCPU, ResizeTestFluid,
548                         Combine(Values(CV_8UC1),
549                                 Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
550                                 Values(cv::Size(128, 400)),
551                                 Values(std::make_tuple(cv::Size(128, 384), cv::Rect{})),
552                                 Values(1, 2, 3, 4), // lpi
553                                 Values(0.0)));
554
555 INSTANTIATE_TEST_CASE_P(Resize220_400TestCPU, ResizeTestFluid,
556                         Combine(Values(CV_8UC1),
557                                 Values(cv::INTER_LINEAR),
558                                 Values(cv::Size(220, 220)),
559                                 Values(std::make_tuple(cv::Size(400, 400), cv::Rect{})),
560                                 Values(1, 2, 3, 4), // lpi
561                                 Values(0.0)));
562
563 static auto cvBlur = [](const cv::Mat& in, cv::Mat& out, int kernelSize)
564 {
565     if (kernelSize == 1)
566     {
567         out = in;
568     }
569     else
570     {
571         cv::blur(in, out, {kernelSize, kernelSize});
572     }
573 };
574
575 using SizesWithRois = std::tuple<cv::Size, cv::Rect, cv::Size, cv::Rect>;
576 struct ResizeAndAnotherReaderTest : public TestWithParam<std::tuple<int, int, bool, SizesWithRois>>{};
577 TEST_P(ResizeAndAnotherReaderTest, SanityTest)
578 {
579     bool readFromInput = false;
580     int interp = -1, kernelSize = -1;
581     SizesWithRois sizesWithRois;
582     std::tie(interp, kernelSize, readFromInput, sizesWithRois) = GetParam();
583
584     cv::Size sz,  resizedSz;
585     cv::Rect roi, resizedRoi;
586     std::tie(sz, roi, resizedSz, resizedRoi) = sizesWithRois;
587
588     cv::Mat in_mat(sz, CV_8UC1);
589     cv::Scalar mean = cv::Scalar(127);
590     cv::Scalar stddev = cv::Scalar(40.f);
591     cv::randn(in_mat, mean, stddev);
592
593     cv::Mat gapi_resize_out = cv::Mat::zeros(resizedSz, CV_8UC1);
594     cv::Mat gapi_blur_out = cv::Mat::zeros(sz, CV_8UC1);
595
596     auto blur = kernelSize == 1 ? &TBlur1x1::on : kernelSize == 3 ? &TBlur3x3::on : &TBlur5x5::on;
597
598     cv::GMat in, resize_out, blur_out;
599
600     if (readFromInput)
601     {
602         resize_out = gapi::resize(in, resizedSz, 0, 0, interp);
603         blur_out   = blur(in, cv::BORDER_DEFAULT, {});
604     }
605     else
606     {
607         auto mid   = TCopy::on(in);
608         resize_out = gapi::resize(mid, resizedSz, 0, 0, interp);
609         blur_out   = blur(mid, cv::BORDER_DEFAULT, {});
610     }
611
612     cv::GComputation c(GIn(in), GOut(resize_out, blur_out));
613     c.apply(gin(in_mat), gout(gapi_resize_out, gapi_blur_out), cv::compile_args(GFluidOutputRois{{resizedRoi, roi}},
614                                                                                 fluidResizeTestPackage(interp, sz, resizedSz)));
615
616     cv::Mat ocv_resize_out = cv::Mat::zeros(resizedSz, CV_8UC1);
617     cv::resize(in_mat, ocv_resize_out, resizedSz, 0, 0, interp);
618     cv::Mat ocv_blur_out = cv::Mat::zeros(sz, CV_8UC1);
619     cvBlur(in_mat, ocv_blur_out, kernelSize);
620
621     EXPECT_EQ(0, cv::countNonZero(gapi_resize_out(resizedRoi) != ocv_resize_out(resizedRoi)));
622     EXPECT_EQ(0, cv::countNonZero(gapi_blur_out(roi) != ocv_blur_out(roi)));
623 }
624
625 INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeAndAnotherReaderTest,
626                         Combine(Values(cv::INTER_NEAREST, cv::INTER_LINEAR),
627                                 Values(1, 3, 5),
628                                 testing::Bool(), // Read from input directly or place a copy node at start
629                                 Values(std::make_tuple(cv::Size{8,8}, cv::Rect{0,0,8,8},
630                                                        cv::Size{4,4}, cv::Rect{0,0,4,4}),
631                                        std::make_tuple(cv::Size{8,8}, cv::Rect{0,0,8,2},
632                                                        cv::Size{4,4}, cv::Rect{0,0,4,1}),
633                                        std::make_tuple(cv::Size{8,8}, cv::Rect{0,2,8,4},
634                                                        cv::Size{4,4}, cv::Rect{0,1,4,2}),
635                                        std::make_tuple(cv::Size{8,8}, cv::Rect{0,4,8,4},
636                                                        cv::Size{4,4}, cv::Rect{0,2,4,2}),
637                                        std::make_tuple(cv::Size{64,64}, cv::Rect{0, 0,64,64},
638                                                        cv::Size{49,49}, cv::Rect{0, 0,49,49}),
639                                        std::make_tuple(cv::Size{64,64}, cv::Rect{0, 0,64,15},
640                                                        cv::Size{49,49}, cv::Rect{0, 0,49,11}),
641                                        std::make_tuple(cv::Size{64,64}, cv::Rect{0,11,64,23},
642                                                        cv::Size{49,49}, cv::Rect{0, 9,49,17}),
643                                        std::make_tuple(cv::Size{64,64}, cv::Rect{0,50,64,14},
644                                                        cv::Size{49,49}, cv::Rect{0,39,49,10}))));
645
646 struct BlursAfterResizeTest : public TestWithParam<std::tuple<int, int, int, bool, std::tuple<cv::Size, cv::Size, cv::Rect>>>{};
647 TEST_P(BlursAfterResizeTest, SanityTest)
648 {
649     bool readFromInput = false;
650     int interp = -1, kernelSize1 = -1, kernelSize2 = -1;
651     std::tuple<cv::Size, cv::Size, cv::Rect> sizesWithRoi;
652     std::tie(interp, kernelSize1, kernelSize2, readFromInput, sizesWithRoi) = GetParam();
653
654     cv::Size inSz,  outSz;
655     cv::Rect outRoi;
656     std::tie(inSz, outSz, outRoi) = sizesWithRoi;
657
658     cv::Mat in_mat(inSz, CV_8UC1);
659     cv::Scalar mean = cv::Scalar(127);
660     cv::Scalar stddev = cv::Scalar(40.f);
661     cv::randn(in_mat, mean, stddev);
662     cv::Mat gapi_out1 = cv::Mat::zeros(outSz, CV_8UC1);
663     cv::Mat gapi_out2 = cv::Mat::zeros(outSz, CV_8UC1);
664
665     auto blur1 = kernelSize1 == 1 ? &TBlur1x1::on : kernelSize1 == 3 ? &TBlur3x3::on : &TBlur5x5::on;
666     auto blur2 = kernelSize2 == 1 ? &TBlur1x1::on : kernelSize2 == 3 ? &TBlur3x3::on : &TBlur5x5::on;
667
668     cv::GMat in, out1, out2;
669     if (readFromInput)
670     {
671         auto resized = gapi::resize(in, outSz, 0, 0, interp);
672         out1 = blur1(resized, cv::BORDER_DEFAULT, {});
673         out2 = blur2(resized, cv::BORDER_DEFAULT, {});
674     }
675     else
676     {
677         auto mid = TCopy::on(in);
678         auto resized = gapi::resize(mid, outSz, 0, 0, interp);
679         out1 = blur1(resized, cv::BORDER_DEFAULT, {});
680         out2 = blur2(resized, cv::BORDER_DEFAULT, {});
681     }
682
683     cv::GComputation c(GIn(in), GOut(out1, out2));
684     c.apply(gin(in_mat), gout(gapi_out1, gapi_out2), cv::compile_args(GFluidOutputRois{{outRoi, outRoi}},
685                                                                       fluidResizeTestPackage(interp, inSz, outSz)));
686
687     cv::Mat ocv_out1 = cv::Mat::zeros(outSz, CV_8UC1);
688     cv::Mat ocv_out2 = cv::Mat::zeros(outSz, CV_8UC1);
689     cv::Mat resized = cv::Mat::zeros(outSz, CV_8UC1);
690     cv::resize(in_mat, resized, outSz, 0, 0, interp);
691     cvBlur(resized, ocv_out1, kernelSize1);
692     cvBlur(resized, ocv_out2, kernelSize2);
693
694     EXPECT_EQ(0, cv::countNonZero(gapi_out1(outRoi) != ocv_out1(outRoi)));
695     EXPECT_EQ(0, cv::countNonZero(gapi_out2(outRoi) != ocv_out2(outRoi)));
696 }
697
698 INSTANTIATE_TEST_CASE_P(ResizeTestCPU, BlursAfterResizeTest,
699                         Combine(Values(cv::INTER_NEAREST, cv::INTER_LINEAR),
700                                 Values(1, 3, 5),
701                                 Values(1, 3, 5),
702                                 testing::Bool(), // Read from input directly or place a copy node at start
703                                 Values(std::make_tuple(cv::Size{8,8},
704                                                        cv::Size{4,4}, cv::Rect{0,0,4,4}),
705                                        std::make_tuple(cv::Size{8,8},
706                                                        cv::Size{4,4}, cv::Rect{0,0,4,1}),
707                                        std::make_tuple(cv::Size{8,8},
708                                                        cv::Size{4,4}, cv::Rect{0,1,4,2}),
709                                        std::make_tuple(cv::Size{8,8},
710                                                        cv::Size{4,4}, cv::Rect{0,2,4,2}),
711                                        std::make_tuple(cv::Size{64,64},
712                                                        cv::Size{49,49}, cv::Rect{0, 0,49,49}),
713                                        std::make_tuple(cv::Size{64,64},
714                                                        cv::Size{49,49}, cv::Rect{0, 0,49,11}),
715                                        std::make_tuple(cv::Size{64,64},
716                                                        cv::Size{49,49}, cv::Rect{0, 9,49,17}),
717                                        std::make_tuple(cv::Size{64,64},
718                                                        cv::Size{49,49}, cv::Rect{0,39,49,10}))));
719
720 } // namespace opencv_test