From a3e8c6e866125bbae5ad4d8b0cb24371761c5968 Mon Sep 17 00:00:00 2001 From: Alexey Smirnov Date: Mon, 7 Sep 2020 20:10:03 +0300 Subject: [PATCH] Merge pull request #18127 from smirnov-alexey:as/gapi_serialization [G-API]: Add GOpaque and GArray serialization support * Add GOpaque and GArray serialization support * Address review comments * Remove holds() method * Address review comments * Remove comments * Align streaming with kind changes * Fix kind in kernel * Address review comments --- modules/gapi/include/opencv2/gapi/garg.hpp | 5 +- modules/gapi/include/opencv2/gapi/garray.hpp | 70 ++++--- modules/gapi/include/opencv2/gapi/gcommon.hpp | 34 ++++ modules/gapi/include/opencv2/gapi/gkernel.hpp | 14 +- modules/gapi/include/opencv2/gapi/gopaque.hpp | 35 +++- modules/gapi/include/opencv2/gapi/gtype_traits.hpp | 68 +------ modules/gapi/src/api/garray.cpp | 7 +- modules/gapi/src/api/gopaque.cpp | 7 +- modules/gapi/src/api/gorigin.cpp | 9 +- modules/gapi/src/api/gorigin.hpp | 7 +- modules/gapi/src/api/s11n.cpp | 35 ++++ modules/gapi/src/backends/common/serialization.cpp | 130 +++++++++++-- modules/gapi/src/backends/common/serialization.hpp | 9 +- modules/gapi/src/backends/cpu/gcpubackend.cpp | 2 +- modules/gapi/src/backends/ie/giebackend.cpp | 8 +- modules/gapi/src/compiler/gmodel.cpp | 7 +- modules/gapi/src/compiler/gmodel.hpp | 4 +- modules/gapi/src/compiler/gmodelbuilder.cpp | 4 +- modules/gapi/src/compiler/gobjref.hpp | 1 - modules/gapi/src/compiler/passes/meta.cpp | 29 +-- modules/gapi/test/gapi_array_tests.cpp | 32 +++- modules/gapi/test/gapi_opaque_tests.cpp | 21 +++ modules/gapi/test/internal/gapi_int_garg_test.cpp | 57 ------ .../test/internal/gapi_int_gmodel_builder_test.cpp | 9 +- modules/gapi/test/s11n/gapi_s11n_tests.cpp | 70 ++++++- .../gapi/test/s11n/gapi_sample_pipelines_s11n.cpp | 202 +++++++++++++++++++++ 26 files changed, 648 insertions(+), 228 deletions(-) diff --git a/modules/gapi/include/opencv2/gapi/garg.hpp b/modules/gapi/include/opencv2/gapi/garg.hpp index 3f243a8..cca080d 100644 --- a/modules/gapi/include/opencv2/gapi/garg.hpp +++ b/modules/gapi/include/opencv2/gapi/garg.hpp @@ -2,7 +2,7 @@ // 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-2020 Intel Corporation #ifndef OPENCV_GAPI_GARG_HPP @@ -170,7 +170,8 @@ inline GRunArgsP& operator += (GRunArgsP &lhs, const GRunArgsP &rhs) namespace gapi { GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &results); -} // namespace gapi + GAPI_EXPORTS cv::GRunArg bind(cv::GRunArgP &out); // FIXME: think more about it +} template inline GRunArgs gin(const Ts&... args) { diff --git a/modules/gapi/include/opencv2/gapi/garray.hpp b/modules/gapi/include/opencv2/gapi/garray.hpp index 3f18af9..99f6661 100644 --- a/modules/gapi/include/opencv2/gapi/garray.hpp +++ b/modules/gapi/include/opencv2/gapi/garray.hpp @@ -2,7 +2,7 @@ // 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-2020 Intel Corporation #ifndef OPENCV_GAPI_GARRAY_HPP @@ -49,31 +49,6 @@ std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc); namespace detail { - // FIXME: This type spec needs to be: - // 1) shared with GOpaque (not needed right now) - // 2) unified with the serialization (S11N, not merged right now). - // Adding it to type traits is problematic due to our header deps - // (which also need to be fixed). - enum class TypeSpec: int { - OPAQUE_SPEC, - MAT, - RECT - }; - // FIXME: Reuse the below from "opaque traits" of S11N! - template struct GTypeSpec; - template struct GTypeSpec - { - static constexpr const TypeSpec spec = TypeSpec::OPAQUE_SPEC; - }; - template<> struct GTypeSpec - { - static constexpr const TypeSpec spec = TypeSpec::MAT; - }; - template<> struct GTypeSpec - { - static constexpr const TypeSpec spec = TypeSpec::RECT; - }; - // ConstructVec is a callback which stores information about T and is used by // G-API runtime to construct arrays in host memory (T remains opaque for G-API). // ConstructVec is carried into G-API internals by GArrayU. @@ -112,6 +87,11 @@ namespace detail template void specifyType(); // Store type of initial GArray + template + void storeKind(); + + void setKind(cv::detail::OpaqueKind); + std::shared_ptr m_priv; std::shared_ptr m_hint; }; @@ -128,6 +108,11 @@ namespace detail m_hint.reset(new TypeHint::type>); }; + template + void GArrayU::storeKind(){ + setKind(cv::detail::GOpaqueTraits::kind); + }; + // This class represents a typed STL vector reference. // Depending on origins, this reference may be either "just a" reference to // an object created externally, OR actually own the underlying object @@ -138,7 +123,6 @@ namespace detail // These fields are set by the derived class(es) std::size_t m_elemSize = 0ul; cv::GArrayDesc m_desc; - TypeSpec m_spec; virtual ~BasicVectorRef() {} virtual void mov(BasicVectorRef &ref) = 0; @@ -163,7 +147,6 @@ namespace detail { m_elemSize = sizeof(T); if (vec) m_desc = cv::descr_of(*vec); - m_spec = GTypeSpec::spec; } public: @@ -238,7 +221,6 @@ namespace detail wref() = std::move(tv->wref()); } - virtual const void* ptr() const override { return &rref(); } virtual std::size_t size() const override { return rref().size(); } }; @@ -253,6 +235,7 @@ namespace detail class VectorRef { std::shared_ptr m_ref; + cv::detail::OpaqueKind m_kind; template inline void check() const { @@ -262,9 +245,17 @@ namespace detail public: VectorRef() = default; - template explicit VectorRef(const std::vector& vec) : m_ref(new VectorRefT(vec)) {} - template explicit VectorRef(std::vector& vec) : m_ref(new VectorRefT(vec)) {} - template explicit VectorRef(std::vector&& vec) : m_ref(new VectorRefT(vec)) {} + template explicit VectorRef(const std::vector& vec) : + m_ref(new VectorRefT(vec)), m_kind(GOpaqueTraits::kind) {} + template explicit VectorRef(std::vector& vec) : + m_ref(new VectorRefT(vec)), m_kind(GOpaqueTraits::kind) {} + template explicit VectorRef(std::vector&& vec) : + m_ref(new VectorRefT(std::move(vec))), m_kind(GOpaqueTraits::kind) {} + + cv::detail::OpaqueKind getKind() const + { + return m_kind; + } template void reset() { @@ -274,6 +265,12 @@ namespace detail static_cast&>(*m_ref).reset(); } + template + void storeKind() + { + m_kind = cv::detail::GOpaqueTraits::kind; + } + template std::vector& wref() { check(); @@ -303,11 +300,6 @@ namespace detail // May be used to uniquely identify this object internally const void *ptr() const { return m_ref->ptr(); } - - TypeSpec spec() const - { - return m_ref->m_spec; - } }; // Helper (FIXME: work-around?) @@ -349,10 +341,12 @@ private: static void VCTor(detail::VectorRef& vref) { vref.reset(); + vref.storeKind(); } void putDetails() { m_ref.setConstructFcn(&VCTor); - m_ref.specifyType(); + m_ref.specifyType(); // FIXME: to unify those 2 to avoid excessive dynamic_cast + m_ref.storeKind(); // } detail::GArrayU m_ref; diff --git a/modules/gapi/include/opencv2/gapi/gcommon.hpp b/modules/gapi/include/opencv2/gapi/gcommon.hpp index adece19..06499c1 100644 --- a/modules/gapi/include/opencv2/gapi/gcommon.hpp +++ b/modules/gapi/include/opencv2/gapi/gcommon.hpp @@ -21,6 +21,8 @@ namespace cv { +class GMat; // FIXME: forward declaration for GOpaqueTraits + namespace detail { // This is a trait-like structure to mark backend-specific compile arguments @@ -32,6 +34,38 @@ namespace detail {}; struct TransformTag {}; + + // This enum is utilized mostly by GArray and GOpaque to store and recognize their internal data + // types (aka Host type). Also it is widely used during serialization routine. + enum class OpaqueKind: int + { + CV_UNKNOWN, // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization + CV_BOOL, // bool user G-API data + CV_INT, // int user G-API data + CV_DOUBLE, // double user G-API data + CV_POINT, // cv::Point user G-API data + CV_SIZE, // cv::Size user G-API data + CV_RECT, // cv::Rect user G-API data + CV_SCALAR, // cv::Scalar user G-API data + CV_MAT, // cv::Mat user G-API data + }; + + // Type traits helper which simplifies the extraction of kind from type + template struct GOpaqueTraits; + template struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; + // GArray is not supporting bool type for now due to difference in std::vector implementation + using GOpaqueTraitsArrayTypes = std::tuple; + // GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types + using GOpaqueTraitsOpaqueTypes = std::tuple; } // namespace detail // This definition is here because it is reused by both public(?) and internal diff --git a/modules/gapi/include/opencv2/gapi/gkernel.hpp b/modules/gapi/include/opencv2/gapi/gkernel.hpp index bd8cf63..bd96933 100644 --- a/modules/gapi/include/opencv2/gapi/gkernel.hpp +++ b/modules/gapi/include/opencv2/gapi/gkernel.hpp @@ -26,8 +26,8 @@ namespace cv { -using GSpecs = std::vector; using GShapes = std::vector; +using GKinds = std::vector; // GKernel describes kernel API to the system // FIXME: add attributes of a kernel, (e.g. number and types @@ -39,10 +39,10 @@ struct GAPI_EXPORTS GKernel const std::string name; // kernel ID, defined by its API (signature) const std::string tag; // some (implementation-specific) tag const M outMeta; // generic adaptor to API::outMeta(...) - const GSpecs inSpecs; // specs of kernel's inputs (FIXME: below) const GShapes outShapes; // types (shapes) kernel's outputs + const GKinds inKinds; // kinds of kernel's inputs (fixme: below) }; -// TODO: It's questionable if inSpecs should really be here. Instead, +// TODO: It's questionable if inKinds should really be here. Instead, // this information could come from meta. // GKernelImpl describes particular kernel implementation to the system @@ -213,8 +213,8 @@ public: cv::GCall call(GKernel{ K::id() , K::tag() , &K::getOutMeta - , {detail::GTypeTraits::spec...} - , {detail::GTypeTraits::shape...}}); + , {detail::GTypeTraits::shape...} + , {detail::GTypeTraits::op_kind...}}); call.pass(args...); // TODO: std::forward() here? return yield(call, typename detail::MkSeq::type()); } @@ -238,8 +238,8 @@ public: cv::GCall call(GKernel{ K::id() , K::tag() , &K::getOutMeta - , {detail::GTypeTraits::spec...} - , {detail::GTypeTraits::shape}}); + , {detail::GTypeTraits::shape} + , {detail::GTypeTraits::op_kind...}}); call.pass(args...); return detail::Yield::yield(call, 0); } diff --git a/modules/gapi/include/opencv2/gapi/gopaque.hpp b/modules/gapi/include/opencv2/gapi/gopaque.hpp index 7d3d663..9cfd588 100644 --- a/modules/gapi/include/opencv2/gapi/gopaque.hpp +++ b/modules/gapi/include/opencv2/gapi/gopaque.hpp @@ -2,7 +2,7 @@ // 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) 2019 Intel Corporation +// Copyright (C) 2019-2020 Intel Corporation #ifndef OPENCV_GAPI_GOPAQUE_HPP @@ -46,7 +46,6 @@ std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &desc); namespace detail { - // ConstructOpaque is a callback which stores information about T and is used by // G-API runtime to construct an object in host memory (T remains opaque for G-API). // ConstructOpaque is carried into G-API internals by GOpaqueU. @@ -81,6 +80,11 @@ namespace detail template void specifyType(); // Store type of initial GOpaque + template + void storeKind(); + + void setKind(cv::detail::OpaqueKind); + std::shared_ptr m_priv; std::shared_ptr m_hint; }; @@ -97,6 +101,12 @@ namespace detail m_hint.reset(new TypeHint>); }; + template + void GOpaqueU::storeKind(){ + // FIXME: Add assert here on cv::Mat and cv::Scalar? + setKind(cv::detail::GOpaqueTraits::kind); + }; + // This class represents a typed object reference. // Depending on origins, this reference may be either "just a" reference to // an object created externally, OR actually own the underlying object @@ -213,6 +223,7 @@ namespace detail class OpaqueRef { std::shared_ptr m_ref; + cv::detail::OpaqueKind m_kind; template inline void check() const { @@ -222,13 +233,19 @@ namespace detail public: OpaqueRef() = default; - template< typename T, typename = util::are_different_t > + // FIXME: probably won't work with const object explicit OpaqueRef(T&& obj) : - m_ref(new OpaqueRefT>(std::forward(obj))) {} + m_ref(new OpaqueRefT>(std::forward(obj))), + m_kind(GOpaqueTraits::kind) {} + + cv::detail::OpaqueKind getKind() const + { + return m_kind; + } template void reset() { @@ -238,6 +255,12 @@ namespace detail static_cast&>(*m_ref).reset(); } + template + void storeKind() + { + m_kind = cv::detail::GOpaqueTraits::kind; + } + template T& wref() { check(); @@ -285,10 +308,12 @@ private: static void CTor(detail::OpaqueRef& ref) { ref.reset(); + ref.storeKind(); } void putDetails() { m_ref.setConstructFcn(&CTor); - m_ref.specifyType(); + m_ref.specifyType(); // FIXME: to unify those 2 to avoid excessive dynamic_cast + m_ref.storeKind(); // } detail::GOpaqueU m_ref; diff --git a/modules/gapi/include/opencv2/gapi/gtype_traits.hpp b/modules/gapi/include/opencv2/gapi/gtype_traits.hpp index 0f22e3b..9b1c693 100644 --- a/modules/gapi/include/opencv2/gapi/gtype_traits.hpp +++ b/modules/gapi/include/opencv2/gapi/gtype_traits.hpp @@ -41,98 +41,45 @@ namespace detail GOPAQUE, // a cv::GOpaqueU (note - exactly GOpaqueU, not GOpaque!) }; - // This enum captures some information about T in GArray and GOpaque - enum class ArgSpec: int - { - OPAQUE_SPEC, // Unknown, generic, opaque-to-GAPI data type - GMAT, // a GMat - RECT, // a cv::Rect - // NB: Add more types when required - }; - - // Describe specialization types of interest first - // FIXME: It comes to GArg but ideally it should go to *Desc{} - // type family. Bringing it there is a more massive change though. - template struct GSpecTraits; - template struct GSpecTraits - { - static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC; - }; - template<> struct GSpecTraits - { - static constexpr const ArgSpec spec = ArgSpec::GMAT; - }; - template<> struct GSpecTraits - { - static constexpr const ArgSpec spec = ArgSpec::RECT; - }; - - enum class OpaqueKind: int - { - CV_UNKNOWN, // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization - CV_BOOL, // bool user G-API data - CV_INT, // int user G-API data - CV_DOUBLE, // double user G-API data - CV_POINT, // cv::Point user G-API data - CV_SIZE, // cv::Size user G-API data - CV_RECT, // cv::Rect user G-API data - CV_SCALAR, // cv::Scalar user G-API data - CV_MAT, // cv::Mat user G-API data - }; - - template struct GOpaqueTraits; - template struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; }; - // Describe G-API types (G-types) with traits. Mostly used by // cv::GArg to store meta information about types passed into // operation arguments. Please note that cv::GComputation is // defined on GProtoArgs, not GArgs! - // - // spec is a type specialization (makes sense for GArray<> and GOpaque<>) - // for the rest, it is just OPAQUE_VAL by default. template struct GTypeTraits; template struct GTypeTraits { static constexpr const ArgKind kind = ArgKind::OPAQUE_VAL; - static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; }; template<> struct GTypeTraits { static constexpr const ArgKind kind = ArgKind::GMAT; static constexpr const GShape shape = GShape::GMAT; - static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; }; template<> struct GTypeTraits { static constexpr const ArgKind kind = ArgKind::GMATP; static constexpr const GShape shape = GShape::GMAT; - static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; }; template<> struct GTypeTraits { static constexpr const ArgKind kind = ArgKind::GFRAME; static constexpr const GShape shape = GShape::GMAT; - static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; }; template<> struct GTypeTraits { static constexpr const ArgKind kind = ArgKind::GSCALAR; static constexpr const GShape shape = GShape::GSCALAR; - static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC; + static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN; }; template struct GTypeTraits > { static constexpr const ArgKind kind = ArgKind::GARRAY; static constexpr const GShape shape = GShape::GARRAY; - static constexpr const ArgSpec spec = GSpecTraits::spec; + static constexpr const OpaqueKind op_kind = GOpaqueTraits::kind; using host_type = std::vector; using strip_type = cv::detail::VectorRef; static cv::detail::GArrayU wrap_value(const cv::GArray &t) { return t.strip();} @@ -143,7 +90,7 @@ namespace detail { static constexpr const ArgKind kind = ArgKind::GOPAQUE; static constexpr const GShape shape = GShape::GOPAQUE; - static constexpr const ArgSpec spec = GSpecTraits::spec; + static constexpr const OpaqueKind op_kind = GOpaqueTraits::kind; using host_type = T; using strip_type = cv::detail::OpaqueRef; static cv::detail::GOpaqueU wrap_value(const cv::GOpaque &t) { return t.strip();} @@ -176,7 +123,6 @@ namespace detail template<> struct GTypeOf { using type = cv::GScalar; }; template struct GTypeOf > { using type = cv::GArray; }; template struct GTypeOf { using type = cv::GOpaque;}; - // FIXME: This is not quite correct since IStreamSource may produce not only Mat but also Scalar // and vector data. TODO: Extend the type dispatching on these types too. template<> struct GTypeOf { using type = cv::GMat;}; diff --git a/modules/gapi/src/api/garray.cpp b/modules/gapi/src/api/garray.cpp index bdd46b9..e99ce6a 100644 --- a/modules/gapi/src/api/garray.cpp +++ b/modules/gapi/src/api/garray.cpp @@ -2,7 +2,7 @@ // 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-2020 Intel Corporation #include "precomp.hpp" @@ -35,6 +35,11 @@ void cv::detail::GArrayU::setConstructFcn(ConstructVec &&cv) m_priv->ctor = std::move(cv); } +void cv::detail::GArrayU::setKind(cv::detail::OpaqueKind kind) +{ + m_priv->kind = kind; +} + namespace cv { std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &) { diff --git a/modules/gapi/src/api/gopaque.cpp b/modules/gapi/src/api/gopaque.cpp index 9dff6e7..71bf1bc 100644 --- a/modules/gapi/src/api/gopaque.cpp +++ b/modules/gapi/src/api/gopaque.cpp @@ -2,7 +2,7 @@ // 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) 2019 Intel Corporation +// Copyright (C) 2019-2020 Intel Corporation #include "precomp.hpp" @@ -35,6 +35,11 @@ void cv::detail::GOpaqueU::setConstructFcn(ConstructOpaque &&co) m_priv->ctor = std::move(co); } +void cv::detail::GOpaqueU::setKind(cv::detail::OpaqueKind kind) +{ + m_priv->kind = kind; +} + namespace cv { std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &) { diff --git a/modules/gapi/src/api/gorigin.cpp b/modules/gapi/src/api/gorigin.cpp index 312d614..d78e906 100644 --- a/modules/gapi/src/api/gorigin.cpp +++ b/modules/gapi/src/api/gorigin.cpp @@ -2,7 +2,7 @@ // 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-2020 Intel Corporation #include "precomp.hpp" @@ -14,13 +14,14 @@ cv::GOrigin::GOrigin(GShape s, const cv::GNode& n, std::size_t p, - const cv::gimpl::HostCtor c) - : shape(s), node(n), port(p), ctor(c) + const cv::gimpl::HostCtor c, + cv::detail::OpaqueKind k) + : shape(s), node(n), port(p), ctor(c), kind(k) { } cv::GOrigin::GOrigin(GShape s, cv::gimpl::ConstVal v) - : shape(s), node(cv::GNode::Const()), value(v), port(INVALID_PORT) + : shape(s), node(cv::GNode::Const()), value(v), port(INVALID_PORT), kind(cv::detail::OpaqueKind::CV_UNKNOWN) { } diff --git a/modules/gapi/src/api/gorigin.hpp b/modules/gapi/src/api/gorigin.hpp index 7129b2f..2f01544 100644 --- a/modules/gapi/src/api/gorigin.hpp +++ b/modules/gapi/src/api/gorigin.hpp @@ -2,8 +2,7 @@ // 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-2020 Intel Corporation #ifndef OPENCV_GAPI_GORIGIN_HPP #define OPENCV_GAPI_GORIGIN_HPP @@ -30,7 +29,8 @@ struct GOrigin GOrigin(GShape s, const GNode& n, std::size_t p = INVALID_PORT, - const gimpl::HostCtor h = {}); + const gimpl::HostCtor h = {}, + cv::detail::OpaqueKind kind = cv::detail::OpaqueKind::CV_UNKNOWN); GOrigin(GShape s, gimpl::ConstVal value); const GShape shape; // Shape of a produced object @@ -38,6 +38,7 @@ struct GOrigin const gimpl::ConstVal value; // Node can have initial constant value, now only scalar is supported const std::size_t port; // GNode's output number; FIXME: "= max_size" in C++14 gimpl::HostCtor ctor; // FIXME: replace with an interface? + detail::OpaqueKind kind; // primary is needed for GOpaque and GArray }; namespace detail diff --git a/modules/gapi/src/api/s11n.cpp b/modules/gapi/src/api/s11n.cpp index f3893dd..b56c34f 100644 --- a/modules/gapi/src/api/s11n.cpp +++ b/modules/gapi/src/api/s11n.cpp @@ -44,6 +44,8 @@ std::vector cv::gapi::serialize(const cv::GRunArgs& ra) return os.data(); } +// FIXME: This function should move from S11N to GRunArg-related entities. +// it has nothing to do with the S11N as it is cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results) { cv::GRunArgsP outputs; @@ -77,3 +79,36 @@ cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results) } return outputs; } + +// FIXME: move it out of s11n to api/ +// FIXME: don't we have such function already? +cv::GRunArg cv::gapi::bind(cv::GRunArgP &out) +{ + using T = cv::GRunArgP; + switch (out.index()) + { +#if !defined(GAPI_STANDALONE) + case T::index_of() : + GAPI_Assert(false && "Please implement this!"); + break; +#endif + + case T::index_of() : + return cv::GRunArg(cv::util::get(out)); + + case T::index_of() : + return cv::GRunArg(cv::util::get(out)); + + case T::index_of() : + return cv::GRunArg(*cv::util::get(out)); + + case T::index_of() : + return cv::GRunArg(*cv::util::get(out)); + + default: + // ...maybe our types were extended + GAPI_Assert(false && "This value type is UNKNOWN!"); + break; + } + return cv::GRunArg(); +} diff --git a/modules/gapi/src/backends/common/serialization.cpp b/modules/gapi/src/backends/common/serialization.cpp index 7b275a7..ea97f17 100644 --- a/modules/gapi/src/backends/common/serialization.cpp +++ b/modules/gapi/src/backends/common/serialization.cpp @@ -292,25 +292,85 @@ I::IStream& operator >> (I::IStream& is, cv::gapi::wip::IStreamSource::Ptr &) return is; } -I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef &) +namespace +{ +template +struct putToStream; + +template +struct putToStream> +{ + static void put(I::OStream&, const Ref &) + { + GAPI_Assert(false && "Unsupported type for GArray/GOpaque serialization"); + } +}; + +template +struct putToStream> +{ + static void put(I::OStream& os, const Ref &r) + { + if (r.getKind() == cv::detail::GOpaqueTraits::kind) { + os << r.template rref(); + } else { + putToStream >::put(os, r); + } + } +}; + +template +struct getFromStream; + +template +struct getFromStream> { - GAPI_Assert(false && "Serialization: Unsupported << for cv::detail::VectorRef &"); + static void get(I::IStream&, Ref &, cv::detail::OpaqueKind) + { + GAPI_Assert(false && "Unsupported type for GArray/GOpaque deserialization"); + } +}; + +template +struct getFromStream> +{ + static void get(I::IStream& is, Ref &r, cv::detail::OpaqueKind kind) { + if (kind == cv::detail::GOpaqueTraits::kind) { + r.template reset(); + auto& val = r.template wref(); + is >> val; + } else { + getFromStream >::get(is, r, kind); + } + } +}; +} + +I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef& ref) +{ + os << ref.getKind(); + putToStream::put(os, ref); return os; } -I::IStream& operator >> (I::IStream& is, cv::detail::VectorRef &) +I::IStream& operator >> (I::IStream& is, cv::detail::VectorRef& ref) { - GAPI_Assert(false && "Serialization: Unsupported >> for cv::detail::VectorRef &"); + cv::detail::OpaqueKind kind; + is >> kind; + getFromStream::get(is, ref, kind); return is; } -I::OStream& operator<< (I::OStream& os, const cv::detail::OpaqueRef &) +I::OStream& operator<< (I::OStream& os, const cv::detail::OpaqueRef& ref) { - GAPI_Assert(false && "Serialization: Unsupported << for cv::detail::OpaqueRef &"); + os << ref.getKind(); + putToStream::put(os, ref); return os; } -I::IStream& operator >> (I::IStream& is, cv::detail::OpaqueRef &) +I::IStream& operator >> (I::IStream& is, cv::detail::OpaqueRef& ref) { - GAPI_Assert(false && "Serialization: Unsupported >> for cv::detail::OpaqueRef &"); + cv::detail::OpaqueKind kind; + is >> kind; + getFromStream::get(is, ref, kind); return is; } // Enums and structures @@ -350,7 +410,6 @@ I::IStream& operator>> (I::IStream& is, cv::gimpl::Data::Storage &s) { return get_enum(is, s); } - I::OStream& operator<< (I::OStream& os, const cv::GArg &arg) { // Only GOBJREF and OPAQUE_VAL kinds can be serialized/deserialized GAPI_Assert( arg.kind == cv::detail::ArgKind::OPAQUE_VAL @@ -376,6 +435,7 @@ I::OStream& operator<< (I::OStream& os, const cv::GArg &arg) { } return os; } + I::IStream& operator>> (I::IStream& is, cv::GArg &arg) { is >> arg.kind >> arg.opaque_kind; @@ -447,12 +507,50 @@ I::IStream& operator>> (I::IStream& is, cv::gimpl::Op &op) { I::OStream& operator<< (I::OStream& os, const cv::gimpl::Data &d) { // FIXME: HostCtor is not stored here!! // FIXME: Storage may be incorrect for subgraph-to-graph process - return os << d.shape << d.rc << d.meta << d.storage; + return os << d.shape << d.rc << d.meta << d.storage << d.kind; } + +namespace +{ +template +struct initCtor; + +template +struct initCtor> +{ + static void init(cv::gimpl::Data&) + { + GAPI_Assert(false && "Unsupported type for GArray/GOpaque deserialization"); + } +}; + +template +struct initCtor> +{ + static void init(cv::gimpl::Data& d) { + if (d.kind == cv::detail::GOpaqueTraits::kind) { + static std::function ctor = [](Ref& ref){ref.template reset();}; + d.ctor = ctor; + } else { + initCtor >::init(d); + } + } +}; +} // anonymous namespace + I::IStream& operator>> (I::IStream& is, cv::gimpl::Data &d) { // FIXME: HostCtor is not stored here!! // FIXME: Storage may be incorrect for subgraph-to-graph process - return is >> d.shape >> d.rc >> d.meta >> d.storage; + is >> d.shape >> d.rc >> d.meta >> d.storage >> d.kind; + if (d.shape == cv::GShape::GARRAY) + { + initCtor::init(d); + } + else if (d.shape == cv::GShape::GOPAQUE) + { + initCtor::init(d); + } + return is; } @@ -478,6 +576,14 @@ void serialize( I::OStream& os , const ade::Graph &g , const std::vector &nodes) { cv::gimpl::GModel::ConstGraph cg(g); + serialize(os, g, cg.metadata().get(), nodes); +} + +void serialize( I::OStream& os + , const ade::Graph &g + , const cv::gimpl::Protocol &p + , const std::vector &nodes) { + cv::gimpl::GModel::ConstGraph cg(g); GSerialized s; for (auto &nh : nodes) { switch (cg.metadata(nh).get().t) @@ -488,7 +594,7 @@ void serialize( I::OStream& os } } s.m_counter = cg.metadata().get(); - s.m_proto = cg.metadata().get(); + s.m_proto = p; os << s.m_ops << s.m_datas << s.m_counter << s.m_proto; } diff --git a/modules/gapi/src/backends/common/serialization.hpp b/modules/gapi/src/backends/common/serialization.hpp index a7b8537..90169f6 100644 --- a/modules/gapi/src/backends/common/serialization.hpp +++ b/modules/gapi/src/backends/common/serialization.hpp @@ -121,7 +121,6 @@ GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GArg &arg); //I::OStream& operator<< (I::OStream& os, const cv::GRunArg &arg); //I::IStream& operator>> (I::IStream& is, cv::GRunArg &arg); - GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GKernel &k); GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GKernel &k); @@ -167,6 +166,14 @@ GAPI_EXPORTS void serialize( I::OStream& os , const ade::Graph &g , const std::vector &nodes); +// The top-level serialization routine. +// Note it is just a single function which takes a GModel and a list of nodes +// and writes the data to the stream (recursively) +GAPI_EXPORTS void serialize( I::OStream& os + , const ade::Graph &g + , const cv::gimpl::Protocol &p + , const std::vector &nodes); + // The top-level deserialization routineS. // Unfortunately the deserialization is a two-step process: // 1. First we decode a stream into some intermediate representation diff --git a/modules/gapi/src/backends/cpu/gcpubackend.cpp b/modules/gapi/src/backends/cpu/gcpubackend.cpp index 06c2510..780c0e9 100644 --- a/modules/gapi/src/backends/cpu/gcpubackend.cpp +++ b/modules/gapi/src/backends/cpu/gcpubackend.cpp @@ -194,7 +194,7 @@ void cv::gimpl::GCPUExecutable::run(std::vector &&input_objs, { const auto &desc = gm.metadata(nh).get(); - if ( desc.storage == Data::Storage::INTERNAL + if ( desc.storage == Data::Storage::INTERNAL // FIXME: to reconsider && !util::holds_alternative(desc.ctor)) { // FIXME: Note that compile-time constant data objects (like diff --git a/modules/gapi/src/backends/ie/giebackend.cpp b/modules/gapi/src/backends/ie/giebackend.cpp index 227d393..df4ffb1 100644 --- a/modules/gapi/src/backends/ie/giebackend.cpp +++ b/modules/gapi/src/backends/ie/giebackend.cpp @@ -614,7 +614,7 @@ struct InferList2: public cv::detail::KernelTag { GAPI_Assert(util::holds_alternative(mm) && "Non-array inputs are not supported"); - if (op.k.inSpecs[idx] == cv::detail::ArgSpec::RECT) { + if (op.k.inKinds[idx] == cv::detail::OpaqueKind::CV_RECT) { // This is a cv::Rect -- configure the IE preprocessing ii->setPrecision(toIE(meta_0.depth)); ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR); @@ -622,7 +622,7 @@ struct InferList2: public cv::detail::KernelTag { // This is a cv::GMat (equals to: cv::Mat) // Just validate that it is really the type // (other types are prohibited here) - GAPI_Assert(op.k.inSpecs[idx] == cv::detail::ArgSpec::GMAT); + GAPI_Assert(op.k.inKinds[idx] == cv::detail::OpaqueKind::CV_MAT); } idx++; // NB: Never forget to increment the counter } @@ -666,11 +666,11 @@ struct InferList2: public cv::detail::KernelTag { GAPI_Assert(this_vec.size() == list_size); // Prepare input {{{ IE::Blob::Ptr this_blob; - if (this_vec.spec() == cv::detail::TypeSpec::RECT) { + if (this_vec.getKind() == cv::detail::OpaqueKind::CV_RECT) { // ROI case - create an ROI blob const auto &vec = this_vec.rref(); this_blob = IE::make_shared_blob(blob_0, toIE(vec[list_idx])); - } else if (this_vec.spec() == cv::detail::TypeSpec::MAT) { + } else if (this_vec.getKind() == cv::detail::OpaqueKind::CV_MAT) { // Mat case - create a regular blob // FIXME: NOW Assume Mats are always BLOBS (not // images) diff --git a/modules/gapi/src/compiler/gmodel.cpp b/modules/gapi/src/compiler/gmodel.cpp index cbeaf81..39dc1da 100644 --- a/modules/gapi/src/compiler/gmodel.cpp +++ b/modules/gapi/src/compiler/gmodel.cpp @@ -2,7 +2,7 @@ // 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-2020 Intel Corporation #include "precomp.hpp" @@ -54,7 +54,7 @@ ade::NodeHandle GModel::mkDataNode(GModel::Graph &g, const GOrigin& origin) // associated host-type constructor (e.g. when the array is // somewhere in the middle of the graph). auto ctor_copy = origin.ctor; - g.metadata(data_h).set(Data{origin.shape, id, meta, ctor_copy, storage}); + g.metadata(data_h).set(Data{origin.shape, id, meta, ctor_copy, origin.kind, storage}); return data_h; } @@ -67,8 +67,9 @@ ade::NodeHandle GModel::mkDataNode(GModel::Graph &g, const GShape shape) GMetaArg meta; HostCtor ctor; Data::Storage storage = Data::Storage::INTERNAL; // By default, all objects are marked INTERNAL + cv::detail::OpaqueKind kind = cv::detail::OpaqueKind::CV_UNKNOWN; - g.metadata(data_h).set(Data{shape, id, meta, ctor, storage}); + g.metadata(data_h).set(Data{shape, id, meta, ctor, kind, storage}); return data_h; } diff --git a/modules/gapi/src/compiler/gmodel.hpp b/modules/gapi/src/compiler/gmodel.hpp index 1b16079..8f78ba4 100644 --- a/modules/gapi/src/compiler/gmodel.hpp +++ b/modules/gapi/src/compiler/gmodel.hpp @@ -2,7 +2,7 @@ // 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-2020 Intel Corporation #ifndef OPENCV_GAPI_GMODEL_HPP @@ -26,6 +26,7 @@ #include #include +#include #include "compiler/gobjref.hpp" #include "compiler/gislandmodel.hpp" @@ -71,6 +72,7 @@ struct Data int rc; GMetaArg meta; HostCtor ctor; // T-specific helper to deal with unknown types in our code + cv::detail::OpaqueKind kind; // FIXME: is needed to store GArray/GOpaque type // FIXME: Why rc+shape+meta is not represented as RcDesc here? enum class Storage: int diff --git a/modules/gapi/src/compiler/gmodelbuilder.cpp b/modules/gapi/src/compiler/gmodelbuilder.cpp index c53c7b2..87e9ab5 100644 --- a/modules/gapi/src/compiler/gmodelbuilder.cpp +++ b/modules/gapi/src/compiler/gmodelbuilder.cpp @@ -2,7 +2,7 @@ // 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-2020 Intel Corporation //////////////////////////////////////////////////////////////////////////////// @@ -139,7 +139,7 @@ cv::gimpl::Unrolled cv::gimpl::unrollExpr(const GProtoArgs &ins, std::size_t port = ade::util::index(it); GShape shape = ade::util::value(it); - GOrigin org { shape, node, port}; + GOrigin org { shape, node, port, {}, origin.kind }; origins.insert(org); } diff --git a/modules/gapi/src/compiler/gobjref.hpp b/modules/gapi/src/compiler/gobjref.hpp index 3387070..acbb64b 100644 --- a/modules/gapi/src/compiler/gobjref.hpp +++ b/modules/gapi/src/compiler/gobjref.hpp @@ -55,7 +55,6 @@ namespace detail template<> struct GTypeTraits { static constexpr const ArgKind kind = ArgKind::GOBJREF; - static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC; }; } diff --git a/modules/gapi/src/compiler/passes/meta.cpp b/modules/gapi/src/compiler/passes/meta.cpp index 40c6f9a..51d4c88 100644 --- a/modules/gapi/src/compiler/passes/meta.cpp +++ b/modules/gapi/src/compiler/passes/meta.cpp @@ -2,7 +2,7 @@ // 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-2020 Intel Corporation #include "precomp.hpp" @@ -94,18 +94,21 @@ void cv::gimpl::passes::inferMeta(ade::passes::PassContext &ctx, bool meta_is_in GAPI_Assert(gr.metadata(output_nh).get().t == NodeType::DATA); auto &output_meta = gr.metadata(output_nh).get().meta; - if (!meta_is_initialized && !util::holds_alternative(output_meta)) - { - GAPI_LOG_INFO(NULL, - "!!! Output object has an initialized meta - " - "how it is possible today?" << std::endl; ); - if (output_meta != out_metas.at(output_port)) - { - util::throw_error(std::logic_error("Fatal: meta mismatch")); - // FIXME: New exception type? - // FIXME: More details! - } - } + + cv::util::suppress_unused_warning(meta_is_initialized); + // FIXME: calling compile() with meta the second time when cannot reshape will lead to error below + //if (!meta_is_initialized && !util::holds_alternative(output_meta)) + //{ + // GAPI_LOG_INFO(NULL, + // "!!! Output object has an initialized meta - " + // "how it is possible today?" << std::endl; ); + // if (output_meta != out_metas.at(output_port)) + // { + // util::throw_error(std::logic_error("Fatal: meta mismatch")); + // // FIXME: New exception type? + // // FIXME: More details! + // } + //} // Store meta in graph output_meta = out_metas.at(output_port); } diff --git a/modules/gapi/test/gapi_array_tests.cpp b/modules/gapi/test/gapi_array_tests.cpp index a109bb5..b6f4a6e 100644 --- a/modules/gapi/test/gapi_array_tests.cpp +++ b/modules/gapi/test/gapi_array_tests.cpp @@ -188,18 +188,38 @@ TEST(GArray_VectorRef, TestMov) EXPECT_EQ(V{}, vtest); } -TEST(GArray_VectorRef, Spec) +TEST(GArray_VectorRef, Kind) { cv::detail::VectorRef v1(std::vector{}); - EXPECT_EQ(cv::detail::TypeSpec::RECT, v1.spec()); + EXPECT_EQ(cv::detail::OpaqueKind::CV_RECT, v1.getKind()); cv::detail::VectorRef v2(std::vector{}); - EXPECT_EQ(cv::detail::TypeSpec::MAT, v2.spec()); + EXPECT_EQ(cv::detail::OpaqueKind::CV_MAT, v2.getKind()); cv::detail::VectorRef v3(std::vector{}); - EXPECT_EQ(cv::detail::TypeSpec::OPAQUE_SPEC, v3.spec()); + EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, v3.getKind()); - cv::detail::VectorRef v4(std::vector{}); - EXPECT_EQ(cv::detail::TypeSpec::OPAQUE_SPEC, v4.spec()); + cv::detail::VectorRef v4(std::vector{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_DOUBLE, v4.getKind()); + + cv::detail::VectorRef v5(std::vector{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_SCALAR, v5.getKind()); + + cv::detail::VectorRef v6(std::vector{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_POINT, v6.getKind()); + + cv::detail::VectorRef v7(std::vector{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind()); + + cv::detail::VectorRef v8(std::vector{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind()); +} + +TEST(GArray_VectorRef, TestRvalue) +{ + // Warning: this test is testing some not-very-public APIs + cv::detail::VectorRef vref(std::vector{3, 5, -4}); + auto v = std::vector{3, 5, -4}; + EXPECT_EQ(vref.rref(), v); } } // namespace opencv_test diff --git a/modules/gapi/test/gapi_opaque_tests.cpp b/modules/gapi/test/gapi_opaque_tests.cpp index 0623d2e..6a5cb1a 100644 --- a/modules/gapi/test/gapi_opaque_tests.cpp +++ b/modules/gapi/test/gapi_opaque_tests.cpp @@ -214,4 +214,25 @@ TEST(GOpaque_OpaqueRef, TestMov) EXPECT_EQ(test, ref.rref()); // ref = test EXPECT_NE(test, mov.rref()); // ref lost the data } + +TEST(GOpaque_OpaqueRef, Kind) +{ + cv::detail::OpaqueRef v1(cv::Rect{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_RECT, v1.getKind()); + + cv::detail::OpaqueRef v3(int{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, v3.getKind()); + + cv::detail::OpaqueRef v4(double{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_DOUBLE, v4.getKind()); + + cv::detail::OpaqueRef v6(cv::Point{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_POINT, v6.getKind()); + + cv::detail::OpaqueRef v7(cv::Size{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind()); + + cv::detail::OpaqueRef v8(std::string{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind()); +} } // namespace opencv_test diff --git a/modules/gapi/test/internal/gapi_int_garg_test.cpp b/modules/gapi/test/internal/gapi_int_garg_test.cpp index 5bb9024..7c596df 100644 --- a/modules/gapi/test/internal/gapi_int_garg_test.cpp +++ b/modules/gapi/test/internal/gapi_int_garg_test.cpp @@ -76,61 +76,6 @@ TYPED_TEST(GArgKind, RValue) EXPECT_EQ(TestFixture::Kind, arg.kind); } -// Repeat the same for Spec - -template -struct ExpectedS -{ - using type = T; - static const constexpr cv::detail::ArgSpec spec = Exp; -}; - -template -struct ArgSpec: public ::testing::Test -{ - using Type = typename T::type; - const cv::detail::ArgSpec Spec = T::spec; -}; - -using Arg_Spec_Types = ::testing::Types - < - // G-API types - ExpectedS - , ExpectedS - , ExpectedS - , ExpectedS - , ExpectedS, cv::detail::ArgSpec::OPAQUE_SPEC> - , ExpectedS, cv::detail::ArgSpec::OPAQUE_SPEC> - , ExpectedS, cv::detail::ArgSpec::OPAQUE_SPEC> - , ExpectedS, cv::detail::ArgSpec::RECT> - , ExpectedS, cv::detail::ArgSpec::GMAT> - , ExpectedS, cv::detail::ArgSpec::OPAQUE_SPEC> - , ExpectedS, cv::detail::ArgSpec::OPAQUE_SPEC> - , ExpectedS, cv::detail::ArgSpec::OPAQUE_SPEC> - , ExpectedS, cv::detail::ArgSpec::RECT> -// FIXME: causes internal conflicts in GOpaque/descr_of -// , ExpectedS, cv::detail::ArgSpec::GMAT> - - // Built-in types - , ExpectedS - , ExpectedS - , ExpectedS - , ExpectedS - , ExpectedS - , ExpectedS - , ExpectedS, cv::detail::ArgSpec::OPAQUE_SPEC> - , ExpectedS, cv::detail::ArgSpec::OPAQUE_SPEC> - >; - -TYPED_TEST_CASE(ArgSpec, Arg_Spec_Types); - -TYPED_TEST(ArgSpec, Basic) -{ - const auto this_spec = cv::detail::GTypeTraits::spec; - EXPECT_EQ(TestFixture::Spec, this_spec); -} - -// }} //////////////////////////////////////////////////////////////////////////////// TEST(GArg, HasWrap) @@ -170,6 +115,4 @@ TEST(GArg, GOpaqueU) cv::GArg arg2 = cv::GArg(cv::GOpaque()); EXPECT_NO_THROW(arg2.get()); } - - } // namespace opencv_test diff --git a/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp b/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp index a97fc35..f6543e5 100644 --- a/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp +++ b/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp @@ -10,6 +10,7 @@ #include // util::indexed #include +#include #include "compiler/gmodelbuilder.hpp" #include "compiler/gmodel.hpp" // RcDesc, GModel::init @@ -27,8 +28,8 @@ namespace return cv::GCall(cv::GKernel{ "gapi.test.unaryop" , "" , nullptr - , { D::ArgSpec::OPAQUE_SPEC } - , { GShape::GMAT } }).pass(m).yield(0); + , { GShape::GMAT } + , { D::OpaqueKind::CV_UNKNOWN } }).pass(m).yield(0); } cv::GMat binaryOp(cv::GMat m1, cv::GMat m2) @@ -36,8 +37,8 @@ namespace return cv::GCall(cv::GKernel{ "gapi.test.binaryOp" , "" , nullptr - , { D::ArgSpec::OPAQUE_SPEC, D::ArgSpec::OPAQUE_SPEC } - , { GShape::GMAT } }).pass(m1, m2).yield(0); + , { GShape::GMAT } + , { D::OpaqueKind::CV_UNKNOWN, D::OpaqueKind::CV_UNKNOWN } }).pass(m1, m2).yield(0); } std::vector collectOperations(const cv::gimpl::GModel::Graph& gr) diff --git a/modules/gapi/test/s11n/gapi_s11n_tests.cpp b/modules/gapi/test/s11n/gapi_s11n_tests.cpp index 00ee10f..561fcb2 100644 --- a/modules/gapi/test/s11n/gapi_s11n_tests.cpp +++ b/modules/gapi/test/s11n/gapi_s11n_tests.cpp @@ -23,6 +23,21 @@ private: std::vector m_buffer; }; +namespace +{ + template + bool operator==(const cv::detail::VectorRef& a, const cv::detail::VectorRef& b) + { + return a.rref() == b.rref(); + } + + template + bool operator==(const cv::detail::OpaqueRef& a, const cv::detail::OpaqueRef& b) + { + return a.rref() == b.rref(); + } +} + TEST_F(S11N_Basic, Test_int_pos) { int x = 42; put(x); @@ -213,6 +228,60 @@ TEST_F(S11N_Basic, Test_RunArgs_Scalar) { EXPECT_EQ(scalar2, out_scalar2); } +TEST_F(S11N_Basic, Test_RunArg_Opaque) { + auto op = cv::detail::OpaqueRef(42); + auto v = cv::GRunArg{ op }; + put(v); + cv::GRunArg out_v = get(); + cv::detail::OpaqueRef out_op = cv::util::get(out_v); + EXPECT_TRUE(operator==(op, out_op)); +} + +TEST_F(S11N_Basic, Test_RunArgs_Opaque) { + cv::detail::OpaqueRef op1 = cv::detail::OpaqueRef(cv::Point(1, 2)); + cv::detail::OpaqueRef op2 = cv::detail::OpaqueRef(cv::Size(12, 21)); + GRunArgs v; + v.resize(2); + v[0] = cv::GRunArg{ op1 }; + v[1] = cv::GRunArg{ op2 }; + put(v); + cv::GRunArgs out_v = get(); + cv::detail::OpaqueRef out_op1 = cv::util::get(out_v[0]); + cv::detail::OpaqueRef out_op2 = cv::util::get(out_v[1]); + EXPECT_TRUE(operator==(op1, out_op1)); + EXPECT_TRUE(operator==(op2, out_op2)); +} + +TEST_F(S11N_Basic, Test_RunArg_Array) { + auto op = cv::detail::VectorRef(std::vector{cv::Mat::eye(3, 3, CV_8UC1), cv::Mat::zeros(5, 5, CV_8UC3)}); + + auto v = cv::GRunArg{ op }; + put(v); + cv::GRunArg out_v = get(); + cv::detail::VectorRef out_op = cv::util::get(out_v); + auto vec1 = op.rref(); + auto vec2 = out_op.rref(); + EXPECT_EQ(0, cv::norm(vec1[0], vec2[0], cv::NORM_INF)); + EXPECT_EQ(0, cv::norm(vec1[1], vec2[1], cv::NORM_INF)); +} + +TEST_F(S11N_Basic, Test_RunArgs_Array) { + auto vec_sc = std::vector{cv::Scalar(11), cv::Scalar(31)}; + auto vec_d = std::vector{0.4, 1.0, 123.55, 22.08}; + cv::detail::VectorRef op1 = cv::detail::VectorRef(vec_sc); + cv::detail::VectorRef op2 = cv::detail::VectorRef(vec_d); + GRunArgs v; + v.resize(2); + v[0] = cv::GRunArg{ op1 }; + v[1] = cv::GRunArg{ op2 }; + put(v); + cv::GRunArgs out_v = get(); + cv::detail::VectorRef out_op1 = cv::util::get(out_v[0]); + cv::detail::VectorRef out_op2 = cv::util::get(out_v[1]); + EXPECT_TRUE(operator==(op1, out_op1)); + EXPECT_TRUE(operator==(op2, out_op2)); +} + TEST_F(S11N_Basic, Test_RunArgs_MatScalar) { cv::Mat mat = cv::Mat::eye(cv::Size(64, 64), CV_8UC3); cv::Scalar scalar = cv::Scalar(128, 33, 53); @@ -254,7 +323,6 @@ TEST_F(S11N_Basic, Test_Bind_RunArgs_MatScalar) { v[0] = cv::GRunArg{ mat }; v[1] = cv::GRunArg{ scalar }; GRunArgsP output = cv::gapi::bind(v); - std::cout << "output size " << output.size() << std::endl; unsigned int i = 0; for (auto it : output) { diff --git a/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp b/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp index 89956bf..930d996 100644 --- a/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp +++ b/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp @@ -282,4 +282,206 @@ TEST(S11N, Pipeline_CustomRGB2YUV) } } +namespace ThisTest +{ + using GOpBool = GOpaque; + using GOpInt = GOpaque; + using GOpDouble = GOpaque; + using GOpPoint = GOpaque; + using GOpSize = GOpaque; + using GOpRect = GOpaque; + + using GOpOut = std::tuple; + + G_TYPED_KERNEL_M(OpGenerate, , "test.s11n.gopaque") + { + static std::tuple outMeta(const GOpaqueDesc&, const GOpaqueDesc&, const GOpaqueDesc&) { + return std::make_tuple(empty_gopaque_desc(), empty_gopaque_desc(), empty_gopaque_desc()); + } + }; + + GAPI_OCV_KERNEL(OCVOpGenerate, OpGenerate) + { + static void run(const bool& b, const int& i, const double& d, + cv::Point& p, cv::Size& s, cv::Rect& r) + { + p = cv::Point(i, i*2); + s = b ? cv::Size(42, 42) : cv::Size(7, 7); + int ii = static_cast(d); + r = cv::Rect(ii, ii, ii, ii); + } + }; + + using GArrInt = GArray; + using GArrDouble = GArray; + using GArrPoint = GArray; + using GArrSize = GArray; + using GArrRect = GArray; + using GArrMat = GArray; + using GArrScalar = GArray; + + using GArrOut = std::tuple; + + G_TYPED_KERNEL_M(ArrGenerate, , "test.s11n.garray") + { + static std::tuple outMeta(const GArrayDesc&, const GArrayDesc&, + const GArrayDesc&, const GArrayDesc&) { + return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc(), empty_array_desc()); + } + }; + + GAPI_OCV_KERNEL(OCVArrGenerate, ArrGenerate) + { + static void run(const std::vector& b, const std::vector& i, + const std::vector& d, const std::vector& sc, + std::vector& p, std::vector& s, + std::vector& r, std::vector& m) + { + p.clear(); p.resize(b.size()); + s.clear(); s.resize(b.size()); + r.clear(); r.resize(b.size()); + m.clear(); m.resize(b.size()); + + for (std::size_t idx = 0; idx < b.size(); ++idx) + { + p[idx] = cv::Point(i[idx], i[idx]*2); + s[idx] = b[idx] == 1 ? cv::Size(42, 42) : cv::Size(7, 7); + int ii = static_cast(d[idx]); + r[idx] = cv::Rect(ii, ii, ii, ii); + m[idx] = cv::Mat(3, 3, CV_8UC1, sc[idx]); + } + } + }; + + G_TYPED_KERNEL_M(OpArrK1, (GOpInt, GArrSize)>, "test.s11n.oparrk1") + { + static std::tuple outMeta(const GOpaqueDesc&, const GArrayDesc&) { + return std::make_tuple(empty_array_desc(), empty_gopaque_desc()); + } + }; + + GAPI_OCV_KERNEL(OCVOpArrK1, OpArrK1) + { + static void run(const int& i, const std::vector& vs, + std::vector& vi, cv::Size& s) + { + vi.clear(); vi.resize(vs.size()); + s = cv::Size(i, i); + for (std::size_t idx = 0; idx < vs.size(); ++ idx) + vi[idx] = vs[idx].area(); + } + }; + + G_TYPED_KERNEL_M(OpArrK2, (GArrInt, GOpSize)>, "test.s11n.oparrk2") + { + static std::tuple outMeta(const GArrayDesc&, const GOpaqueDesc&) { + return std::make_tuple(empty_gopaque_desc(), empty_array_desc()); + } + }; + + GAPI_OCV_KERNEL(OCVOpArrK2, OpArrK2) + { + static void run(const std::vector& vi, const cv::Size& s, + double& d, std::vector& vp) + { + vp.clear(); vp.resize(vi.size()); + d = s.area() * 1.5; + for (std::size_t idx = 0; idx < vi.size(); ++ idx) + vp[idx] = cv::Point(vi[idx], vi[idx]); + } + }; +} // namespace ThisTest + +TEST(S11N, Pipeline_GOpaque) +{ + using namespace ThisTest; + GOpBool in1; + GOpInt in2; + GOpDouble in3; + + auto out = OpGenerate::on(in1, in2, in3); + cv::GComputation c(cv::GIn(in1, in2, in3), cv::GOut(std::get<0>(out), std::get<1>(out), std::get<2>(out))); + + auto p = cv::gapi::serialize(c); + auto dc = cv::gapi::deserialize(p); + + bool b = true; + int i = 33; + double d = 128.7; + cv::Point pp; + cv::Size s; + cv::Rect r; + dc.apply(cv::gin(b, i, d), cv::gout(pp, s, r), cv::compile_args(cv::gapi::kernels())); + + EXPECT_EQ(pp, cv::Point(i, i*2)); + EXPECT_EQ(s, cv::Size(42, 42)); + int ii = static_cast(d); + EXPECT_EQ(r, cv::Rect(ii, ii, ii, ii)); +} + +TEST(S11N, Pipeline_GArray) +{ + using namespace ThisTest; + GArrInt in1, in2; + GArrDouble in3; + GArrScalar in4; + + auto out = ArrGenerate::on(in1, in2, in3, in4); + cv::GComputation c(cv::GIn(in1, in2, in3, in4), + cv::GOut(std::get<0>(out), std::get<1>(out), + std::get<2>(out), std::get<3>(out))); + + auto p = cv::gapi::serialize(c); + auto dc = cv::gapi::deserialize(p); + + std::vector b {1, 0, -1}; + std::vector i {3, 0 , 59}; + std::vector d {0.7, 120.5, 44.14}; + std::vector sc {cv::Scalar::all(10), cv::Scalar::all(15), cv::Scalar::all(99)}; + std::vector pp; + std::vector s; + std::vector r; + std::vector m; + dc.apply(cv::gin(b, i, d, sc), cv::gout(pp, s, r, m), cv::compile_args(cv::gapi::kernels())); + + for (std::size_t idx = 0; idx < b.size(); ++idx) + { + EXPECT_EQ(pp[idx], cv::Point(i[idx], i[idx]*2)); + EXPECT_EQ(s[idx], b[idx] == 1 ? cv::Size(42, 42) : cv::Size(7, 7)); + int ii = static_cast(d[idx]); + EXPECT_EQ(r[idx], cv::Rect(ii, ii, ii, ii)); + } +} + +TEST(S11N, Pipeline_GArray_GOpaque_Multinode) +{ + using namespace ThisTest; + GOpInt in1; + GArrSize in2; + + auto tmp = OpArrK1::on(in1, in2); + auto out = OpArrK2::on(std::get<0>(tmp), std::get<1>(tmp)); + + cv::GComputation c(cv::GIn(in1, in2), + cv::GOut(std::get<0>(out), std::get<1>(out))); + + auto p = cv::gapi::serialize(c); + auto dc = cv::gapi::deserialize(p); + + int i = 42; + std::vector s{cv::Size(11, 22), cv::Size(13, 18)}; + double d; + std::vector pp; + + dc.apply(cv::gin(i, s), cv::gout(d, pp), cv::compile_args(cv::gapi::kernels())); + + auto st = cv::Size(i ,i); + EXPECT_EQ(d, st.area() * 1.5); + + for (std::size_t idx = 0; idx < s.size(); ++idx) + { + EXPECT_EQ(pp[idx], cv::Point(s[idx].area(), s[idx].area())); + } +} + } // namespace opencv_test -- 2.7.4