// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2019 Intel Corporation
+#ifndef OPENCV_GAPI_TESTS_COMMON_HPP
+#define OPENCV_GAPI_TESTS_COMMON_HPP
#include <iostream>
+#include <tuple>
+#include <type_traits>
-#include "opencv2/ts.hpp"
-#include "opencv2/gapi.hpp"
+#include <opencv2/ts.hpp>
+#include <opencv2/gapi.hpp>
+#include <opencv2/gapi/util/util.hpp>
+
+#include "gapi_tests_helpers.hpp"
namespace
{
return cv::Scalar(s1, s2, s3, s4);
}
+ void initOutMats(cv::Size sz_in, int dtype)
+ {
+ if (dtype != -1)
+ {
+ out_mat_gapi = cv::Mat(sz_in, dtype);
+ out_mat_ocv = cv::Mat(sz_in, dtype);
+ }
+ }
+
void initMatsRandU(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
{
in_mat1 = cv::Mat(sz_in, type);
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
- if (createOutputMatrices && dtype != -1)
+ if (createOutputMatrices)
{
- out_mat_gapi = cv::Mat (sz_in, dtype);
- out_mat_ocv = cv::Mat (sz_in, dtype);
+ initOutMats(sz_in, dtype);
}
}
in_mat1 = cv::Mat(sz_in, type);
sc = initScalarRandU(100);
-
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
- if (createOutputMatrices && dtype != -1)
+ if (createOutputMatrices)
{
- out_mat_gapi = cv::Mat (sz_in, dtype);
- out_mat_ocv = cv::Mat (sz_in, dtype);
+ initOutMats(sz_in, dtype);
}
}
- void initMatsRandN(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
+ void initMatrixRandN(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
{
- in_mat1 = cv::Mat(sz_in, type);
+ in_mat1 = cv::Mat(sz_in, type);
cv::randn(in_mat1, cv::Scalar::all(127), cv::Scalar::all(40.f));
- if (createOutputMatrices && dtype != -1)
+ if (createOutputMatrices)
{
- out_mat_gapi = cv::Mat(sz_in, dtype);
- out_mat_ocv = cv::Mat(sz_in, dtype);
+ initOutMats(sz_in, dtype);
}
}
+ // empty function intended to show that nothing is to be initialized via TestFunctional methods
+ void initNothing(int, cv::Size, int, bool = true) {}
+
static cv::Mat nonZeroPixels(const cv::Mat& mat)
{
int channels = mat.channels();
using compare_scalar_f = std::function<bool(const cv::Scalar &a, const cv::Scalar &b)>;
+// FIXME: re-use MatType. current problem: "special values" interpreted incorrectly (-1 is printed
+// as 16FC512)
+struct MatType2
+{
+public:
+ MatType2(int val = 0) : _value(val) {}
+ operator int() const { return _value; }
+ friend std::ostream& operator<<(std::ostream& os, const MatType2& t)
+ {
+ switch (t)
+ {
+ case -1: return os << "SAME_TYPE";
+ default: PrintTo(MatType(t), &os); return os;
+ }
+ }
+private:
+ int _value;
+};
+
+// Universal parameter wrapper for common (pre-defined) and specific (user-defined) parameters
+template<typename ...SpecificParams>
+struct Params
+{
+ using gcomp_args_function_t = cv::GCompileArgs(*)();
+ using common_params_t = std::tuple<MatType2, cv::Size, MatType2, gcomp_args_function_t>;
+ using specific_params_t = std::tuple<SpecificParams...>;
+ using params_t = std::tuple<MatType2, cv::Size, MatType2, gcomp_args_function_t, SpecificParams...>;
+ static constexpr const size_t common_params_size = std::tuple_size<common_params_t>::value;
+ static constexpr const size_t specific_params_size = std::tuple_size<specific_params_t>::value;
+
+ template<size_t I>
+ static const typename std::tuple_element<I, common_params_t>::type&
+ getCommon(const params_t& t)
+ {
+ static_assert(I < common_params_size, "Index out of range");
+ return std::get<I>(t);
+ }
+
+ template<size_t I>
+ static const typename std::tuple_element<I, specific_params_t>::type&
+ getSpecific(const params_t& t)
+ {
+ static_assert(specific_params_size > 0,
+ "Impossible to call this function: no specific parameters specified");
+ static_assert(I < specific_params_size, "Index out of range");
+ return std::get<common_params_size + I>(t);
+ }
+};
+
+// Base class for test fixtures
+template<typename ...SpecificParams>
+struct TestWithParamBase : TestFunctional,
+ TestWithParam<typename Params<SpecificParams...>::params_t>
+{
+ using AllParams = Params<SpecificParams...>;
+
+ MatType2 type = getCommonParam<0>();
+ cv::Size sz = getCommonParam<1>();
+ MatType2 dtype = getCommonParam<2>();
+
+ // Get common (pre-defined) parameter value by index
+ template<size_t I>
+ inline auto getCommonParam() const
+ -> decltype(AllParams::template getCommon<I>(this->GetParam()))
+ {
+ return AllParams::template getCommon<I>(this->GetParam());
+ }
+
+ // Get specific (user-defined) parameter value by index
+ template<size_t I>
+ inline auto getSpecificParam() const
+ -> decltype(AllParams::template getSpecific<I>(this->GetParam()))
+ {
+ return AllParams::template getSpecific<I>(this->GetParam());
+ }
+
+ // Return G-API compile arguments specified for test fixture
+ inline cv::GCompileArgs getCompileArgs() const
+ {
+ return getCommonParam<3>()();
+ }
+};
+
+/**
+ * @private
+ * @brief Create G-API test fixture with TestWithParamBase base class
+ * @param Fixture test fixture name
+ * @param InitF callable that will initialize default available members (from TestFunctional)
+ * @param API base class API. Specifies types of user-defined parameters. If there are no such
+ * parameters, empty angle brackets ("<>") must be specified.
+ * @param Number number of user-defined parameters (corresponds to the number of types in API).
+ * if there are no such parameters, 0 must be specified.
+ * @param ... list of names of user-defined parameters. if there are no parameters, the list
+ * must be empty.
+ */
+#define GAPI_TEST_FIXTURE(Fixture, InitF, API, Number, ...) \
+ struct Fixture : public TestWithParamBase API { \
+ static_assert(Number == AllParams::specific_params_size, \
+ "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \
+ __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \
+ Fixture() { InitF(type, sz, dtype); } \
+ };
+
+// Wrapper for test fixture API. Use to specify multiple types.
+// Example: FIXTURE_API(int, bool) expands to <int, bool>
+#define FIXTURE_API(...) <__VA_ARGS__>
+
+template<typename T1, typename T2>
+struct CompareF
+{
+ using callable_t = std::function<bool(const T1& a, const T2& b)>;
+ CompareF(callable_t&& cmp, std::string&& cmp_name) :
+ _comparator(std::move(cmp)), _name(std::move(cmp_name)) {}
+ bool operator()(const T1& a, const T2& b) const
+ {
+ return _comparator(a, b);
+ }
+ friend std::ostream& operator<<(std::ostream& os, const CompareF<T1, T2>& obj)
+ {
+ return os << obj._name;
+ }
+private:
+ callable_t _comparator;
+ std::string _name;
+};
+
+using CompareMats = CompareF<cv::Mat, cv::Mat>;
+using CompareScalars = CompareF<cv::Scalar, cv::Scalar>;
template<typename T>
struct Wrappable
return t(a, b);
};
}
+
+ CompareMats to_compare_obj()
+ {
+ T t = *static_cast<T*const>(this);
+ std::stringstream ss;
+ ss << t;
+ return CompareMats(to_compare_f(), ss.str());
+ }
};
template<typename T>
return t(a, b);
};
}
+
+ CompareScalars to_compare_obj()
+ {
+ T t = *static_cast<T*const>(this);
+ std::stringstream ss;
+ ss << t;
+ return CompareScalars(to_compare_f(), ss.str());
+ }
};
return true;
}
}
-private:
+ friend std::ostream& operator<<(std::ostream& os, const AbsExact&)
+ {
+ return os << "AbsExact()";
+ }
};
class AbsTolerance : public Wrappable<AbsTolerance>
return true;
}
}
+ friend std::ostream& operator<<(std::ostream& os, const AbsTolerance& obj)
+ {
+ return os << "AbsTolerance(" << std::to_string(obj._tol) << ")";
+ }
private:
double _tol;
};
}
}
}
+ friend std::ostream& operator<<(std::ostream& os, const Tolerance_FloatRel_IntAbs& obj)
+ {
+ return os << "Tolerance_FloatRel_IntAbs(" << obj._tol << ", " << obj._tol8u << ")";
+ }
private:
double _tol;
double _tol8u;
return true;
}
}
+ friend std::ostream& operator<<(std::ostream& os, const AbsSimilarPoints& obj)
+ {
+ return os << "AbsSimilarPoints(" << obj._tol << ", " << obj._percent << ")";
+ }
private:
double _tol;
double _percent;
}
return true;
}
+ friend std::ostream& operator<<(std::ostream& os, const ToleranceFilter& obj)
+ {
+ return os << "ToleranceFilter(" << obj._tol << ", " << obj._tol8u << ", "
+ << obj._inf_tol << ")";
+ }
private:
double _tol;
double _tol8u;
}
return true;
}
+ friend std::ostream& operator<<(std::ostream& os, const ToleranceColor& obj)
+ {
+ return os << "ToleranceColor(" << obj._tol << ", " << obj._inf_tol << ")";
+ }
private:
double _tol;
double _inf_tol;
return true;
}
}
+ friend std::ostream& operator<<(std::ostream& os, const AbsToleranceScalar& obj)
+ {
+ return os << "AbsToleranceScalar(" << std::to_string(obj._tol) << ")";
+ }
private:
double _tol;
};
-
} // namespace opencv_test
namespace
{
- inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_f&)
+inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_f&)
+{
+ return os << "compare_f";
+}
+
+inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_scalar_f&)
+{
+ return os << "compare_scalar_f";
+}
+} // anonymous namespace
+
+// Note: namespace must match the namespace of the type of the printed object
+namespace cv
+{
+inline std::ostream& operator<<(std::ostream& os, CmpTypes op)
+{
+#define CASE(v) case CmpTypes::v: os << #v; break
+ switch (op)
{
- return os << "compare_f";
+ CASE(CMP_EQ);
+ CASE(CMP_GT);
+ CASE(CMP_GE);
+ CASE(CMP_LT);
+ CASE(CMP_LE);
+ CASE(CMP_NE);
+ default: GAPI_Assert(false && "unknown CmpTypes value");
}
+#undef CASE
+ return os;
}
-namespace
+inline std::ostream& operator<<(std::ostream& os, NormTypes op)
{
- inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_scalar_f&)
+#define CASE(v) case NormTypes::v: os << #v; break
+ switch (op)
{
- return os << "compare_scalar_f";
+ CASE(NORM_INF);
+ CASE(NORM_L1);
+ CASE(NORM_L2);
+ CASE(NORM_L2SQR);
+ CASE(NORM_HAMMING);
+ CASE(NORM_HAMMING2);
+ CASE(NORM_RELATIVE);
+ CASE(NORM_MINMAX);
+ default: GAPI_Assert(false && "unknown NormTypes value");
}
+#undef CASE
+ return os;
}
+} // namespace cv
+
+#endif //OPENCV_GAPI_TESTS_COMMON_HPP