// 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
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<typename... Ts> inline GRunArgs gin(const Ts&... args)
{
// 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
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<typename T> struct GTypeSpec;
- template<typename T> struct GTypeSpec
- {
- static constexpr const TypeSpec spec = TypeSpec::OPAQUE_SPEC;
- };
- template<> struct GTypeSpec<cv::Mat>
- {
- static constexpr const TypeSpec spec = TypeSpec::MAT;
- };
- template<> struct GTypeSpec<cv::Rect>
- {
- 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.
template <typename T>
void specifyType(); // Store type of initial GArray<T>
+ template <typename T>
+ void storeKind();
+
+ void setKind(cv::detail::OpaqueKind);
+
std::shared_ptr<GOrigin> m_priv;
std::shared_ptr<TypeHintBase> m_hint;
};
m_hint.reset(new TypeHint<typename std::decay<T>::type>);
};
+ template <typename T>
+ void GArrayU::storeKind(){
+ setKind(cv::detail::GOpaqueTraits<T>::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
// 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;
{
m_elemSize = sizeof(T);
if (vec) m_desc = cv::descr_of(*vec);
- m_spec = GTypeSpec<T>::spec;
}
public:
wref() = std::move(tv->wref());
}
-
virtual const void* ptr() const override { return &rref(); }
virtual std::size_t size() const override { return rref().size(); }
};
class VectorRef
{
std::shared_ptr<BasicVectorRef> m_ref;
+ cv::detail::OpaqueKind m_kind;
template<typename T> inline void check() const
{
public:
VectorRef() = default;
- template<typename T> explicit VectorRef(const std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
- template<typename T> explicit VectorRef(std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
- template<typename T> explicit VectorRef(std::vector<T>&& vec) : m_ref(new VectorRefT<T>(vec)) {}
+ template<typename T> explicit VectorRef(const std::vector<T>& vec) :
+ m_ref(new VectorRefT<T>(vec)), m_kind(GOpaqueTraits<T>::kind) {}
+ template<typename T> explicit VectorRef(std::vector<T>& vec) :
+ m_ref(new VectorRefT<T>(vec)), m_kind(GOpaqueTraits<T>::kind) {}
+ template<typename T> explicit VectorRef(std::vector<T>&& vec) :
+ m_ref(new VectorRefT<T>(std::move(vec))), m_kind(GOpaqueTraits<T>::kind) {}
+
+ cv::detail::OpaqueKind getKind() const
+ {
+ return m_kind;
+ }
template<typename T> void reset()
{
static_cast<VectorRefT<T>&>(*m_ref).reset();
}
+ template <typename T>
+ void storeKind()
+ {
+ m_kind = cv::detail::GOpaqueTraits<T>::kind;
+ }
+
template<typename T> std::vector<T>& wref()
{
check<T>();
// 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?)
static void VCTor(detail::VectorRef& vref) {
vref.reset<HT>();
+ vref.storeKind<HT>();
}
void putDetails() {
m_ref.setConstructFcn(&VCTor);
- m_ref.specifyType<HT>();
+ m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
+ m_ref.storeKind<HT>(); //
}
detail::GArrayU m_ref;
namespace cv {
+class GMat; // FIXME: forward declaration for GOpaqueTraits
+
namespace detail
{
// This is a trait-like structure to mark backend-specific compile arguments
{};
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<typename T> struct GOpaqueTraits;
+ template<typename T> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; };
+ template<> struct GOpaqueTraits<int> { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; };
+ template<> struct GOpaqueTraits<double> { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; };
+ template<> struct GOpaqueTraits<cv::Size> { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; };
+ template<> struct GOpaqueTraits<bool> { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; };
+ template<> struct GOpaqueTraits<cv::Scalar> { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; };
+ template<> struct GOpaqueTraits<cv::Point> { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; };
+ template<> struct GOpaqueTraits<cv::Mat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
+ template<> struct GOpaqueTraits<cv::Rect> { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; };
+ template<> struct GOpaqueTraits<cv::GMat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
+ // GArray is not supporting bool type for now due to difference in std::vector<bool> implementation
+ using GOpaqueTraitsArrayTypes = std::tuple<int, double, cv::Size, cv::Scalar, cv::Point, cv::Mat, cv::Rect>;
+ // GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types
+ using GOpaqueTraitsOpaqueTypes = std::tuple<bool, int, double, cv::Size, cv::Point, cv::Rect>;
} // namespace detail
// This definition is here because it is reused by both public(?) and internal
namespace cv {
-using GSpecs = std::vector<cv::detail::ArgSpec>;
using GShapes = std::vector<GShape>;
+using GKinds = std::vector<cv::detail::OpaqueKind>;
// GKernel describes kernel API to the system
// FIXME: add attributes of a kernel, (e.g. number and types
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
cv::GCall call(GKernel{ K::id()
, K::tag()
, &K::getOutMeta
- , {detail::GTypeTraits<Args>::spec...}
- , {detail::GTypeTraits<R>::shape...}});
+ , {detail::GTypeTraits<R>::shape...}
+ , {detail::GTypeTraits<Args>::op_kind...}});
call.pass(args...); // TODO: std::forward() here?
return yield(call, typename detail::MkSeq<sizeof...(R)>::type());
}
cv::GCall call(GKernel{ K::id()
, K::tag()
, &K::getOutMeta
- , {detail::GTypeTraits<Args>::spec...}
- , {detail::GTypeTraits<R>::shape}});
+ , {detail::GTypeTraits<R>::shape}
+ , {detail::GTypeTraits<Args>::op_kind...}});
call.pass(args...);
return detail::Yield<R>::yield(call, 0);
}
// 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
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.
template <typename T>
void specifyType(); // Store type of initial GOpaque<T>
+ template <typename T>
+ void storeKind();
+
+ void setKind(cv::detail::OpaqueKind);
+
std::shared_ptr<GOrigin> m_priv;
std::shared_ptr<TypeHintBase> m_hint;
};
m_hint.reset(new TypeHint<util::decay_t<T>>);
};
+ template <typename T>
+ void GOpaqueU::storeKind(){
+ // FIXME: Add assert here on cv::Mat and cv::Scalar?
+ setKind(cv::detail::GOpaqueTraits<T>::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
class OpaqueRef
{
std::shared_ptr<BasicOpaqueRef> m_ref;
+ cv::detail::OpaqueKind m_kind;
template<typename T> inline void check() const
{
public:
OpaqueRef() = default;
-
template<
typename T,
typename = util::are_different_t<OpaqueRef, T>
>
+ // FIXME: probably won't work with const object
explicit OpaqueRef(T&& obj) :
- m_ref(new OpaqueRefT<util::decay_t<T>>(std::forward<T>(obj))) {}
+ m_ref(new OpaqueRefT<util::decay_t<T>>(std::forward<T>(obj))),
+ m_kind(GOpaqueTraits<T>::kind) {}
+
+ cv::detail::OpaqueKind getKind() const
+ {
+ return m_kind;
+ }
template<typename T> void reset()
{
static_cast<OpaqueRefT<T>&>(*m_ref).reset();
}
+ template <typename T>
+ void storeKind()
+ {
+ m_kind = cv::detail::GOpaqueTraits<T>::kind;
+ }
+
template<typename T> T& wref()
{
check<T>();
static void CTor(detail::OpaqueRef& ref) {
ref.reset<HT>();
+ ref.storeKind<HT>();
}
void putDetails() {
m_ref.setConstructFcn(&CTor);
- m_ref.specifyType<HT>();
+ m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
+ m_ref.storeKind<HT>(); //
}
detail::GOpaqueU m_ref;
GOPAQUE, // a cv::GOpaqueU (note - exactly GOpaqueU, not GOpaque<T>!)
};
- // This enum captures some information about T in GArray<T> and GOpaque<T>
- 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<typename T> struct GSpecTraits;
- template<typename T> struct GSpecTraits
- {
- static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC;
- };
- template<> struct GSpecTraits<cv::GMat>
- {
- static constexpr const ArgSpec spec = ArgSpec::GMAT;
- };
- template<> struct GSpecTraits<cv::Rect>
- {
- 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<typename T> struct GOpaqueTraits;
- template<typename T> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; };
- template<> struct GOpaqueTraits<int> { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; };
- template<> struct GOpaqueTraits<double> { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; };
- template<> struct GOpaqueTraits<cv::Size> { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; };
- template<> struct GOpaqueTraits<bool> { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; };
- template<> struct GOpaqueTraits<cv::Scalar> { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; };
- template<> struct GOpaqueTraits<cv::Point> { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; };
- template<> struct GOpaqueTraits<cv::Mat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
- template<> struct GOpaqueTraits<cv::Rect> { 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<typename T> struct GTypeTraits;
template<typename T> 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<cv::GMat>
{
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<cv::GMatP>
{
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<cv::GFrame>
{
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<cv::GScalar>
{
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<class T> struct GTypeTraits<cv::GArray<T> >
{
static constexpr const ArgKind kind = ArgKind::GARRAY;
static constexpr const GShape shape = GShape::GARRAY;
- static constexpr const ArgSpec spec = GSpecTraits<T>::spec;
+ static constexpr const OpaqueKind op_kind = GOpaqueTraits<T>::kind;
using host_type = std::vector<T>;
using strip_type = cv::detail::VectorRef;
static cv::detail::GArrayU wrap_value(const cv::GArray<T> &t) { return t.strip();}
{
static constexpr const ArgKind kind = ArgKind::GOPAQUE;
static constexpr const GShape shape = GShape::GOPAQUE;
- static constexpr const ArgSpec spec = GSpecTraits<T>::spec;
+ static constexpr const OpaqueKind op_kind = GOpaqueTraits<T>::kind;
using host_type = T;
using strip_type = cv::detail::OpaqueRef;
static cv::detail::GOpaqueU wrap_value(const cv::GOpaque<T> &t) { return t.strip();}
template<> struct GTypeOf<cv::Scalar> { using type = cv::GScalar; };
template<typename U> struct GTypeOf<std::vector<U> > { using type = cv::GArray<U>; };
template<typename U> struct GTypeOf { using type = cv::GOpaque<U>;};
-
// 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<cv::gapi::wip::IStreamSource::Ptr> { using type = cv::GMat;};
// 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"
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 &)
{
// 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"
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 &)
{
// 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"
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)
{
}
// 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
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
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
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;
}
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<cv::UMat*>() :
+ GAPI_Assert(false && "Please implement this!");
+ break;
+#endif
+
+ case T::index_of<cv::detail::VectorRef>() :
+ return cv::GRunArg(cv::util::get<cv::detail::VectorRef>(out));
+
+ case T::index_of<cv::detail::OpaqueRef>() :
+ return cv::GRunArg(cv::util::get<cv::detail::OpaqueRef>(out));
+
+ case T::index_of<cv::Mat*>() :
+ return cv::GRunArg(*cv::util::get<cv::Mat*>(out));
+
+ case T::index_of<cv::Scalar*>() :
+ return cv::GRunArg(*cv::util::get<cv::Scalar*>(out));
+
+ default:
+ // ...maybe our types were extended
+ GAPI_Assert(false && "This value type is UNKNOWN!");
+ break;
+ }
+ return cv::GRunArg();
+}
return is;
}
-I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef &)
+namespace
+{
+template<typename Ref, typename T, typename... Ts>
+struct putToStream;
+
+template<typename Ref>
+struct putToStream<Ref, std::tuple<>>
+{
+ static void put(I::OStream&, const Ref &)
+ {
+ GAPI_Assert(false && "Unsupported type for GArray/GOpaque serialization");
+ }
+};
+
+template<typename Ref, typename T, typename... Ts>
+struct putToStream<Ref, std::tuple<T, Ts...>>
+{
+ static void put(I::OStream& os, const Ref &r)
+ {
+ if (r.getKind() == cv::detail::GOpaqueTraits<T>::kind) {
+ os << r.template rref<T>();
+ } else {
+ putToStream<Ref, std::tuple<Ts...> >::put(os, r);
+ }
+ }
+};
+
+template<typename Ref, typename T, typename... Ts>
+struct getFromStream;
+
+template<typename Ref>
+struct getFromStream<Ref, std::tuple<>>
{
- 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<typename Ref, typename T, typename... Ts>
+struct getFromStream<Ref, std::tuple<T, Ts...>>
+{
+ static void get(I::IStream& is, Ref &r, cv::detail::OpaqueKind kind) {
+ if (kind == cv::detail::GOpaqueTraits<T>::kind) {
+ r.template reset<T>();
+ auto& val = r.template wref<T>();
+ is >> val;
+ } else {
+ getFromStream<Ref, std::tuple<Ts...> >::get(is, r, kind);
+ }
+ }
+};
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef& ref)
+{
+ os << ref.getKind();
+ putToStream<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::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<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::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<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::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<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::get(is, ref, kind);
return is;
}
// Enums and structures
return get_enum<cv::gimpl::Data::Storage>(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
}
return os;
}
+
I::IStream& operator>> (I::IStream& is, cv::GArg &arg) {
is >> arg.kind >> arg.opaque_kind;
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<typename Ref, typename T, typename... Ts>
+struct initCtor;
+
+template<typename Ref>
+struct initCtor<Ref, std::tuple<>>
+{
+ static void init(cv::gimpl::Data&)
+ {
+ GAPI_Assert(false && "Unsupported type for GArray/GOpaque deserialization");
+ }
+};
+
+template<typename Ref, typename T, typename... Ts>
+struct initCtor<Ref, std::tuple<T, Ts...>>
+{
+ static void init(cv::gimpl::Data& d) {
+ if (d.kind == cv::detail::GOpaqueTraits<T>::kind) {
+ static std::function<void(Ref&)> ctor = [](Ref& ref){ref.template reset<T>();};
+ d.ctor = ctor;
+ } else {
+ initCtor<Ref, std::tuple<Ts...> >::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<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::init(d);
+ }
+ else if (d.shape == cv::GShape::GOPAQUE)
+ {
+ initCtor<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::init(d);
+ }
+ return is;
}
, const ade::Graph &g
, const std::vector<ade::NodeHandle> &nodes) {
cv::gimpl::GModel::ConstGraph cg(g);
+ serialize(os, g, cg.metadata().get<cv::gimpl::Protocol>(), nodes);
+}
+
+void serialize( I::OStream& os
+ , const ade::Graph &g
+ , const cv::gimpl::Protocol &p
+ , const std::vector<ade::NodeHandle> &nodes) {
+ cv::gimpl::GModel::ConstGraph cg(g);
GSerialized s;
for (auto &nh : nodes) {
switch (cg.metadata(nh).get<NodeType>().t)
}
}
s.m_counter = cg.metadata().get<cv::gimpl::DataObjectCounter>();
- s.m_proto = cg.metadata().get<cv::gimpl::Protocol>();
+ s.m_proto = p;
os << s.m_ops << s.m_datas << s.m_counter << s.m_proto;
}
//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);
, const ade::Graph &g
, const std::vector<ade::NodeHandle> &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<ade::NodeHandle> &nodes);
+
// The top-level deserialization routineS.
// Unfortunately the deserialization is a two-step process:
// 1. First we decode a stream into some intermediate representation
{
const auto &desc = gm.metadata(nh).get<Data>();
- if ( desc.storage == Data::Storage::INTERNAL
+ if ( desc.storage == Data::Storage::INTERNAL // FIXME: to reconsider
&& !util::holds_alternative<util::monostate>(desc.ctor))
{
// FIXME: Note that compile-time constant data objects (like
GAPI_Assert(util::holds_alternative<cv::GArrayDesc>(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);
// 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
}
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<cv::Rect>();
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)
// 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"
// 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;
}
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;
}
// 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
#include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/gkernel.hpp>
+#include <opencv2/gapi/gcommon.hpp>
#include "compiler/gobjref.hpp"
#include "compiler/gislandmodel.hpp"
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
// 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
////////////////////////////////////////////////////////////////////////////////
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);
}
template<> struct GTypeTraits<cv::gimpl::RcDesc>
{
static constexpr const ArgKind kind = ArgKind::GOBJREF;
- static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC;
};
}
// 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"
GAPI_Assert(gr.metadata(output_nh).get<NodeType>().t == NodeType::DATA);
auto &output_meta = gr.metadata(output_nh).get<Data>().meta;
- if (!meta_is_initialized && !util::holds_alternative<util::monostate>(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<util::monostate>(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);
}
EXPECT_EQ(V{}, vtest);
}
-TEST(GArray_VectorRef, Spec)
+TEST(GArray_VectorRef, Kind)
{
cv::detail::VectorRef v1(std::vector<cv::Rect>{});
- EXPECT_EQ(cv::detail::TypeSpec::RECT, v1.spec());
+ EXPECT_EQ(cv::detail::OpaqueKind::CV_RECT, v1.getKind());
cv::detail::VectorRef v2(std::vector<cv::Mat>{});
- EXPECT_EQ(cv::detail::TypeSpec::MAT, v2.spec());
+ EXPECT_EQ(cv::detail::OpaqueKind::CV_MAT, v2.getKind());
cv::detail::VectorRef v3(std::vector<int>{});
- EXPECT_EQ(cv::detail::TypeSpec::OPAQUE_SPEC, v3.spec());
+ EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, v3.getKind());
- cv::detail::VectorRef v4(std::vector<std::string>{});
- EXPECT_EQ(cv::detail::TypeSpec::OPAQUE_SPEC, v4.spec());
+ cv::detail::VectorRef v4(std::vector<double>{});
+ EXPECT_EQ(cv::detail::OpaqueKind::CV_DOUBLE, v4.getKind());
+
+ cv::detail::VectorRef v5(std::vector<cv::Scalar>{});
+ EXPECT_EQ(cv::detail::OpaqueKind::CV_SCALAR, v5.getKind());
+
+ cv::detail::VectorRef v6(std::vector<cv::Point>{});
+ EXPECT_EQ(cv::detail::OpaqueKind::CV_POINT, v6.getKind());
+
+ cv::detail::VectorRef v7(std::vector<cv::Size>{});
+ EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind());
+
+ cv::detail::VectorRef v8(std::vector<std::string>{});
+ 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<int>{3, 5, -4});
+ auto v = std::vector<int>{3, 5, -4};
+ EXPECT_EQ(vref.rref<int>(), v);
}
} // namespace opencv_test
EXPECT_EQ(test, ref.rref<I>()); // ref = test
EXPECT_NE(test, mov.rref<I>()); // 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
EXPECT_EQ(TestFixture::Kind, arg.kind);
}
-// Repeat the same for Spec
-
-template<class T, cv::detail::ArgSpec Exp>
-struct ExpectedS
-{
- using type = T;
- static const constexpr cv::detail::ArgSpec spec = Exp;
-};
-
-template<typename T>
-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<cv::GMat, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GMatP, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GFrame, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GScalar, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GArray<int>, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GArray<float>, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GArray<cv::Point>, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GArray<cv::Rect>, cv::detail::ArgSpec::RECT>
- , ExpectedS<cv::GArray<cv::GMat>, cv::detail::ArgSpec::GMAT>
- , ExpectedS<cv::GOpaque<int>, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GOpaque<float>, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GOpaque<cv::Point>, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::GOpaque<cv::Rect>, cv::detail::ArgSpec::RECT>
-// FIXME: causes internal conflicts in GOpaque/descr_of
-// , ExpectedS<cv::GOpaque<cv::Mat>, cv::detail::ArgSpec::GMAT>
-
- // Built-in types
- , ExpectedS<int, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<float, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<int*, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::Point, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<std::string, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<cv::Mat, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<std::vector<int>, cv::detail::ArgSpec::OPAQUE_SPEC>
- , ExpectedS<std::vector<cv::Point>, cv::detail::ArgSpec::OPAQUE_SPEC>
- >;
-
-TYPED_TEST_CASE(ArgSpec, Arg_Spec_Types);
-
-TYPED_TEST(ArgSpec, Basic)
-{
- const auto this_spec = cv::detail::GTypeTraits<typename TestFixture::Type>::spec;
- EXPECT_EQ(TestFixture::Spec, this_spec);
-}
-
-// }}
////////////////////////////////////////////////////////////////////////////////
TEST(GArg, HasWrap)
cv::GArg arg2 = cv::GArg(cv::GOpaque<cv::Point>());
EXPECT_NO_THROW(arg2.get<cv::detail::GOpaqueU>());
}
-
-
} // namespace opencv_test
#include <ade/util/zip_range.hpp> // util::indexed
#include <opencv2/gapi/gkernel.hpp>
+#include <opencv2/gapi/gcommon.hpp>
#include "compiler/gmodelbuilder.hpp"
#include "compiler/gmodel.hpp" // RcDesc, GModel::init
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)
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<ade::NodeHandle> collectOperations(const cv::gimpl::GModel::Graph& gr)
std::vector<char> m_buffer;
};
+namespace
+{
+ template<typename T>
+ bool operator==(const cv::detail::VectorRef& a, const cv::detail::VectorRef& b)
+ {
+ return a.rref<T>() == b.rref<T>();
+ }
+
+ template<typename T>
+ bool operator==(const cv::detail::OpaqueRef& a, const cv::detail::OpaqueRef& b)
+ {
+ return a.rref<T>() == b.rref<T>();
+ }
+}
+
TEST_F(S11N_Basic, Test_int_pos) {
int x = 42;
put(x);
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::GRunArg>();
+ cv::detail::OpaqueRef out_op = cv::util::get<cv::detail::OpaqueRef>(out_v);
+ EXPECT_TRUE(operator==<int>(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::GRunArgs>();
+ cv::detail::OpaqueRef out_op1 = cv::util::get<cv::detail::OpaqueRef>(out_v[0]);
+ cv::detail::OpaqueRef out_op2 = cv::util::get<cv::detail::OpaqueRef>(out_v[1]);
+ EXPECT_TRUE(operator==<cv::Point>(op1, out_op1));
+ EXPECT_TRUE(operator==<cv::Size>(op2, out_op2));
+}
+
+TEST_F(S11N_Basic, Test_RunArg_Array) {
+ auto op = cv::detail::VectorRef(std::vector<cv::Mat>{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::GRunArg>();
+ cv::detail::VectorRef out_op = cv::util::get<cv::detail::VectorRef>(out_v);
+ auto vec1 = op.rref<cv::Mat>();
+ auto vec2 = out_op.rref<cv::Mat>();
+ 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>{cv::Scalar(11), cv::Scalar(31)};
+ auto vec_d = std::vector<double>{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::GRunArgs>();
+ cv::detail::VectorRef out_op1 = cv::util::get<cv::detail::VectorRef>(out_v[0]);
+ cv::detail::VectorRef out_op2 = cv::util::get<cv::detail::VectorRef>(out_v[1]);
+ EXPECT_TRUE(operator==<cv::Scalar>(op1, out_op1));
+ EXPECT_TRUE(operator==<double>(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);
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)
{
}
}
+namespace ThisTest
+{
+ using GOpBool = GOpaque<bool>;
+ using GOpInt = GOpaque<int>;
+ using GOpDouble = GOpaque<double>;
+ using GOpPoint = GOpaque<cv::Point>;
+ using GOpSize = GOpaque<cv::Size>;
+ using GOpRect = GOpaque<cv::Rect>;
+
+ using GOpOut = std::tuple<GOpPoint, GOpSize, GOpRect>;
+
+ G_TYPED_KERNEL_M(OpGenerate, <GOpOut(GOpBool, GOpInt, GOpDouble)>, "test.s11n.gopaque")
+ {
+ static std::tuple<GOpaqueDesc, GOpaqueDesc, GOpaqueDesc> 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<int>(d);
+ r = cv::Rect(ii, ii, ii, ii);
+ }
+ };
+
+ using GArrInt = GArray<int>;
+ using GArrDouble = GArray<double>;
+ using GArrPoint = GArray<cv::Point>;
+ using GArrSize = GArray<cv::Size>;
+ using GArrRect = GArray<cv::Rect>;
+ using GArrMat = GArray<cv::Mat>;
+ using GArrScalar = GArray<cv::Scalar>;
+
+ using GArrOut = std::tuple<GArrPoint, GArrSize, GArrRect, GArrMat>;
+
+ G_TYPED_KERNEL_M(ArrGenerate, <GArrOut(GArrInt, GArrInt, GArrDouble, GArrScalar)>, "test.s11n.garray")
+ {
+ static std::tuple<GArrayDesc, GArrayDesc, GArrayDesc, GArrayDesc> 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<int>& b, const std::vector<int>& i,
+ const std::vector<double>& d, const std::vector<cv::Scalar>& sc,
+ std::vector<cv::Point>& p, std::vector<cv::Size>& s,
+ std::vector<cv::Rect>& r, std::vector<cv::Mat>& 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<int>(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, <std::tuple<GArrInt,GOpSize>(GOpInt, GArrSize)>, "test.s11n.oparrk1")
+ {
+ static std::tuple<GArrayDesc, GOpaqueDesc> 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<cv::Size>& vs,
+ std::vector<int>& 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, <std::tuple<GOpDouble,GArrPoint>(GArrInt, GOpSize)>, "test.s11n.oparrk2")
+ {
+ static std::tuple<GOpaqueDesc, GArrayDesc> 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<int>& vi, const cv::Size& s,
+ double& d, std::vector<cv::Point>& 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<cv::GComputation>(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<OCVOpGenerate>()));
+
+ EXPECT_EQ(pp, cv::Point(i, i*2));
+ EXPECT_EQ(s, cv::Size(42, 42));
+ int ii = static_cast<int>(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<cv::GComputation>(p);
+
+ std::vector<int> b {1, 0, -1};
+ std::vector<int> i {3, 0 , 59};
+ std::vector<double> d {0.7, 120.5, 44.14};
+ std::vector<cv::Scalar> sc {cv::Scalar::all(10), cv::Scalar::all(15), cv::Scalar::all(99)};
+ std::vector<cv::Point> pp;
+ std::vector<cv::Size> s;
+ std::vector<cv::Rect> r;
+ std::vector<cv::Mat> m;
+ dc.apply(cv::gin(b, i, d, sc), cv::gout(pp, s, r, m), cv::compile_args(cv::gapi::kernels<OCVArrGenerate>()));
+
+ 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<int>(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<cv::GComputation>(p);
+
+ int i = 42;
+ std::vector<cv::Size> s{cv::Size(11, 22), cv::Size(13, 18)};
+ double d;
+ std::vector<cv::Point> pp;
+
+ dc.apply(cv::gin(i, s), cv::gout(d, pp), cv::compile_args(cv::gapi::kernels<OCVOpArrK1, OCVOpArrK2>()));
+
+ 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