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.
5 // Copyright (C) 2018-2019 Intel Corporation
7 #ifndef OPENCV_GAPI_TESTS_COMMON_HPP
8 #define OPENCV_GAPI_TESTS_COMMON_HPP
12 #include <type_traits>
14 #include <opencv2/ts.hpp>
15 #include <opencv2/gapi.hpp>
16 #include <opencv2/gapi/util/util.hpp>
18 #include "gapi_tests_helpers.hpp"
22 inline std::ostream& operator<<(std::ostream& o, const cv::GCompileArg& arg)
24 return o << (arg.tag.empty() ? "empty" : arg.tag);
41 cv::Scalar initScalarRandU(unsigned upper)
43 auto& rng = cv::theRNG();
44 double s1 = rng(upper);
45 double s2 = rng(upper);
46 double s3 = rng(upper);
47 double s4 = rng(upper);
48 return cv::Scalar(s1, s2, s3, s4);
51 void initOutMats(cv::Size sz_in, int dtype)
55 out_mat_gapi = cv::Mat(sz_in, dtype);
56 out_mat_ocv = cv::Mat(sz_in, dtype);
60 void initMatsRandU(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
62 in_mat1 = cv::Mat(sz_in, type);
63 in_mat2 = cv::Mat(sz_in, type);
65 sc = initScalarRandU(100);
66 cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
67 cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
69 if (createOutputMatrices)
71 initOutMats(sz_in, dtype);
75 void initMatrixRandU(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
77 in_mat1 = cv::Mat(sz_in, type);
79 sc = initScalarRandU(100);
80 cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
82 if (createOutputMatrices)
84 initOutMats(sz_in, dtype);
88 void initMatrixRandN(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
90 in_mat1 = cv::Mat(sz_in, type);
91 cv::randn(in_mat1, cv::Scalar::all(127), cv::Scalar::all(40.f));
93 if (createOutputMatrices)
95 initOutMats(sz_in, dtype);
99 // empty function intended to show that nothing is to be initialized via TestFunctional methods
100 void initNothing(int, cv::Size, int, bool = true) {}
102 static cv::Mat nonZeroPixels(const cv::Mat& mat)
104 int channels = mat.channels();
105 std::vector<cv::Mat> split(channels);
106 cv::split(mat, split);
108 for (int c=0; c < channels; c++)
111 result = split[c] != 0;
113 result = result | (split[c] != 0);
118 static int countNonZeroPixels(const cv::Mat& mat)
120 return cv::countNonZero( nonZeroPixels(mat) );
126 class TestParams: public TestFunctional, public TestWithParam<T>{};
129 class TestPerfParams: public TestFunctional, public perf::TestBaseWithParam<T>{};
131 using compare_f = std::function<bool(const cv::Mat &a, const cv::Mat &b)>;
133 using compare_scalar_f = std::function<bool(const cv::Scalar &a, const cv::Scalar &b)>;
135 // FIXME: re-use MatType. current problem: "special values" interpreted incorrectly (-1 is printed
140 MatType2(int val = 0) : _value(val) {}
141 operator int() const { return _value; }
142 friend std::ostream& operator<<(std::ostream& os, const MatType2& t)
146 case -1: return os << "SAME_TYPE";
147 default: PrintTo(MatType(t), &os); return os;
154 // Universal parameter wrapper for common (pre-defined) and specific (user-defined) parameters
155 template<typename ...SpecificParams>
158 using gcomp_args_function_t = cv::GCompileArgs(*)();
159 using common_params_t = std::tuple<MatType2, cv::Size, MatType2, gcomp_args_function_t>;
160 using specific_params_t = std::tuple<SpecificParams...>;
161 using params_t = std::tuple<MatType2, cv::Size, MatType2, gcomp_args_function_t, SpecificParams...>;
162 static constexpr const size_t common_params_size = std::tuple_size<common_params_t>::value;
163 static constexpr const size_t specific_params_size = std::tuple_size<specific_params_t>::value;
166 static const typename std::tuple_element<I, common_params_t>::type&
167 getCommon(const params_t& t)
169 static_assert(I < common_params_size, "Index out of range");
170 return std::get<I>(t);
174 static const typename std::tuple_element<I, specific_params_t>::type&
175 getSpecific(const params_t& t)
177 static_assert(specific_params_size > 0,
178 "Impossible to call this function: no specific parameters specified");
179 static_assert(I < specific_params_size, "Index out of range");
180 return std::get<common_params_size + I>(t);
184 // Base class for test fixtures
185 template<typename ...SpecificParams>
186 struct TestWithParamBase : TestFunctional,
187 TestWithParam<typename Params<SpecificParams...>::params_t>
189 using AllParams = Params<SpecificParams...>;
191 MatType2 type = getCommonParam<0>();
192 cv::Size sz = getCommonParam<1>();
193 MatType2 dtype = getCommonParam<2>();
195 // Get common (pre-defined) parameter value by index
197 inline auto getCommonParam() const
198 -> decltype(AllParams::template getCommon<I>(this->GetParam()))
200 return AllParams::template getCommon<I>(this->GetParam());
203 // Get specific (user-defined) parameter value by index
205 inline auto getSpecificParam() const
206 -> decltype(AllParams::template getSpecific<I>(this->GetParam()))
208 return AllParams::template getSpecific<I>(this->GetParam());
211 // Return G-API compile arguments specified for test fixture
212 inline cv::GCompileArgs getCompileArgs() const
214 return getCommonParam<3>()();
220 * @brief Create G-API test fixture with TestWithParamBase base class
221 * @param Fixture test fixture name
222 * @param InitF callable that will initialize default available members (from TestFunctional)
223 * @param API base class API. Specifies types of user-defined parameters. If there are no such
224 * parameters, empty angle brackets ("<>") must be specified.
225 * @param Number number of user-defined parameters (corresponds to the number of types in API).
226 * if there are no such parameters, 0 must be specified.
227 * @param ... list of names of user-defined parameters. if there are no parameters, the list
230 #define GAPI_TEST_FIXTURE(Fixture, InitF, API, Number, ...) \
231 struct Fixture : public TestWithParamBase API { \
232 static_assert(Number == AllParams::specific_params_size, \
233 "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \
234 __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \
235 Fixture() { InitF(type, sz, dtype); } \
238 // Wrapper for test fixture API. Use to specify multiple types.
239 // Example: FIXTURE_API(int, bool) expands to <int, bool>
240 #define FIXTURE_API(...) <__VA_ARGS__>
242 template<typename T1, typename T2>
245 using callable_t = std::function<bool(const T1& a, const T2& b)>;
246 CompareF(callable_t&& cmp, std::string&& cmp_name) :
247 _comparator(std::move(cmp)), _name(std::move(cmp_name)) {}
248 bool operator()(const T1& a, const T2& b) const
250 return _comparator(a, b);
252 friend std::ostream& operator<<(std::ostream& os, const CompareF<T1, T2>& obj)
254 return os << obj._name;
257 callable_t _comparator;
261 using CompareMats = CompareF<cv::Mat, cv::Mat>;
262 using CompareScalars = CompareF<cv::Scalar, cv::Scalar>;
267 compare_f to_compare_f()
269 T t = *static_cast<T*const>(this);
270 return [t](const cv::Mat &a, const cv::Mat &b)
276 CompareMats to_compare_obj()
278 T t = *static_cast<T*const>(this);
279 std::stringstream ss;
281 return CompareMats(to_compare_f(), ss.str());
286 struct WrappableScalar
288 compare_scalar_f to_compare_f()
290 T t = *static_cast<T*const>(this);
291 return [t](const cv::Scalar &a, const cv::Scalar &b)
297 CompareScalars to_compare_obj()
299 T t = *static_cast<T*const>(this);
300 std::stringstream ss;
302 return CompareScalars(to_compare_f(), ss.str());
307 class AbsExact : public Wrappable<AbsExact>
311 bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
313 if (cv::norm(in1, in2, NORM_INF) != 0)
315 std::cout << "AbsExact error: G-API output and reference output matrixes are not bitexact equal." << std::endl;
323 friend std::ostream& operator<<(std::ostream& os, const AbsExact&)
325 return os << "AbsExact()";
329 class AbsTolerance : public Wrappable<AbsTolerance>
332 AbsTolerance(double tol) : _tol(tol) {}
333 bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
335 if (cv::norm(in1, in2, NORM_INF) > _tol)
337 std::cout << "AbsTolerance error: Number of different pixels in " << std::endl;
338 std::cout << "G-API output and reference output matrixes exceeds " << _tol << " pixels threshold." << std::endl;
346 friend std::ostream& operator<<(std::ostream& os, const AbsTolerance& obj)
348 return os << "AbsTolerance(" << std::to_string(obj._tol) << ")";
354 class Tolerance_FloatRel_IntAbs : public Wrappable<Tolerance_FloatRel_IntAbs>
357 Tolerance_FloatRel_IntAbs(double tol, double tol8u) : _tol(tol), _tol8u(tol8u) {}
358 bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
360 int depth = CV_MAT_DEPTH(in1.type());
362 double err = depth >= CV_32F ? cv::norm(in1, in2, NORM_L1 | NORM_RELATIVE)
363 : cv::norm(in1, in2, NORM_INF);
364 double tolerance = depth >= CV_32F ? _tol : _tol8u;
367 std::cout << "Tolerance_FloatRel_IntAbs error: err=" << err
368 << " tolerance=" << tolerance
369 << " depth=" << cv::typeToString(depth) << std::endl;
378 friend std::ostream& operator<<(std::ostream& os, const Tolerance_FloatRel_IntAbs& obj)
380 return os << "Tolerance_FloatRel_IntAbs(" << obj._tol << ", " << obj._tol8u << ")";
388 class AbsSimilarPoints : public Wrappable<AbsSimilarPoints>
391 AbsSimilarPoints(double tol, double percent) : _tol(tol), _percent(percent) {}
392 bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
395 cv::absdiff(in1, in2, diff);
396 Mat err_mask = diff > _tol;
397 int err_points = cv::countNonZero(err_mask.reshape(1));
398 double max_err_points = _percent * std::max((size_t)1000, in1.total());
399 if (err_points > max_err_points)
401 std::cout << "AbsSimilarPoints error: err_points=" << err_points
402 << " max_err_points=" << max_err_points << " (total=" << in1.total() << ")"
403 << " diff_tolerance=" << _tol << std::endl;
411 friend std::ostream& operator<<(std::ostream& os, const AbsSimilarPoints& obj)
413 return os << "AbsSimilarPoints(" << obj._tol << ", " << obj._percent << ")";
421 class ToleranceFilter : public Wrappable<ToleranceFilter>
424 ToleranceFilter(double tol, double tol8u, double inf_tol = 2.0) : _tol(tol), _tol8u(tol8u), _inf_tol(inf_tol) {}
425 bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
427 int depth = CV_MAT_DEPTH(in1.type());
429 double err_Inf = cv::norm(in1, in2, NORM_INF);
430 if (err_Inf > _inf_tol)
432 std::cout << "ToleranceFilter error: err_Inf=" << err_Inf << " tolerance=" << _inf_tol << std::endl;
435 double err = cv::norm(in1, in2, NORM_L2 | NORM_RELATIVE);
436 double tolerance = depth >= CV_32F ? _tol : _tol8u;
439 std::cout << "ToleranceFilter error: err=" << err << " tolerance=" << tolerance
440 << " depth=" << cv::depthToString(depth)
447 friend std::ostream& operator<<(std::ostream& os, const ToleranceFilter& obj)
449 return os << "ToleranceFilter(" << obj._tol << ", " << obj._tol8u << ", "
450 << obj._inf_tol << ")";
458 class ToleranceColor : public Wrappable<ToleranceColor>
461 ToleranceColor(double tol, double inf_tol = 2.0) : _tol(tol), _inf_tol(inf_tol) {}
462 bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
465 double err_Inf = cv::norm(in1, in2, NORM_INF);
466 if (err_Inf > _inf_tol)
468 std::cout << "ToleranceColor error: err_Inf=" << err_Inf << " tolerance=" << _inf_tol << std::endl;;
471 double err = cv::norm(in1, in2, NORM_L1 | NORM_RELATIVE);
474 std::cout << "ToleranceColor error: err=" << err << " tolerance=" << _tol << std::endl;;
480 friend std::ostream& operator<<(std::ostream& os, const ToleranceColor& obj)
482 return os << "ToleranceColor(" << obj._tol << ", " << obj._inf_tol << ")";
489 class AbsToleranceScalar : public WrappableScalar<AbsToleranceScalar>
492 AbsToleranceScalar(double tol) : _tol(tol) {}
493 bool operator() (const cv::Scalar& in1, const cv::Scalar& in2) const
495 double abs_err = std::abs(in1[0] - in2[0]) / std::max(1.0, std::abs(in2[0]));
498 std::cout << "AbsToleranceScalar error: abs_err=" << abs_err << " tolerance=" << _tol << " in1[0]" << in1[0] << " in2[0]" << in2[0] << std::endl;;
506 friend std::ostream& operator<<(std::ostream& os, const AbsToleranceScalar& obj)
508 return os << "AbsToleranceScalar(" << std::to_string(obj._tol) << ")";
513 } // namespace opencv_test
517 inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_f&)
519 return os << "compare_f";
522 inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_scalar_f&)
524 return os << "compare_scalar_f";
526 } // anonymous namespace
528 // Note: namespace must match the namespace of the type of the printed object
531 inline std::ostream& operator<<(std::ostream& os, CmpTypes op)
533 #define CASE(v) case CmpTypes::v: os << #v; break
542 default: GAPI_Assert(false && "unknown CmpTypes value");
548 inline std::ostream& operator<<(std::ostream& os, NormTypes op)
550 #define CASE(v) case NormTypes::v: os << #v; break
561 default: GAPI_Assert(false && "unknown NormTypes value");
568 #endif //OPENCV_GAPI_TESTS_COMMON_HPP