gapi_fluid_resize_test.cpp 38 KB

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