gapi_array_tests.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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 <vector>
  8. #include <ade/util/algorithm.hpp>
  9. namespace opencv_test
  10. {
  11. namespace ThisTest
  12. {
  13. using GPointArray = cv::GArray<cv::Point>;
  14. G_TYPED_KERNEL(GeneratePoints, <GPointArray(GMat)>, "test.array.out_const")
  15. {
  16. static GArrayDesc outMeta(const GMatDesc&) { return empty_array_desc(); }
  17. };
  18. G_TYPED_KERNEL(FindCorners, <GPointArray(GMat)>, "test.array.out")
  19. {
  20. static GArrayDesc outMeta(const GMatDesc&) { return empty_array_desc(); }
  21. };
  22. G_TYPED_KERNEL(CountCorners, <GScalar(GPointArray)>, "test.array.in")
  23. {
  24. static GScalarDesc outMeta(const GArrayDesc &) { return empty_scalar_desc(); }
  25. };
  26. G_TYPED_KERNEL(PointIncrement, <GPointArray(GMat, GPointArray)>, "test.point_increment")
  27. {
  28. static GArrayDesc outMeta(const GMatDesc&, const GArrayDesc&) { return empty_array_desc(); }
  29. };
  30. G_TYPED_KERNEL(CountContours, <GOpaque<size_t>(GArray<GPointArray>)>, "test.array.array.in")
  31. {
  32. static GOpaqueDesc outMeta(const GArrayDesc&) { return empty_gopaque_desc(); }
  33. };
  34. } // namespace ThisTest
  35. namespace
  36. {
  37. GAPI_OCV_KERNEL(OCVGeneratePoints, ThisTest::GeneratePoints)
  38. {
  39. static void run(cv::Mat, std::vector<cv::Point> &out)
  40. {
  41. for (int i = 0; i < 10; i++)
  42. out.emplace_back(i, i);
  43. }
  44. };
  45. GAPI_OCV_KERNEL(OCVFindCorners, ThisTest::FindCorners)
  46. {
  47. static void run(cv::Mat in, std::vector<cv::Point> &out)
  48. {
  49. cv::goodFeaturesToTrack(in, out, 1024, 0.01, 3);
  50. }
  51. };
  52. GAPI_OCV_KERNEL(OCVCountCorners, ThisTest::CountCorners)
  53. {
  54. static void run(const std::vector<cv::Point> &in, cv::Scalar &out)
  55. {
  56. out[0] = static_cast<double>(in.size());
  57. }
  58. };
  59. GAPI_OCV_KERNEL(OCVPointIncrement, ThisTest::PointIncrement)
  60. {
  61. static void run(const cv::Mat&, const std::vector<cv::Point>& in, std::vector<cv::Point>& out)
  62. {
  63. for (const auto& el : in)
  64. out.emplace_back(el + Point(1,1));
  65. }
  66. };
  67. GAPI_OCV_KERNEL(OCVCountContours, ThisTest::CountContours)
  68. {
  69. static void run(const std::vector<std::vector<cv::Point>> &contours, size_t &out)
  70. {
  71. out = contours.size();
  72. }
  73. };
  74. cv::Mat cross(int w, int h)
  75. {
  76. cv::Mat mat = cv::Mat::eye(h, w, CV_8UC1)*255;
  77. cv::Mat yee;
  78. cv::flip(mat, yee, 0); // X-axis
  79. mat |= yee; // make an "X" matrix;
  80. return mat;
  81. }
  82. } // (anonymous namespace)
  83. TEST(GArray, TestReturnValue)
  84. {
  85. // FIXME: Make .apply() able to take compile arguments
  86. cv::GComputationT<ThisTest::GPointArray(cv::GMat)> c(ThisTest::FindCorners::on);
  87. auto cc = c.compile(cv::GMatDesc{CV_8U,1,{32,32}},
  88. cv::compile_args(cv::gapi::kernels<OCVFindCorners>()));
  89. // Prepare input matrix
  90. cv::Mat input = cross(32, 32);
  91. std::vector<cv::Point> points;
  92. cc(input, points);
  93. // OCV goodFeaturesToTrack should find 5 points here (with these settings)
  94. EXPECT_EQ(5u, points.size());
  95. EXPECT_TRUE(ade::util::find(points, cv::Point(16,16)) != points.end());
  96. EXPECT_TRUE(ade::util::find(points, cv::Point(30,30)) != points.end());
  97. EXPECT_TRUE(ade::util::find(points, cv::Point( 1,30)) != points.end());
  98. EXPECT_TRUE(ade::util::find(points, cv::Point(30, 1)) != points.end());
  99. EXPECT_TRUE(ade::util::find(points, cv::Point( 1, 1)) != points.end());
  100. }
  101. TEST(GArray, TestInputArg)
  102. {
  103. cv::GComputationT<cv::GScalar(ThisTest::GPointArray)> c(ThisTest::CountCorners::on);
  104. auto cc = c.compile(cv::empty_array_desc(),
  105. cv::compile_args(cv::gapi::kernels<OCVCountCorners>()));
  106. const std::vector<cv::Point> arr = {cv::Point(1,1), cv::Point(2,2)};
  107. cv::Scalar out;
  108. cc(arr, out);
  109. EXPECT_EQ(2, out[0]);
  110. }
  111. TEST(GArray, TestPipeline)
  112. {
  113. cv::GComputationT<cv::GScalar(cv::GMat)> c([](cv::GMat in)
  114. {
  115. return ThisTest::CountCorners::on(ThisTest::FindCorners::on(in));
  116. });
  117. auto cc = c.compile(cv::GMatDesc{CV_8U,1,{32,32}},
  118. cv::compile_args(cv::gapi::kernels<OCVFindCorners, OCVCountCorners>()));
  119. cv::Mat input = cross(32, 32);
  120. cv::Scalar out;
  121. cc(input, out);
  122. EXPECT_EQ(5, out[0]);
  123. }
  124. TEST(GArray, NoAggregationBetweenRuns)
  125. {
  126. cv::GComputationT<cv::GScalar(cv::GMat)> c([](cv::GMat in)
  127. {
  128. return ThisTest::CountCorners::on(ThisTest::GeneratePoints::on(in));
  129. });
  130. auto cc = c.compile(cv::GMatDesc{CV_8U,1,{32,32}},
  131. cv::compile_args(cv::gapi::kernels<OCVGeneratePoints, OCVCountCorners>()));
  132. cv::Mat input = cv::Mat::eye(32, 32, CV_8UC1);
  133. cv::Scalar out;
  134. cc(input, out);
  135. EXPECT_EQ(10, out[0]);
  136. // Last kernel in the graph counts number of elements in array, returned by the previous kernel
  137. // (in this test, this variable is constant).
  138. // After 10 executions, this number MUST remain the same - 1st kernel is adding new values on every
  139. // run, but it is graph's responsibility to reset internal object state.
  140. cv::Scalar out2;
  141. for (int i = 0; i < 10; i++)
  142. {
  143. cc(input, out2);
  144. }
  145. EXPECT_EQ(10, out2[0]);
  146. }
  147. TEST(GArray, TestIntermediateOutput)
  148. {
  149. using Result = std::tuple<ThisTest::GPointArray, cv::GScalar>;
  150. cv::GComputationT<Result(cv::GMat)> c([](cv::GMat in)
  151. {
  152. auto corners = ThisTest::GeneratePoints::on(in);
  153. return std::make_tuple(corners, ThisTest::CountCorners::on(corners));
  154. });
  155. cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
  156. std::vector<cv::Point> out_points;
  157. cv::Scalar out_count;
  158. auto cc = c.compile(cv::descr_of(in_mat),
  159. cv::compile_args(cv::gapi::kernels<OCVGeneratePoints, OCVCountCorners>()));
  160. cc(in_mat, out_points, out_count);
  161. EXPECT_EQ(10u, out_points.size());
  162. EXPECT_EQ(10, out_count[0]);
  163. }
  164. TEST(GArray, TestGArrayGArrayKernelInput)
  165. {
  166. cv::GMat in;
  167. auto contours = cv::gapi::findContours(in, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
  168. auto out = ThisTest::CountContours::on(contours);
  169. cv::GComputation c(GIn(in), GOut(out));
  170. // Create input - two filled rectangles
  171. cv::Mat in_mat = cv::Mat::zeros(50, 50, CV_8UC1);
  172. cv::rectangle(in_mat, cv::Point{5,5}, cv::Point{20,20}, 255, cv::FILLED);
  173. cv::rectangle(in_mat, cv::Point{25,25}, cv::Point{40,40}, 255, cv::FILLED);
  174. size_t out_count = 0u;
  175. c.apply(gin(in_mat), gout(out_count), cv::compile_args(cv::gapi::kernels<OCVCountContours>()));
  176. EXPECT_EQ(2u, out_count) << "Two contours must be found";
  177. }
  178. TEST(GArray, GArrayConstValInitialization)
  179. {
  180. std::vector<cv::Point> initial_vec {Point(0,0), Point(1,1), Point(2,2)};
  181. std::vector<cv::Point> ref_vec {Point(1,1), Point(2,2), Point(3,3)};
  182. std::vector<cv::Point> out_vec;
  183. cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
  184. cv::GComputationT<ThisTest::GPointArray(cv::GMat)> c([&](cv::GMat in)
  185. {
  186. // Initialization
  187. ThisTest::GPointArray test_garray(initial_vec);
  188. return ThisTest::PointIncrement::on(in, test_garray);
  189. });
  190. auto cc = c.compile(cv::descr_of(in_mat),
  191. cv::compile_args(cv::gapi::kernels<OCVPointIncrement>()));
  192. cc(in_mat, out_vec);
  193. EXPECT_EQ(ref_vec, out_vec);
  194. }
  195. TEST(GArray, GArrayRValInitialization)
  196. {
  197. std::vector<cv::Point> ref_vec {Point(1,1), Point(2,2), Point(3,3)};
  198. std::vector<cv::Point> out_vec;
  199. cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
  200. cv::GComputationT<ThisTest::GPointArray(cv::GMat)> c([&](cv::GMat in)
  201. {
  202. // Rvalue initialization
  203. ThisTest::GPointArray test_garray({Point(0,0), Point(1,1), Point(2,2)});
  204. return ThisTest::PointIncrement::on(in, test_garray);
  205. });
  206. auto cc = c.compile(cv::descr_of(in_mat),
  207. cv::compile_args(cv::gapi::kernels<OCVPointIncrement>()));
  208. cc(in_mat, out_vec);
  209. EXPECT_EQ(ref_vec, out_vec);
  210. }
  211. TEST(GArray_VectorRef, TestMov)
  212. {
  213. // Warning: this test is testing some not-very-public APIs
  214. // Test how VectorRef's mov() (aka poor man's move()) is working.
  215. using I = int;
  216. using V = std::vector<I>;
  217. const V vgold = { 1, 2, 3};
  218. V vtest = vgold;
  219. const I* vptr = vtest.data();
  220. cv::detail::VectorRef vref(vtest);
  221. cv::detail::VectorRef vmov;
  222. vmov.reset<I>();
  223. EXPECT_EQ(vgold, vref.rref<I>());
  224. vmov.mov(vref);
  225. EXPECT_EQ(vgold, vmov.rref<I>());
  226. EXPECT_EQ(vptr, vmov.rref<I>().data());
  227. EXPECT_EQ(V{}, vref.rref<I>());
  228. EXPECT_EQ(V{}, vtest);
  229. }
  230. // types from anonymous namespace doesn't work well with templates
  231. inline namespace gapi_array_tests {
  232. struct MyTestStruct {
  233. int i;
  234. float f;
  235. std::string name;
  236. };
  237. }
  238. TEST(GArray_VectorRef, Kind)
  239. {
  240. cv::detail::VectorRef v1(std::vector<cv::Rect>{});
  241. EXPECT_EQ(cv::detail::OpaqueKind::CV_RECT, v1.getKind());
  242. cv::detail::VectorRef v2(std::vector<cv::Mat>{});
  243. EXPECT_EQ(cv::detail::OpaqueKind::CV_MAT, v2.getKind());
  244. cv::detail::VectorRef v3(std::vector<int>{});
  245. EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, v3.getKind());
  246. cv::detail::VectorRef v4(std::vector<double>{});
  247. EXPECT_EQ(cv::detail::OpaqueKind::CV_DOUBLE, v4.getKind());
  248. cv::detail::VectorRef v5(std::vector<cv::Scalar>{});
  249. EXPECT_EQ(cv::detail::OpaqueKind::CV_SCALAR, v5.getKind());
  250. cv::detail::VectorRef v6(std::vector<cv::Point>{});
  251. EXPECT_EQ(cv::detail::OpaqueKind::CV_POINT, v6.getKind());
  252. cv::detail::VectorRef v7(std::vector<cv::Size>{});
  253. EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind());
  254. cv::detail::VectorRef v8(std::vector<std::string>{});
  255. EXPECT_EQ(cv::detail::OpaqueKind::CV_STRING, v8.getKind());
  256. cv::detail::VectorRef v9(std::vector<MyTestStruct>{});
  257. EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v9.getKind());
  258. }
  259. TEST(GArray_VectorRef, TestRvalue)
  260. {
  261. // Warning: this test is testing some not-very-public APIs
  262. cv::detail::VectorRef vref(std::vector<int>{3, 5, -4});
  263. auto v = std::vector<int>{3, 5, -4};
  264. EXPECT_EQ(vref.rref<int>(), v);
  265. }
  266. TEST(GArray_VectorRef, TestReset)
  267. {
  268. // Warning: this test is testing some not-very-public APIs
  269. cv::detail::VectorRef vref(std::vector<int>{3, 5, -4});
  270. EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, vref.getKind());
  271. vref.reset<int>();
  272. EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, vref.getKind());
  273. }
  274. } // namespace opencv_test