gapi_tests_common.hpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  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-2020 Intel Corporation
  6. #ifndef OPENCV_GAPI_TESTS_COMMON_HPP
  7. #define OPENCV_GAPI_TESTS_COMMON_HPP
  8. #include <iostream>
  9. #include <tuple>
  10. #include <type_traits>
  11. #include <time.h>
  12. #include <opencv2/ts.hpp>
  13. #include <opencv2/gapi.hpp>
  14. #include <opencv2/gapi/util/util.hpp>
  15. #include "gapi_tests_helpers.hpp"
  16. #include <opencv2/gapi/render/render.hpp>
  17. namespace
  18. {
  19. inline std::ostream& operator<<(std::ostream& o, const cv::GCompileArg& arg)
  20. {
  21. return o << (arg.tag.empty() ? "empty" : arg.tag);
  22. }
  23. inline std::ostream& operator<<(std::ostream& o, const cv::gapi::wip::draw::Prim& p)
  24. {
  25. using namespace cv::gapi::wip::draw;
  26. switch (p.index())
  27. {
  28. case Prim::index_of<Rect>():
  29. o << "cv::gapi::draw::Rect";
  30. break;
  31. case Prim::index_of<Text>():
  32. o << "cv::gapi::draw::Text";
  33. break;
  34. case Prim::index_of<Circle>():
  35. o << "cv::gapi::draw::Circle";
  36. break;
  37. case Prim::index_of<Line>():
  38. o << "cv::gapi::draw::Line";
  39. break;
  40. case Prim::index_of<Mosaic>():
  41. o << "cv::gapi::draw::Mosaic";
  42. break;
  43. case Prim::index_of<Image>():
  44. o << "cv::gapi::draw::Image";
  45. break;
  46. case Prim::index_of<Poly>():
  47. o << "cv::gapi::draw::Poly";
  48. break;
  49. default: o << "Unrecognized primitive";
  50. }
  51. return o;
  52. }
  53. template <typename T> inline void initPointRandU(cv::RNG &rng, cv::Point_<T>& pt)
  54. {
  55. GAPI_Assert(std::is_integral<T>::value);
  56. pt = cv::Point_<T>(static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))),
  57. static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))));
  58. }
  59. template <typename T> inline void initPointRandU(cv::RNG &rng, cv::Point3_<T>& pt)
  60. {
  61. GAPI_Assert(std::is_integral<T>::value);
  62. pt = cv::Point3_<T>(static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))),
  63. static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))),
  64. static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))));
  65. }
  66. template <typename F> inline void initFloatPointRandU(cv::RNG &rng, cv::Point_<F> &pt)
  67. {
  68. GAPI_Assert(std::is_floating_point<F>::value);
  69. static const int fscale = 256; // avoid bits near ULP, generate stable test input
  70. pt = cv::Point_<F>(rng.uniform(0, 255 * fscale) / static_cast<F>(fscale),
  71. rng.uniform(0, 255 * fscale) / static_cast<F>(fscale));
  72. }
  73. template<> inline void initPointRandU(cv::RNG &rng, cv::Point2f &pt)
  74. { initFloatPointRandU(rng, pt); }
  75. template<> inline void initPointRandU(cv::RNG &rng, cv::Point2d &pt)
  76. { initFloatPointRandU(rng, pt); }
  77. template <typename F> inline void initFloatPointRandU(cv::RNG &rng, cv::Point3_<F> &pt)
  78. {
  79. GAPI_Assert(std::is_floating_point<F>::value);
  80. static const int fscale = 256; // avoid bits near ULP, generate stable test input
  81. pt = cv::Point3_<F>(rng.uniform(0, 255 * fscale) / static_cast<F>(fscale),
  82. rng.uniform(0, 255 * fscale) / static_cast<F>(fscale),
  83. rng.uniform(0, 255 * fscale) / static_cast<F>(fscale));
  84. }
  85. template<> inline void initPointRandU(cv::RNG &rng, cv::Point3f &pt)
  86. { initFloatPointRandU(rng, pt); }
  87. template<> inline void initPointRandU(cv::RNG &rng, cv::Point3d &pt)
  88. { initFloatPointRandU(rng, pt); }
  89. } // namespace
  90. namespace opencv_test
  91. {
  92. class TestFunctional
  93. {
  94. public:
  95. cv::Mat in_mat1;
  96. cv::Mat in_mat2;
  97. cv::Mat out_mat_gapi;
  98. cv::Mat out_mat_ocv;
  99. cv::Scalar sc;
  100. // integral Scalar initialization
  101. cv::Scalar initScalarRandU(unsigned upper)
  102. {
  103. cv::RNG rng(time(nullptr));
  104. double s1 = rng(upper);
  105. double s2 = rng(upper);
  106. double s3 = rng(upper);
  107. double s4 = rng(upper);
  108. return cv::Scalar(s1, s2, s3, s4);
  109. }
  110. // floating-point Scalar initialization (cv::core)
  111. cv::Scalar initScalarRandU()
  112. {
  113. cv::RNG rng(time(nullptr));
  114. double s1 = exp(rng.uniform(-1, 6) * 3.0 * CV_LOG2) * (rng.uniform(0, 2) ? 1. : -1.);
  115. double s2 = exp(rng.uniform(-1, 6) * 3.0 * CV_LOG2) * (rng.uniform(0, 2) ? 1. : -1.);
  116. double s3 = exp(rng.uniform(-1, 6) * 3.0 * CV_LOG2) * (rng.uniform(0, 2) ? 1. : -1.);
  117. double s4 = exp(rng.uniform(-1, 6) * 3.0 * CV_LOG2) * (rng.uniform(0, 2) ? 1. : -1.);
  118. return cv::Scalar(s1, s2, s3, s4);
  119. }
  120. void initOutMats(cv::Size sz_in, int dtype)
  121. {
  122. if (dtype != -1)
  123. {
  124. out_mat_gapi = cv::Mat(sz_in, dtype);
  125. out_mat_ocv = cv::Mat(sz_in, dtype);
  126. }
  127. }
  128. void initMatsRandU(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
  129. {
  130. in_mat1 = cv::Mat(sz_in, type);
  131. in_mat2 = cv::Mat(sz_in, type);
  132. int sdepth = CV_MAT_DEPTH(type);
  133. int ddepth = (dtype >= 0) ? CV_MAT_DEPTH(dtype)
  134. : sdepth; // dtype == -1 <=> dtype == SAME_TYPE
  135. if ((sdepth >= CV_32F) || (ddepth >= CV_32F))
  136. {
  137. sc = initScalarRandU(); // initializing by floating-points
  138. }
  139. else
  140. {
  141. switch (sdepth)
  142. {
  143. case CV_8U:
  144. sc = initScalarRandU(UCHAR_MAX + 1U);
  145. break;
  146. case CV_16U:
  147. sc = initScalarRandU(USHRT_MAX + 1U);
  148. break;
  149. case CV_16S:
  150. sc = initScalarRandU(SHRT_MAX + 1U);
  151. break;
  152. default:
  153. sc = initScalarRandU(SCHAR_MAX + 1U);
  154. break;
  155. }
  156. }
  157. // Details: https://github.com/opencv/opencv/pull/16083
  158. //if (CV_MAT_DEPTH(type) < CV_32F)
  159. if (1)
  160. {
  161. cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
  162. cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
  163. }
  164. else
  165. {
  166. const int fscale = 256; // avoid bits near ULP, generate stable test input
  167. Mat in_mat32s(in_mat1.size(), CV_MAKE_TYPE(CV_32S, CV_MAT_CN(type)));
  168. cv::randu(in_mat32s, cv::Scalar::all(0), cv::Scalar::all(255 * fscale));
  169. in_mat32s.convertTo(in_mat1, type, 1.0f / fscale, 0);
  170. cv::randu(in_mat32s, cv::Scalar::all(0), cv::Scalar::all(255 * fscale));
  171. in_mat32s.convertTo(in_mat2, type, 1.0f / fscale, 0);
  172. }
  173. if (createOutputMatrices)
  174. {
  175. initOutMats(sz_in, dtype);
  176. }
  177. }
  178. void initMatrixRandU(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
  179. {
  180. in_mat1 = cv::Mat(sz_in, type);
  181. int sdepth = CV_MAT_DEPTH(type);
  182. int ddepth = (dtype >= 0) ? CV_MAT_DEPTH(dtype)
  183. : sdepth; // dtype == -1 <=> dtype == SAME_TYPE
  184. if ((sdepth >= CV_32F) || (ddepth >= CV_32F))
  185. {
  186. sc = initScalarRandU();
  187. }
  188. else
  189. {
  190. switch (sdepth)
  191. {
  192. case CV_8U:
  193. sc = initScalarRandU(UCHAR_MAX + 1U);
  194. break;
  195. case CV_16U:
  196. sc = initScalarRandU(USHRT_MAX + 1U);
  197. break;
  198. case CV_16S:
  199. sc = initScalarRandU(SHRT_MAX + 1U);
  200. break;
  201. default:
  202. sc = initScalarRandU(SCHAR_MAX + 1U);
  203. break;
  204. }
  205. }
  206. if (CV_MAT_DEPTH(type) < CV_32F)
  207. {
  208. cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
  209. }
  210. else
  211. {
  212. const int fscale = 256; // avoid bits near ULP, generate stable test input
  213. Mat in_mat32s(in_mat1.size(), CV_MAKE_TYPE(CV_32S, CV_MAT_CN(type)));
  214. cv::randu(in_mat32s, cv::Scalar::all(0), cv::Scalar::all(255 * fscale));
  215. in_mat32s.convertTo(in_mat1, type, 1.0f / fscale, 0);
  216. }
  217. if (createOutputMatrices)
  218. {
  219. initOutMats(sz_in, dtype);
  220. }
  221. }
  222. void initMatrixRandN(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
  223. {
  224. in_mat1 = cv::Mat(sz_in, type);
  225. cv::randn(in_mat1, cv::Scalar::all(127), cv::Scalar::all(40.f));
  226. if (createOutputMatrices)
  227. {
  228. initOutMats(sz_in, dtype);
  229. }
  230. }
  231. void initMatFromImage(int type, const std::string& fileName)
  232. {
  233. int channels = (type >> CV_CN_SHIFT) + 1;
  234. GAPI_Assert(channels == 1 || channels == 3 || channels == 4);
  235. const int readFlags = (channels == 1) ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR;
  236. cv::Mat mat = cv::imread(findDataFile(fileName), readFlags);
  237. if (channels == 4)
  238. {
  239. cv::cvtColor(mat, in_mat1, cv::COLOR_BGR2BGRA);
  240. }
  241. else
  242. {
  243. in_mat1 = mat;
  244. }
  245. int depth = CV_MAT_DEPTH(type);
  246. if (in_mat1.depth() != depth)
  247. {
  248. in_mat1.convertTo(in_mat1, depth);
  249. }
  250. }
  251. void initMatsFromImages(int channels, const std::string& pattern, int imgNum)
  252. {
  253. GAPI_Assert(channels == 1 || channels == 3 || channels == 4);
  254. const int flags = (channels == 1) ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR;
  255. cv::Mat m1 = cv::imread(findDataFile(cv::format(pattern.c_str(), imgNum)), flags);
  256. cv::Mat m2 = cv::imread(findDataFile(cv::format(pattern.c_str(), imgNum + 1)), flags);
  257. if (channels == 4)
  258. {
  259. cvtColor(m1, in_mat1, cv::COLOR_BGR2BGRA);
  260. cvtColor(m2, in_mat2, cv::COLOR_BGR2BGRA);
  261. }
  262. else
  263. {
  264. std::tie(in_mat1, in_mat2) = std::make_tuple(m1, m2);
  265. }
  266. }
  267. template <typename T>
  268. inline void initPointRandU(cv::RNG& rng, T& pt) const
  269. { ::initPointRandU(rng, pt); }
  270. // Disable unreachable code warning for MSVS 2015
  271. #if defined _MSC_VER && _MSC_VER < 1910 /*MSVS 2017*/
  272. #pragma warning(push)
  273. #pragma warning(disable: 4702)
  274. #endif
  275. // initialize std::vector<cv::Point_<T>>/std::vector<cv::Point3_<T>>
  276. template <typename T, template <typename> class Pt>
  277. void initPointsVectorRandU(const int sz_in, std::vector<Pt<T>> &vec_) const
  278. {
  279. cv::RNG& rng = theRNG();
  280. vec_.clear();
  281. vec_.reserve(sz_in);
  282. for (int i = 0; i < sz_in; i++)
  283. {
  284. Pt<T> pt;
  285. initPointRandU(rng, pt);
  286. vec_.emplace_back(pt);
  287. }
  288. }
  289. #if defined _MSC_VER && _MSC_VER < 1910 /*MSVS 2017*/
  290. #pragma warning(pop)
  291. #endif
  292. template<typename Pt>
  293. inline void initMatByPointsVectorRandU(const cv::Size &sz_in)
  294. {
  295. std::vector<Pt> in_vector;
  296. initPointsVectorRandU(sz_in.width, in_vector);
  297. in_mat1 = cv::Mat(in_vector, true);
  298. }
  299. // initialize Mat by a vector of Points
  300. template<template <typename> class Pt>
  301. inline void initMatByPointsVectorRandU(int type, cv::Size sz_in, int)
  302. {
  303. int depth = CV_MAT_DEPTH(type);
  304. switch (depth)
  305. {
  306. case CV_8U:
  307. initMatByPointsVectorRandU<Pt<uchar>>(sz_in);
  308. break;
  309. case CV_8S:
  310. initMatByPointsVectorRandU<Pt<char>>(sz_in);
  311. break;
  312. case CV_16U:
  313. initMatByPointsVectorRandU<Pt<ushort>>(sz_in);
  314. break;
  315. case CV_16S:
  316. initMatByPointsVectorRandU<Pt<short>>(sz_in);
  317. break;
  318. case CV_32S:
  319. initMatByPointsVectorRandU<Pt<int>>(sz_in);
  320. break;
  321. case CV_32F:
  322. initMatByPointsVectorRandU<Pt<float>>(sz_in);
  323. break;
  324. case CV_64F:
  325. initMatByPointsVectorRandU<Pt<double>>(sz_in);
  326. break;
  327. case CV_16F:
  328. initMatByPointsVectorRandU<Pt<cv::float16_t>>(sz_in);
  329. break;
  330. default:
  331. GAPI_Assert(false && "Unsupported depth");
  332. break;
  333. }
  334. }
  335. // empty function intended to show that nothing is to be initialized via TestFunctional methods
  336. void initNothing(int, cv::Size, int, bool = true) {}
  337. };
  338. template<class T>
  339. class TestPerfParams: public TestFunctional, public perf::TestBaseWithParam<T>{};
  340. // FIXME: re-use MatType. current problem: "special values" interpreted incorrectly (-1 is printed
  341. // as 16FC512)
  342. struct MatType2
  343. {
  344. public:
  345. MatType2(int val = 0) : _value(val) {}
  346. operator int() const { return _value; }
  347. friend std::ostream& operator<<(std::ostream& os, const MatType2& t)
  348. {
  349. switch (t)
  350. {
  351. case -1: return os << "SAME_TYPE";
  352. default: PrintTo(MatType(t), &os); return os;
  353. }
  354. }
  355. private:
  356. int _value;
  357. };
  358. // Universal parameter wrapper for common (pre-defined) and specific (user-defined) parameters
  359. template<typename CommonParams, typename SpecificParams>
  360. struct ParamsBase;
  361. template<typename... CommonParams, typename... SpecificParams>
  362. struct ParamsBase<std::tuple<CommonParams...>, std::tuple<SpecificParams...>>
  363. {
  364. using common_params_t = std::tuple<CommonParams...>;
  365. using specific_params_t = std::tuple<SpecificParams...>;
  366. using params_t = std::tuple<CommonParams..., SpecificParams...>;
  367. static constexpr const size_t common_params_size = std::tuple_size<common_params_t>::value;
  368. static constexpr const size_t specific_params_size = std::tuple_size<specific_params_t>::value;
  369. template<size_t I>
  370. static const typename std::tuple_element<I, common_params_t>::type&
  371. getCommon(const params_t& t)
  372. {
  373. static_assert(I < common_params_size, "Index out of range");
  374. return std::get<I>(t);
  375. }
  376. template<size_t I>
  377. static const typename std::tuple_element<I, specific_params_t>::type&
  378. getSpecific(const params_t& t)
  379. {
  380. static_assert(specific_params_size > 0,
  381. "Impossible to call this function: no specific parameters specified");
  382. static_assert(I < specific_params_size, "Index out of range");
  383. return std::get<common_params_size + I>(t);
  384. }
  385. };
  386. template<typename... SpecificParams>
  387. struct Params : public ParamsBase<std::tuple<MatType2,cv::Size,MatType2,cv::GCompileArgs(*)()>,
  388. std::tuple<SpecificParams...>>
  389. {
  390. static constexpr const size_t compile_args_num = 3;
  391. };
  392. template<typename ...SpecificParams>
  393. struct ParamsSpecific : public ParamsBase<std::tuple<cv::GCompileArgs(*)()>,
  394. std::tuple<SpecificParams...>>
  395. {
  396. static constexpr const size_t compile_args_num = 0;
  397. };
  398. // Base class for test fixtures
  399. template<typename AllParams>
  400. struct TestWithParamsBase : TestFunctional, TestWithParam<typename AllParams::params_t>
  401. {
  402. // Get common (pre-defined) parameter value by index
  403. template<size_t I>
  404. inline auto getCommonParam() const
  405. -> decltype(AllParams::template getCommon<I>(this->GetParam()))
  406. {
  407. return AllParams::template getCommon<I>(this->GetParam());
  408. }
  409. // Get specific (user-defined) parameter value by index
  410. template<size_t I>
  411. inline auto getSpecificParam() const
  412. -> decltype(AllParams::template getSpecific<I>(this->GetParam()))
  413. {
  414. return AllParams::template getSpecific<I>(this->GetParam());
  415. }
  416. // Return G-API compile arguments specified for test fixture
  417. inline cv::GCompileArgs getCompileArgs() const
  418. {
  419. return getCommonParam<AllParams::compile_args_num>()();
  420. }
  421. };
  422. template<typename... SpecificParams>
  423. struct TestWithParams : public TestWithParamsBase<Params<SpecificParams...>>
  424. {
  425. using AllParams = Params<SpecificParams...>;
  426. MatType2 type = this->template getCommonParam<0>();
  427. cv::Size sz = this->template getCommonParam<1>();
  428. MatType2 dtype = this->template getCommonParam<2>();
  429. };
  430. template<typename... SpecificParams>
  431. struct TestWithParamsSpecific : public TestWithParamsBase<ParamsSpecific<SpecificParams...>>
  432. {
  433. using AllParams = ParamsSpecific<SpecificParams...>;
  434. };
  435. /**
  436. * @private
  437. * @brief Create G-API test fixture with TestWithParams base class
  438. * @param Fixture test fixture name
  439. * @param InitF callable that will initialize default available members (from TestFunctional)
  440. * @param API base class API. Specifies types of user-defined parameters. If there are no such
  441. * parameters, empty angle brackets ("<>") must be specified.
  442. * @param Number number of user-defined parameters (corresponds to the number of types in API).
  443. * if there are no such parameters, 0 must be specified.
  444. * @param ... list of names of user-defined parameters. if there are no parameters, the list
  445. * must be empty.
  446. */
  447. //TODO: Consider to remove `Number` and use `std::tuple_size<decltype(std::make_tuple(__VA_ARGS__))>::value`
  448. #define GAPI_TEST_FIXTURE(Fixture, InitF, API, Number, ...) \
  449. struct Fixture : public TestWithParams API { \
  450. static_assert(Number == AllParams::specific_params_size, \
  451. "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \
  452. __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \
  453. Fixture() { InitF(type, sz, dtype); } \
  454. };
  455. /**
  456. * @private
  457. * @brief Create G-API test fixture with TestWithParams base class and additional base class.
  458. * @param Fixture test fixture name.
  459. @param ExtBase additional base class.
  460. * @param InitF callable that will initialize default available members (from TestFunctional)
  461. * @param API base class API. Specifies types of user-defined parameters. If there are no such
  462. * parameters, empty angle brackets ("<>") must be specified.
  463. * @param Number number of user-defined parameters (corresponds to the number of types in API).
  464. * if there are no such parameters, 0 must be specified.
  465. * @param ... list of names of user-defined parameters. if there are no parameters, the list
  466. * must be empty.
  467. */
  468. #define GAPI_TEST_EXT_BASE_FIXTURE(Fixture, ExtBase, InitF, API, Number, ...) \
  469. struct Fixture : public TestWithParams API, public ExtBase { \
  470. static_assert(Number == AllParams::specific_params_size, \
  471. "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \
  472. __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \
  473. Fixture() { InitF(type, sz, dtype); } \
  474. };
  475. /**
  476. * @private
  477. * @brief Create G-API test fixture with TestWithParamsSpecific base class
  478. * This fixture has reduced number of common parameters and no initialization;
  479. * it should be used if you don't need common parameters of GAPI_TEST_FIXTURE.
  480. * @param Fixture test fixture name
  481. * @param API base class API. Specifies types of user-defined parameters. If there are no such
  482. * parameters, empty angle brackets ("<>") must be specified.
  483. * @param Number number of user-defined parameters (corresponds to the number of types in API).
  484. * if there are no such parameters, 0 must be specified.
  485. * @param ... list of names of user-defined parameters. if there are no parameters, the list
  486. * must be empty.
  487. */
  488. #define GAPI_TEST_FIXTURE_SPEC_PARAMS(Fixture, API, Number, ...) \
  489. struct Fixture : public TestWithParamsSpecific API { \
  490. static_assert(Number == AllParams::specific_params_size, \
  491. "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \
  492. __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \
  493. };
  494. // Wrapper for test fixture API. Use to specify multiple types.
  495. // Example: FIXTURE_API(int, bool) expands to <int, bool>
  496. #define FIXTURE_API(...) <__VA_ARGS__>
  497. using compare_f = std::function<bool(const cv::Mat &a, const cv::Mat &b)>;
  498. using compare_scalar_f = std::function<bool(const cv::Scalar &a, const cv::Scalar &b)>;
  499. using compare_rect_f = std::function<bool(const cv::Rect &a, const cv::Rect &b)>;
  500. template<typename Elem>
  501. using compare_vector_f = std::function<bool(const std::vector<Elem> &a,
  502. const std::vector<Elem> &b)>;
  503. template<typename Elem, int cn>
  504. using compare_vec_f = std::function<bool(const cv::Vec<Elem, cn> &a, const cv::Vec<Elem, cn> &b)>;
  505. template<typename T1, typename T2>
  506. struct CompareF
  507. {
  508. CompareF() = default;
  509. using callable_t = std::function<bool(const T1& a, const T2& b)>;
  510. CompareF(callable_t&& cmp, std::string&& cmp_name) :
  511. _comparator(std::move(cmp)), _name(std::move(cmp_name)) {}
  512. bool operator()(const T1& a, const T2& b) const
  513. {
  514. return _comparator(a, b);
  515. }
  516. friend std::ostream& operator<<(std::ostream& os, const CompareF<T1, T2>& obj)
  517. {
  518. return os << obj._name;
  519. }
  520. private:
  521. callable_t _comparator;
  522. std::string _name;
  523. };
  524. using CompareMats = CompareF<cv::Mat, cv::Mat>;
  525. using CompareScalars = CompareF<cv::Scalar, cv::Scalar>;
  526. using CompareRects = CompareF<cv::Rect, cv::Rect>;
  527. template<typename Elem>
  528. using CompareVectors = CompareF<std::vector<Elem>, std::vector<Elem>>;
  529. template<typename Elem, int cn>
  530. using CompareVecs = CompareF<cv::Vec<Elem, cn>, cv::Vec<Elem, cn>>;
  531. template<typename T>
  532. struct Wrappable
  533. {
  534. compare_f to_compare_f()
  535. {
  536. T t = *static_cast<T*const>(this);
  537. return [t](const cv::Mat &a, const cv::Mat &b)
  538. {
  539. return t(a, b);
  540. };
  541. }
  542. CompareMats to_compare_obj()
  543. {
  544. T t = *static_cast<T*const>(this);
  545. std::stringstream ss;
  546. ss << t;
  547. return CompareMats(to_compare_f(), ss.str());
  548. }
  549. };
  550. template<typename T>
  551. struct WrappableScalar
  552. {
  553. compare_scalar_f to_compare_f()
  554. {
  555. T t = *static_cast<T*const>(this);
  556. return [t](const cv::Scalar &a, const cv::Scalar &b)
  557. {
  558. return t(a, b);
  559. };
  560. }
  561. CompareScalars to_compare_obj()
  562. {
  563. T t = *static_cast<T*const>(this);
  564. std::stringstream ss;
  565. ss << t;
  566. return CompareScalars(to_compare_f(), ss.str());
  567. }
  568. };
  569. template<typename T>
  570. struct WrappableRect
  571. {
  572. compare_rect_f to_compare_f()
  573. {
  574. T t = *static_cast<T*const>(this);
  575. return [t](const cv::Rect &a, const cv::Rect &b)
  576. {
  577. return t(a, b);
  578. };
  579. }
  580. CompareRects to_compare_obj()
  581. {
  582. T t = *static_cast<T*const>(this);
  583. std::stringstream ss;
  584. ss << t;
  585. return CompareRects(to_compare_f(), ss.str());
  586. }
  587. };
  588. template<typename T, typename Elem>
  589. struct WrappableVector
  590. {
  591. compare_vector_f<Elem> to_compare_f()
  592. {
  593. T t = *static_cast<T* const>(this);
  594. return [t](const std::vector<Elem>& a,
  595. const std::vector<Elem>& b)
  596. {
  597. return t(a, b);
  598. };
  599. }
  600. CompareVectors<Elem> to_compare_obj()
  601. {
  602. T t = *static_cast<T* const>(this);
  603. std::stringstream ss;
  604. ss << t;
  605. return CompareVectors<Elem>(to_compare_f(), ss.str());
  606. }
  607. };
  608. template<typename T, typename Elem, int cn>
  609. struct WrappableVec
  610. {
  611. compare_vec_f<Elem, cn> to_compare_f()
  612. {
  613. T t = *static_cast<T* const>(this);
  614. return [t](const cv::Vec<Elem, cn> &a, const cv::Vec<Elem, cn> &b)
  615. {
  616. return t(a, b);
  617. };
  618. }
  619. CompareVecs<Elem, cn> to_compare_obj()
  620. {
  621. T t = *static_cast<T* const>(this);
  622. std::stringstream ss;
  623. ss << t;
  624. return CompareVecs<Elem, cn>(to_compare_f(), ss.str());
  625. }
  626. };
  627. class AbsExact : public Wrappable<AbsExact>
  628. {
  629. public:
  630. AbsExact() {}
  631. bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
  632. {
  633. if (cv::norm(in1, in2, NORM_INF) != 0)
  634. {
  635. std::cout << "AbsExact error: G-API output and reference output matrixes are not bitexact equal." << std::endl;
  636. return false;
  637. }
  638. else
  639. {
  640. return true;
  641. }
  642. }
  643. friend std::ostream& operator<<(std::ostream& os, const AbsExact&)
  644. {
  645. return os << "AbsExact()";
  646. }
  647. };
  648. class AbsTolerance : public Wrappable<AbsTolerance>
  649. {
  650. public:
  651. AbsTolerance(double tol) : _tol(tol) {}
  652. bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
  653. {
  654. if (cv::norm(in1, in2, NORM_INF) > _tol)
  655. {
  656. std::cout << "AbsTolerance error: Number of different pixels in " << std::endl;
  657. std::cout << "G-API output and reference output matrixes exceeds " << _tol << " pixels threshold." << std::endl;
  658. return false;
  659. }
  660. else
  661. {
  662. return true;
  663. }
  664. }
  665. friend std::ostream& operator<<(std::ostream& os, const AbsTolerance& obj)
  666. {
  667. return os << "AbsTolerance(" << std::to_string(obj._tol) << ")";
  668. }
  669. private:
  670. double _tol;
  671. };
  672. class Tolerance_FloatRel_IntAbs : public Wrappable<Tolerance_FloatRel_IntAbs>
  673. {
  674. public:
  675. Tolerance_FloatRel_IntAbs(double tol, double tol8u) : _tol(tol), _tol8u(tol8u) {}
  676. bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
  677. {
  678. int depth = CV_MAT_DEPTH(in1.type());
  679. {
  680. double err = depth >= CV_32F ? cv::norm(in1, in2, NORM_L1 | NORM_RELATIVE)
  681. : cv::norm(in1, in2, NORM_INF);
  682. double tolerance = depth >= CV_32F ? _tol : _tol8u;
  683. if (err > tolerance)
  684. {
  685. std::cout << "Tolerance_FloatRel_IntAbs error: err=" << err
  686. << " tolerance=" << tolerance
  687. << " depth=" << cv::typeToString(depth) << std::endl;
  688. return false;
  689. }
  690. else
  691. {
  692. return true;
  693. }
  694. }
  695. }
  696. friend std::ostream& operator<<(std::ostream& os, const Tolerance_FloatRel_IntAbs& obj)
  697. {
  698. return os << "Tolerance_FloatRel_IntAbs(" << obj._tol << ", " << obj._tol8u << ")";
  699. }
  700. private:
  701. double _tol;
  702. double _tol8u;
  703. };
  704. class AbsSimilarPoints : public Wrappable<AbsSimilarPoints>
  705. {
  706. public:
  707. AbsSimilarPoints(double tol, double percent) : _tol(tol), _percent(percent) {}
  708. bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
  709. {
  710. Mat diff;
  711. cv::absdiff(in1, in2, diff);
  712. Mat err_mask = diff > _tol;
  713. int err_points = (cv::countNonZero)(err_mask.reshape(1));
  714. double max_err_points = _percent * std::max((size_t)1000, in1.total());
  715. if (err_points > max_err_points)
  716. {
  717. std::cout << "AbsSimilarPoints error: err_points=" << err_points
  718. << " max_err_points=" << max_err_points << " (total=" << in1.total() << ")"
  719. << " diff_tolerance=" << _tol << std::endl;
  720. return false;
  721. }
  722. else
  723. {
  724. return true;
  725. }
  726. }
  727. friend std::ostream& operator<<(std::ostream& os, const AbsSimilarPoints& obj)
  728. {
  729. return os << "AbsSimilarPoints(" << obj._tol << ", " << obj._percent << ")";
  730. }
  731. private:
  732. double _tol;
  733. double _percent;
  734. };
  735. class ToleranceFilter : public Wrappable<ToleranceFilter>
  736. {
  737. public:
  738. ToleranceFilter(double tol, double tol8u, double inf_tol = 2.0) : _tol(tol), _tol8u(tol8u), _inf_tol(inf_tol) {}
  739. bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
  740. {
  741. int depth = CV_MAT_DEPTH(in1.type());
  742. {
  743. double err_Inf = cv::norm(in1, in2, NORM_INF);
  744. if (err_Inf > _inf_tol)
  745. {
  746. std::cout << "ToleranceFilter error: err_Inf=" << err_Inf << " tolerance=" << _inf_tol << std::endl;
  747. return false;
  748. }
  749. double err = cv::norm(in1, in2, NORM_L2 | NORM_RELATIVE);
  750. double tolerance = depth >= CV_32F ? _tol : _tol8u;
  751. if (err > tolerance)
  752. {
  753. std::cout << "ToleranceFilter error: err=" << err << " tolerance=" << tolerance
  754. << " depth=" << cv::depthToString(depth)
  755. << std::endl;
  756. return false;
  757. }
  758. }
  759. return true;
  760. }
  761. friend std::ostream& operator<<(std::ostream& os, const ToleranceFilter& obj)
  762. {
  763. return os << "ToleranceFilter(" << obj._tol << ", " << obj._tol8u << ", "
  764. << obj._inf_tol << ")";
  765. }
  766. private:
  767. double _tol;
  768. double _tol8u;
  769. double _inf_tol;
  770. };
  771. class ToleranceColor : public Wrappable<ToleranceColor>
  772. {
  773. public:
  774. ToleranceColor(double tol, double inf_tol = 2.0) : _tol(tol), _inf_tol(inf_tol) {}
  775. bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
  776. {
  777. {
  778. double err_Inf = cv::norm(in1, in2, NORM_INF);
  779. if (err_Inf > _inf_tol)
  780. {
  781. std::cout << "ToleranceColor error: err_Inf=" << err_Inf
  782. << " tolerance=" << _inf_tol << std::endl;
  783. return false;
  784. }
  785. double err = cv::norm(in1, in2, NORM_L1 | NORM_RELATIVE);
  786. if (err > _tol)
  787. {
  788. std::cout << "ToleranceColor error: err=" << err
  789. << " tolerance=" << _tol << std::endl;
  790. return false;
  791. }
  792. }
  793. return true;
  794. }
  795. friend std::ostream& operator<<(std::ostream& os, const ToleranceColor& obj)
  796. {
  797. return os << "ToleranceColor(" << obj._tol << ", " << obj._inf_tol << ")";
  798. }
  799. private:
  800. double _tol;
  801. double _inf_tol;
  802. };
  803. class AbsToleranceScalar : public WrappableScalar<AbsToleranceScalar>
  804. {
  805. public:
  806. AbsToleranceScalar(double tol) : _tol(tol) {}
  807. bool operator() (const cv::Scalar& in1, const cv::Scalar& in2) const
  808. {
  809. double abs_err = std::abs(in1[0] - in2[0]) / std::max(1.0, std::abs(in2[0]));
  810. if (abs_err > _tol)
  811. {
  812. std::cout << "AbsToleranceScalar error: abs_err=" << abs_err << " tolerance=" << _tol
  813. << " in1[0]" << in1[0] << " in2[0]" << in2[0] << std::endl;
  814. return false;
  815. }
  816. else
  817. {
  818. return true;
  819. }
  820. }
  821. friend std::ostream& operator<<(std::ostream& os, const AbsToleranceScalar& obj)
  822. {
  823. return os << "AbsToleranceScalar(" << std::to_string(obj._tol) << ")";
  824. }
  825. private:
  826. double _tol;
  827. };
  828. class IoUToleranceRect : public WrappableRect<IoUToleranceRect>
  829. {
  830. public:
  831. IoUToleranceRect(double tol) : _tol(tol) {}
  832. bool operator() (const cv::Rect& in1, const cv::Rect& in2) const
  833. {
  834. // determine the (x, y)-coordinates of the intersection rectangle
  835. int xA = max(in1.x, in2.x);
  836. int yA = max(in1.y, in2.y);
  837. int xB = min(in1.br().x, in2.br().x);
  838. int yB = min(in1.br().y, in2.br().y);
  839. // compute the area of intersection rectangle
  840. int interArea = max(0, xB - xA) * max(0, yB - yA);
  841. // compute the area of union rectangle
  842. int unionArea = in1.area() + in2.area() - interArea;
  843. double iou = interArea / unionArea;
  844. double err = 1 - iou;
  845. if (err > _tol)
  846. {
  847. std::cout << "IoUToleranceRect error: err=" << err << " tolerance=" << _tol
  848. << " in1.x=" << in1.x << " in2.x=" << in2.x
  849. << " in1.y=" << in1.y << " in2.y=" << in2.y
  850. << " in1.width=" << in1.width << " in2.width=" << in2.width
  851. << " in1.height=" << in1.height << " in2.height=" << in2.height << std::endl;
  852. return false;
  853. }
  854. else
  855. {
  856. return true;
  857. }
  858. }
  859. friend std::ostream& operator<<(std::ostream& os, const IoUToleranceRect& obj)
  860. {
  861. return os << "IoUToleranceRect(" << std::to_string(obj._tol) << ")";
  862. }
  863. private:
  864. double _tol;
  865. };
  866. template<typename Elem>
  867. class AbsExactVector : public WrappableVector<AbsExactVector<Elem>, Elem>
  868. {
  869. public:
  870. AbsExactVector() {}
  871. bool operator() (const std::vector<Elem>& in1,
  872. const std::vector<Elem>& in2) const
  873. {
  874. if (cv::norm(in1, in2, NORM_INF, cv::noArray()) != 0)
  875. {
  876. std::cout << "AbsExact error: G-API output and reference output vectors are not"
  877. " bitexact equal." << std::endl;
  878. return false;
  879. }
  880. else
  881. {
  882. return true;
  883. }
  884. }
  885. friend std::ostream& operator<<(std::ostream& os, const AbsExactVector<Elem>&)
  886. {
  887. return os << "AbsExactVector()";
  888. }
  889. };
  890. template<typename Elem, int cn>
  891. class RelDiffToleranceVec : public WrappableVec<RelDiffToleranceVec<Elem, cn>, Elem, cn>
  892. {
  893. public:
  894. RelDiffToleranceVec(double tol) : _tol(tol) {}
  895. bool operator() (const cv::Vec<Elem, cn> &in1, const cv::Vec<Elem, cn> &in2) const
  896. {
  897. double abs_err = cv::norm(in1, in2, cv::NORM_L1);
  898. double in2_norm = cv::norm(in2, cv::NORM_L1);
  899. // Checks to avoid dividing by zero
  900. double err = abs_err ? abs_err / (in2_norm ? in2_norm : cv::norm(in1, cv::NORM_L1))
  901. : abs_err;
  902. if (err > _tol)
  903. {
  904. std::cout << "RelDiffToleranceVec error: err=" << err << " tolerance=" << _tol;
  905. for (int i = 0; i < cn; i++)
  906. {
  907. std::cout << " in1[" << i << "]=" << in1[i] << " in2[" << i << "]=" << in2[i];
  908. }
  909. std::cout << std::endl;
  910. return false;
  911. }
  912. else
  913. {
  914. return true;
  915. }
  916. }
  917. friend std::ostream& operator<<(std::ostream& os, const RelDiffToleranceVec<Elem, cn>& obj)
  918. {
  919. return os << "RelDiffToleranceVec(" << std::to_string(obj._tol) << ")";
  920. }
  921. private:
  922. double _tol;
  923. };
  924. } // namespace opencv_test
  925. namespace
  926. {
  927. inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_f&)
  928. {
  929. return os << "compare_f";
  930. }
  931. inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_scalar_f&)
  932. {
  933. return os << "compare_scalar_f";
  934. }
  935. inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_rect_f&)
  936. {
  937. return os << "compare_rect_f";
  938. }
  939. template<typename Elem>
  940. inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_vector_f<Elem>&)
  941. {
  942. return os << "compare_vector_f";
  943. }
  944. template<typename Elem, int cn>
  945. inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_vec_f<Elem, cn>&)
  946. {
  947. return os << "compare_vec_f";
  948. }
  949. } // anonymous namespace
  950. // Note: namespace must match the namespace of the type of the printed object
  951. namespace cv
  952. {
  953. inline std::ostream& operator<<(std::ostream& os, CmpTypes op)
  954. {
  955. #define CASE(v) case CmpTypes::v: os << #v; break
  956. switch (op)
  957. {
  958. CASE(CMP_EQ);
  959. CASE(CMP_GT);
  960. CASE(CMP_GE);
  961. CASE(CMP_LT);
  962. CASE(CMP_LE);
  963. CASE(CMP_NE);
  964. default: GAPI_Assert(false && "unknown CmpTypes value");
  965. }
  966. #undef CASE
  967. return os;
  968. }
  969. inline std::ostream& operator<<(std::ostream& os, NormTypes op)
  970. {
  971. #define CASE(v) case NormTypes::v: os << #v; break
  972. switch (op)
  973. {
  974. CASE(NORM_INF);
  975. CASE(NORM_L1);
  976. CASE(NORM_L2);
  977. CASE(NORM_L2SQR);
  978. CASE(NORM_HAMMING);
  979. CASE(NORM_HAMMING2);
  980. CASE(NORM_RELATIVE);
  981. CASE(NORM_MINMAX);
  982. default: GAPI_Assert(false && "unknown NormTypes value");
  983. }
  984. #undef CASE
  985. return os;
  986. }
  987. inline std::ostream& operator<<(std::ostream& os, RetrievalModes op)
  988. {
  989. #define CASE(v) case RetrievalModes::v: os << #v; break
  990. switch (op)
  991. {
  992. CASE(RETR_EXTERNAL);
  993. CASE(RETR_LIST);
  994. CASE(RETR_CCOMP);
  995. CASE(RETR_TREE);
  996. CASE(RETR_FLOODFILL);
  997. default: GAPI_Assert(false && "unknown RetrievalModes value");
  998. }
  999. #undef CASE
  1000. return os;
  1001. }
  1002. inline std::ostream& operator<<(std::ostream& os, ContourApproximationModes op)
  1003. {
  1004. #define CASE(v) case ContourApproximationModes::v: os << #v; break
  1005. switch (op)
  1006. {
  1007. CASE(CHAIN_APPROX_NONE);
  1008. CASE(CHAIN_APPROX_SIMPLE);
  1009. CASE(CHAIN_APPROX_TC89_L1);
  1010. CASE(CHAIN_APPROX_TC89_KCOS);
  1011. default: GAPI_Assert(false && "unknown ContourApproximationModes value");
  1012. }
  1013. #undef CASE
  1014. return os;
  1015. }
  1016. inline std::ostream& operator<<(std::ostream& os, MorphTypes op)
  1017. {
  1018. #define CASE(v) case MorphTypes::v: os << #v; break
  1019. switch (op)
  1020. {
  1021. CASE(MORPH_ERODE);
  1022. CASE(MORPH_DILATE);
  1023. CASE(MORPH_OPEN);
  1024. CASE(MORPH_CLOSE);
  1025. CASE(MORPH_GRADIENT);
  1026. CASE(MORPH_TOPHAT);
  1027. CASE(MORPH_BLACKHAT);
  1028. CASE(MORPH_HITMISS);
  1029. default: GAPI_Assert(false && "unknown MorphTypes value");
  1030. }
  1031. #undef CASE
  1032. return os;
  1033. }
  1034. inline std::ostream& operator<<(std::ostream& os, DistanceTypes op)
  1035. {
  1036. #define CASE(v) case DistanceTypes::v: os << #v; break
  1037. switch (op)
  1038. {
  1039. CASE(DIST_USER);
  1040. CASE(DIST_L1);
  1041. CASE(DIST_L2);
  1042. CASE(DIST_C);
  1043. CASE(DIST_L12);
  1044. CASE(DIST_FAIR);
  1045. CASE(DIST_WELSCH);
  1046. CASE(DIST_HUBER);
  1047. default: GAPI_Assert(false && "unknown DistanceTypes value");
  1048. }
  1049. #undef CASE
  1050. return os;
  1051. }
  1052. inline std::ostream& operator<<(std::ostream& os, KmeansFlags op)
  1053. {
  1054. int op_(op);
  1055. switch (op_)
  1056. {
  1057. case KmeansFlags::KMEANS_RANDOM_CENTERS:
  1058. os << "KMEANS_RANDOM_CENTERS";
  1059. break;
  1060. case KmeansFlags::KMEANS_PP_CENTERS:
  1061. os << "KMEANS_PP_CENTERS";
  1062. break;
  1063. case KmeansFlags::KMEANS_RANDOM_CENTERS | KmeansFlags::KMEANS_USE_INITIAL_LABELS:
  1064. os << "KMEANS_RANDOM_CENTERS | KMEANS_USE_INITIAL_LABELS";
  1065. break;
  1066. case KmeansFlags::KMEANS_PP_CENTERS | KmeansFlags::KMEANS_USE_INITIAL_LABELS:
  1067. os << "KMEANS_PP_CENTERS | KMEANS_USE_INITIAL_LABELS";
  1068. break;
  1069. default: GAPI_Assert(false && "unknown KmeansFlags value");
  1070. }
  1071. return os;
  1072. }
  1073. } // namespace cv
  1074. #endif //OPENCV_GAPI_TESTS_COMMON_HPP