diff --git a/modules/gapi/include/opencv2/gapi/garray.hpp b/modules/gapi/include/opencv2/gapi/garray.hpp index e818f0ad32..b69fb5d65b 100644 --- a/modules/gapi/include/opencv2/gapi/garray.hpp +++ b/modules/gapi/include/opencv2/gapi/garray.hpp @@ -55,6 +55,12 @@ namespace detail class VectorRef; using ConstructVec = std::function; + // 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 + struct TypeHint final : public TypeHintBase{}; // This class strips type information from GArray and makes it usable // in the G-API graph compiler (expression unrolling, graph generation, etc). @@ -64,6 +70,9 @@ namespace detail public: GArrayU(const GNode &n, std::size_t out); // Operation result constructor + template + bool holds() const; // Check if was created from GArray + GOrigin& priv(); // Internal use only const GOrigin& priv() const; // Internal use only @@ -73,7 +82,23 @@ namespace detail void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor + template + void specifyType(); // Store type of initial GArray + std::shared_ptr m_priv; + std::shared_ptr m_hint; + }; + + template + bool GArrayU::holds() const{ + GAPI_Assert(m_hint != nullptr); + using U = typename std::decay::type; + return dynamic_cast*>(m_hint.get()) != nullptr; + }; + + template + void GArrayU::specifyType(){ + m_hint.reset(new TypeHint::type>); }; // This class represents a typed STL vector reference. @@ -239,7 +264,10 @@ public: private: static void VCTor(detail::VectorRef& vref) { vref.reset(); } - void putDetails() {m_ref.setConstructFcn(&VCTor); } + void putDetails() { + m_ref.setConstructFcn(&VCTor); + m_ref.specifyType(); + } detail::GArrayU m_ref; }; diff --git a/modules/gapi/include/opencv2/gapi/gtransform.hpp b/modules/gapi/include/opencv2/gapi/gtransform.hpp index e8ce161a24..5d1b91b517 100644 --- a/modules/gapi/include/opencv2/gapi/gtransform.hpp +++ b/modules/gapi/include/opencv2/gapi/gtransform.hpp @@ -16,13 +16,16 @@ #include #include #include +#include namespace cv { struct GAPI_EXPORTS GTransform { - using F = std::function; + // FIXME: consider another simplified + // class instead of GComputation + using F = std::function; std::string description; F pattern; @@ -41,20 +44,22 @@ template struct TransHelper, Out> { template - static GArgs invoke(Callable f, const GArgs &in_args, Seq, Seq) + static GComputation invoke(Callable f, Seq, Seq) { - const auto r = tuple_wrap_helper::get(f(in_args.at(IIs).template get()...)); - return GArgs{GArg(std::get(r))...}; + const std::tuple ins; + const auto r = tuple_wrap_helper::get(f(std::get(ins)...)); + return GComputation(cv::GIn(std::get(ins)...), + cv::GOut(std::get(r)...)); } - static GArgs get_pattern(const GArgs &in_args) + static GComputation get_pattern() { - return invoke(K::pattern, in_args, typename MkSeq::type(), + return invoke(K::pattern, typename MkSeq::type(), typename MkSeq::type>::value>::type()); } - static GArgs get_substitute(const GArgs &in_args) + static GComputation get_substitute() { - return invoke(K::substitute, in_args, typename MkSeq::type(), + return invoke(K::substitute, typename MkSeq::type(), typename MkSeq::type>::value>::type()); } }; diff --git a/modules/gapi/test/gapi_transform_tests.cpp b/modules/gapi/test/gapi_transform_tests.cpp index f946499a7f..c18e930e06 100644 --- a/modules/gapi/test/gapi_transform_tests.cpp +++ b/modules/gapi/test/gapi_transform_tests.cpp @@ -8,6 +8,9 @@ #include "test_precomp.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 { @@ -68,6 +71,12 @@ GAPI_TRANSFORM(gmat_in_garr_out, (GMat)>, "gmat_in_garr_out") static GArray substitute(GMat) { return {}; } }; +GAPI_TRANSFORM(gmat_gsc_garray_in_gmat2_out, )>, "gmat_gsc_garray_in_gmat2_out") +{ + static GMat2 pattern(GMat, GScalar, GArray) { return {}; } + static GMat2 substitute(GMat, GScalar, GArray) { return {}; } +}; + } // anonymous namespace TEST(KernelPackageTransform, CreatePackage) @@ -76,12 +85,16 @@ TEST(KernelPackageTransform, CreatePackage) < gmat_in_gmat_out , gmat2_in_gmat_out , gmat2_in_gmat3_out + , gmatp_in_gmatp_out , gsc_in_gmat_out , gmat_in_gsc_out + , garr_in_gmat_out + , gmat_in_garr_out + , gmat_gsc_garray_in_gmat2_out >(); auto tr = pkg.get_transformations(); - EXPECT_EQ(5u, tr.size()); + EXPECT_EQ(9u, tr.size()); } TEST(KernelPackageTransform, Include) @@ -103,81 +116,74 @@ TEST(KernelPackageTransform, Combine) EXPECT_EQ(2u, tr.size()); } -TEST(KernelPackageTransform, Pattern) -{ - auto tr = gmat2_in_gmat3_out::transformation(); - GMat a, b; - 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()); +namespace { + template + inline bool ProtoContainsT(const cv::GProtoArg &arg) { + return cv::GProtoArg::index_of() == arg.index(); } -} +} // anonymous namespace -TEST(KernelPackageTransform, Substitute) +TEST(KernelPackageTransform, gmat_gsc_in_gmat_out) { - auto tr = gmat2_in_gmat3_out::transformation(); - GMat a, b; - auto subst = tr.substitute({cv::GArg(a), cv::GArg(b)}); + auto tr = gmat_gsc_garray_in_gmat2_out::transformation(); - EXPECT_EQ(3u, subst.size()); - for (const auto& s : subst) - { - EXPECT_NO_THROW(s.get()); - } -} + auto check = [](const cv::GComputation &comp){ + const auto &p = comp.priv(); + EXPECT_EQ(3u, p.m_ins.size()); + EXPECT_EQ(2u, p.m_outs.size()); -template -static void transformTest() -{ - auto tr = Transformation::transformation(); - InType in; - auto pattern = tr.pattern({cv::GArg(in)}); - auto subst = tr.substitute({cv::GArg(in)}); + EXPECT_TRUE(ProtoContainsT(p.m_ins[0])); + EXPECT_TRUE(ProtoContainsT(p.m_ins[1])); + EXPECT_TRUE(ProtoContainsT(p.m_ins[2])); + EXPECT_TRUE(cv::util::get(p.m_ins[2]).holds()); + EXPECT_FALSE(cv::util::get(p.m_ins[2]).holds()); - EXPECT_EQ(1u, pattern.size()); - EXPECT_EQ(1u, subst.size()); - - auto checkOut = [](GArg& garg) { - EXPECT_TRUE(garg.kind == cv::detail::GTypeTraits::kind); - EXPECT_NO_THROW(garg.get()); + EXPECT_TRUE(ProtoContainsT(p.m_outs[0])); + EXPECT_TRUE(ProtoContainsT(p.m_outs[1])); }; - checkOut(pattern[0]); - checkOut(subst[0]); + check(tr.pattern()); + check(tr.substitute()); } -TEST(KernelPackageTransform, GMat) +TEST(KernelPackageTransform, gmat_in_garr_out) { - transformTest(); + 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(p.m_ins[0])); + + EXPECT_TRUE(ProtoContainsT(p.m_outs[0])); + EXPECT_TRUE(cv::util::get(p.m_outs[0]).holds()); + EXPECT_FALSE(cv::util::get(p.m_outs[0]).holds()); + }; + + check(tr.pattern()); + check(tr.substitute()); } -TEST(KernelPackageTransform, GMatP) +TEST(KernelPackageTransform, garr_in_gmat_out) { - transformTest(); -} + auto tr = garr_in_gmat_out::transformation(); -TEST(KernelPackageTransform, GScalarIn) -{ - transformTest(); -} + 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()); -TEST(KernelPackageTransform, GScalarOut) -{ - transformTest(); -} + EXPECT_TRUE(ProtoContainsT(p.m_ins[0])); + EXPECT_TRUE(cv::util::get(p.m_ins[0]).holds()); + EXPECT_FALSE(cv::util::get(p.m_ins[0]).holds()); -TEST(KernelPackageTransform, DISABLED_GArrayIn) -{ - transformTest, GMat>(); -} + EXPECT_TRUE(ProtoContainsT(p.m_outs[0])); + }; -TEST(KernelPackageTransform, DISABLED_GArrayOut) -{ - transformTest>(); + check(tr.pattern()); + check(tr.substitute()); } } // namespace opencv_test