mirror of
https://github.com/opencv/opencv.git
synced 2025-07-25 22:57:53 +08:00
Merge pull request #14952 from smirnov-alexey:gapi_transform_macro_rework
G-API: GAPI_TRANSFORM internal functionality rework (#14952) * Change internal pattern and substitute signatures and refactor tests * Enhance GArrayU with type-checker function Add a couple of new tests on GAPI_TRANSFORM
This commit is contained in:
parent
89f23a35c5
commit
8313209704
@ -55,6 +55,12 @@ namespace detail
|
|||||||
class VectorRef;
|
class VectorRef;
|
||||||
using ConstructVec = std::function<void(VectorRef&)>;
|
using ConstructVec = std::function<void(VectorRef&)>;
|
||||||
|
|
||||||
|
// This is the base struct for GArrayU type holder
|
||||||
|
struct TypeHintBase{virtual ~TypeHintBase() = default;};
|
||||||
|
|
||||||
|
// This class holds type of initial GArray to be checked from GArrayU
|
||||||
|
template <typename T>
|
||||||
|
struct TypeHint final : public TypeHintBase{};
|
||||||
|
|
||||||
// This class strips type information from GArray<T> and makes it usable
|
// This class strips type information from GArray<T> and makes it usable
|
||||||
// in the G-API graph compiler (expression unrolling, graph generation, etc).
|
// in the G-API graph compiler (expression unrolling, graph generation, etc).
|
||||||
@ -64,6 +70,9 @@ namespace detail
|
|||||||
public:
|
public:
|
||||||
GArrayU(const GNode &n, std::size_t out); // Operation result constructor
|
GArrayU(const GNode &n, std::size_t out); // Operation result constructor
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool holds() const; // Check if was created from GArray<T>
|
||||||
|
|
||||||
GOrigin& priv(); // Internal use only
|
GOrigin& priv(); // Internal use only
|
||||||
const GOrigin& priv() const; // Internal use only
|
const GOrigin& priv() const; // Internal use only
|
||||||
|
|
||||||
@ -73,7 +82,23 @@ namespace detail
|
|||||||
|
|
||||||
void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor
|
void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void specifyType(); // Store type of initial GArray<T>
|
||||||
|
|
||||||
std::shared_ptr<GOrigin> m_priv;
|
std::shared_ptr<GOrigin> m_priv;
|
||||||
|
std::shared_ptr<TypeHintBase> m_hint;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool GArrayU::holds() const{
|
||||||
|
GAPI_Assert(m_hint != nullptr);
|
||||||
|
using U = typename std::decay<T>::type;
|
||||||
|
return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void GArrayU::specifyType(){
|
||||||
|
m_hint.reset(new TypeHint<typename std::decay<T>::type>);
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class represents a typed STL vector reference.
|
// This class represents a typed STL vector reference.
|
||||||
@ -239,7 +264,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static void VCTor(detail::VectorRef& vref) { vref.reset<T>(); }
|
static void VCTor(detail::VectorRef& vref) { vref.reset<T>(); }
|
||||||
void putDetails() {m_ref.setConstructFcn(&VCTor); }
|
void putDetails() {
|
||||||
|
m_ref.setConstructFcn(&VCTor);
|
||||||
|
m_ref.specifyType<T>();
|
||||||
|
}
|
||||||
|
|
||||||
detail::GArrayU m_ref;
|
detail::GArrayU m_ref;
|
||||||
};
|
};
|
||||||
|
@ -16,13 +16,16 @@
|
|||||||
#include <opencv2/gapi/garg.hpp>
|
#include <opencv2/gapi/garg.hpp>
|
||||||
#include <opencv2/gapi/gtype_traits.hpp>
|
#include <opencv2/gapi/gtype_traits.hpp>
|
||||||
#include <opencv2/gapi/util/compiler_hints.hpp>
|
#include <opencv2/gapi/util/compiler_hints.hpp>
|
||||||
|
#include <opencv2/gapi/gcomputation.hpp>
|
||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
|
|
||||||
struct GAPI_EXPORTS GTransform
|
struct GAPI_EXPORTS GTransform
|
||||||
{
|
{
|
||||||
using F = std::function<GArgs(const GArgs &)>;
|
// FIXME: consider another simplified
|
||||||
|
// class instead of GComputation
|
||||||
|
using F = std::function<GComputation()>;
|
||||||
|
|
||||||
std::string description;
|
std::string description;
|
||||||
F pattern;
|
F pattern;
|
||||||
@ -41,20 +44,22 @@ template <typename K, typename... Ins, typename Out>
|
|||||||
struct TransHelper<K, std::tuple<Ins...>, Out>
|
struct TransHelper<K, std::tuple<Ins...>, Out>
|
||||||
{
|
{
|
||||||
template <typename Callable, int... IIs, int... OIs>
|
template <typename Callable, int... IIs, int... OIs>
|
||||||
static GArgs invoke(Callable f, const GArgs &in_args, Seq<IIs...>, Seq<OIs...>)
|
static GComputation invoke(Callable f, Seq<IIs...>, Seq<OIs...>)
|
||||||
{
|
{
|
||||||
const auto r = tuple_wrap_helper<Out>::get(f(in_args.at(IIs).template get<Ins>()...));
|
const std::tuple<Ins...> ins;
|
||||||
return GArgs{GArg(std::get<OIs>(r))...};
|
const auto r = tuple_wrap_helper<Out>::get(f(std::get<IIs>(ins)...));
|
||||||
|
return GComputation(cv::GIn(std::get<IIs>(ins)...),
|
||||||
|
cv::GOut(std::get<OIs>(r)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GArgs get_pattern(const GArgs &in_args)
|
static GComputation get_pattern()
|
||||||
{
|
{
|
||||||
return invoke(K::pattern, in_args, typename MkSeq<sizeof...(Ins)>::type(),
|
return invoke(K::pattern, typename MkSeq<sizeof...(Ins)>::type(),
|
||||||
typename MkSeq<std::tuple_size<typename tuple_wrap_helper<Out>::type>::value>::type());
|
typename MkSeq<std::tuple_size<typename tuple_wrap_helper<Out>::type>::value>::type());
|
||||||
}
|
}
|
||||||
static GArgs get_substitute(const GArgs &in_args)
|
static GComputation get_substitute()
|
||||||
{
|
{
|
||||||
return invoke(K::substitute, in_args, typename MkSeq<sizeof...(Ins)>::type(),
|
return invoke(K::substitute, typename MkSeq<sizeof...(Ins)>::type(),
|
||||||
typename MkSeq<std::tuple_size<typename tuple_wrap_helper<Out>::type>::value>::type());
|
typename MkSeq<std::tuple_size<typename tuple_wrap_helper<Out>::type>::value>::type());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
#include "opencv2/gapi/gtransform.hpp"
|
#include "opencv2/gapi/gtransform.hpp"
|
||||||
|
#include "opencv2/gapi/gtype_traits.hpp"
|
||||||
|
// explicit include to use GComputation::Priv
|
||||||
|
#include "api/gcomputation_priv.hpp"
|
||||||
|
|
||||||
namespace opencv_test
|
namespace opencv_test
|
||||||
{
|
{
|
||||||
@ -68,6 +71,12 @@ GAPI_TRANSFORM(gmat_in_garr_out, <GArray<int>(GMat)>, "gmat_in_garr_out")
|
|||||||
static GArray<int> substitute(GMat) { return {}; }
|
static GArray<int> substitute(GMat) { return {}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GAPI_TRANSFORM(gmat_gsc_garray_in_gmat2_out, <GMat2(GMat, GScalar, GArray<int>)>, "gmat_gsc_garray_in_gmat2_out")
|
||||||
|
{
|
||||||
|
static GMat2 pattern(GMat, GScalar, GArray<int>) { return {}; }
|
||||||
|
static GMat2 substitute(GMat, GScalar, GArray<int>) { return {}; }
|
||||||
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
TEST(KernelPackageTransform, CreatePackage)
|
TEST(KernelPackageTransform, CreatePackage)
|
||||||
@ -76,12 +85,16 @@ TEST(KernelPackageTransform, CreatePackage)
|
|||||||
< gmat_in_gmat_out
|
< gmat_in_gmat_out
|
||||||
, gmat2_in_gmat_out
|
, gmat2_in_gmat_out
|
||||||
, gmat2_in_gmat3_out
|
, gmat2_in_gmat3_out
|
||||||
|
, gmatp_in_gmatp_out
|
||||||
, gsc_in_gmat_out
|
, gsc_in_gmat_out
|
||||||
, gmat_in_gsc_out
|
, gmat_in_gsc_out
|
||||||
|
, garr_in_gmat_out
|
||||||
|
, gmat_in_garr_out
|
||||||
|
, gmat_gsc_garray_in_gmat2_out
|
||||||
>();
|
>();
|
||||||
|
|
||||||
auto tr = pkg.get_transformations();
|
auto tr = pkg.get_transformations();
|
||||||
EXPECT_EQ(5u, tr.size());
|
EXPECT_EQ(9u, tr.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(KernelPackageTransform, Include)
|
TEST(KernelPackageTransform, Include)
|
||||||
@ -103,81 +116,74 @@ TEST(KernelPackageTransform, Combine)
|
|||||||
EXPECT_EQ(2u, tr.size());
|
EXPECT_EQ(2u, tr.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(KernelPackageTransform, Pattern)
|
namespace {
|
||||||
{
|
template <typename T>
|
||||||
auto tr = gmat2_in_gmat3_out::transformation();
|
inline bool ProtoContainsT(const cv::GProtoArg &arg) {
|
||||||
GMat a, b;
|
return cv::GProtoArg::index_of<T>() == arg.index();
|
||||||
auto pattern = tr.pattern({cv::GArg(a), cv::GArg(b)});
|
|
||||||
|
|
||||||
// return type of '2gmat_in_gmat3_out' is GMat3
|
|
||||||
EXPECT_EQ(3u, pattern.size());
|
|
||||||
for (const auto& p : pattern)
|
|
||||||
{
|
|
||||||
EXPECT_NO_THROW(p.get<GMat>());
|
|
||||||
}
|
}
|
||||||
}
|
} // anonymous namespace
|
||||||
|
|
||||||
TEST(KernelPackageTransform, Substitute)
|
TEST(KernelPackageTransform, gmat_gsc_in_gmat_out)
|
||||||
{
|
{
|
||||||
auto tr = gmat2_in_gmat3_out::transformation();
|
auto tr = gmat_gsc_garray_in_gmat2_out::transformation();
|
||||||
GMat a, b;
|
|
||||||
auto subst = tr.substitute({cv::GArg(a), cv::GArg(b)});
|
|
||||||
|
|
||||||
EXPECT_EQ(3u, subst.size());
|
auto check = [](const cv::GComputation &comp){
|
||||||
for (const auto& s : subst)
|
const auto &p = comp.priv();
|
||||||
{
|
EXPECT_EQ(3u, p.m_ins.size());
|
||||||
EXPECT_NO_THROW(s.get<GMat>());
|
EXPECT_EQ(2u, p.m_outs.size());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Transformation, typename InType, typename OutType>
|
EXPECT_TRUE(ProtoContainsT<GMat>(p.m_ins[0]));
|
||||||
static void transformTest()
|
EXPECT_TRUE(ProtoContainsT<GScalar>(p.m_ins[1]));
|
||||||
{
|
EXPECT_TRUE(ProtoContainsT<cv::detail::GArrayU>(p.m_ins[2]));
|
||||||
auto tr = Transformation::transformation();
|
EXPECT_TRUE(cv::util::get<cv::detail::GArrayU>(p.m_ins[2]).holds<int>());
|
||||||
InType in;
|
EXPECT_FALSE(cv::util::get<cv::detail::GArrayU>(p.m_ins[2]).holds<char>());
|
||||||
auto pattern = tr.pattern({cv::GArg(in)});
|
|
||||||
auto subst = tr.substitute({cv::GArg(in)});
|
|
||||||
|
|
||||||
EXPECT_EQ(1u, pattern.size());
|
EXPECT_TRUE(ProtoContainsT<GMat>(p.m_outs[0]));
|
||||||
EXPECT_EQ(1u, subst.size());
|
EXPECT_TRUE(ProtoContainsT<GMat>(p.m_outs[1]));
|
||||||
|
|
||||||
auto checkOut = [](GArg& garg) {
|
|
||||||
EXPECT_TRUE(garg.kind == cv::detail::GTypeTraits<OutType>::kind);
|
|
||||||
EXPECT_NO_THROW(garg.get<OutType>());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
checkOut(pattern[0]);
|
check(tr.pattern());
|
||||||
checkOut(subst[0]);
|
check(tr.substitute());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(KernelPackageTransform, GMat)
|
TEST(KernelPackageTransform, gmat_in_garr_out)
|
||||||
{
|
{
|
||||||
transformTest<gmat_in_gmat_out, GMat, GMat>();
|
auto tr = gmat_in_garr_out::transformation();
|
||||||
|
|
||||||
|
auto check = [](const cv::GComputation &comp){
|
||||||
|
const auto &p = comp.priv();
|
||||||
|
EXPECT_EQ(1u, p.m_ins.size());
|
||||||
|
EXPECT_EQ(1u, p.m_outs.size());
|
||||||
|
|
||||||
|
EXPECT_TRUE(ProtoContainsT<GMat>(p.m_ins[0]));
|
||||||
|
|
||||||
|
EXPECT_TRUE(ProtoContainsT<cv::detail::GArrayU>(p.m_outs[0]));
|
||||||
|
EXPECT_TRUE(cv::util::get<cv::detail::GArrayU>(p.m_outs[0]).holds<int>());
|
||||||
|
EXPECT_FALSE(cv::util::get<cv::detail::GArrayU>(p.m_outs[0]).holds<float>());
|
||||||
|
};
|
||||||
|
|
||||||
|
check(tr.pattern());
|
||||||
|
check(tr.substitute());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(KernelPackageTransform, GMatP)
|
TEST(KernelPackageTransform, garr_in_gmat_out)
|
||||||
{
|
{
|
||||||
transformTest<gmatp_in_gmatp_out, GMatP, GMatP>();
|
auto tr = garr_in_gmat_out::transformation();
|
||||||
}
|
|
||||||
|
|
||||||
TEST(KernelPackageTransform, GScalarIn)
|
auto check = [](const cv::GComputation &comp){
|
||||||
{
|
const auto &p = comp.priv();
|
||||||
transformTest<gsc_in_gmat_out, GScalar, GMat>();
|
EXPECT_EQ(1u, p.m_ins.size());
|
||||||
}
|
EXPECT_EQ(1u, p.m_outs.size());
|
||||||
|
|
||||||
TEST(KernelPackageTransform, GScalarOut)
|
EXPECT_TRUE(ProtoContainsT<cv::detail::GArrayU>(p.m_ins[0]));
|
||||||
{
|
EXPECT_TRUE(cv::util::get<cv::detail::GArrayU>(p.m_ins[0]).holds<int>());
|
||||||
transformTest<gmat_in_gsc_out, GMat, GScalar>();
|
EXPECT_FALSE(cv::util::get<cv::detail::GArrayU>(p.m_ins[0]).holds<bool>());
|
||||||
}
|
|
||||||
|
|
||||||
TEST(KernelPackageTransform, DISABLED_GArrayIn)
|
EXPECT_TRUE(ProtoContainsT<GMat>(p.m_outs[0]));
|
||||||
{
|
};
|
||||||
transformTest<garr_in_gmat_out, GArray<int>, GMat>();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(KernelPackageTransform, DISABLED_GArrayOut)
|
check(tr.pattern());
|
||||||
{
|
check(tr.substitute());
|
||||||
transformTest<gmat_in_garr_out, GMat, GArray<int>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace opencv_test
|
} // namespace opencv_test
|
||||||
|
Loading…
Reference in New Issue
Block a user