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
This commit is contained in:
Alexey Smirnov 2020-09-07 20:10:03 +03:00 committed by GitHub
parent 620629593b
commit a3e8c6e866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 648 additions and 228 deletions

View File

@ -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<typename... Ts> inline GRunArgs gin(const Ts&... args)
{

View File

@ -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<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.
@ -112,6 +87,11 @@ namespace detail
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;
};
@ -128,6 +108,11 @@ namespace detail
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
@ -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<T>::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<BasicVectorRef> m_ref;
cv::detail::OpaqueKind m_kind;
template<typename T> inline void check() const
{
@ -262,9 +245,17 @@ namespace detail
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()
{
@ -274,6 +265,12 @@ namespace detail
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>();
@ -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<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;

View File

@ -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<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

View File

@ -26,8 +26,8 @@
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
@ -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<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());
}
@ -238,8 +238,8 @@ public:
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);
}

View File

@ -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 <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;
};
@ -97,6 +101,12 @@ namespace detail
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
@ -213,6 +223,7 @@ namespace detail
class OpaqueRef
{
std::shared_ptr<BasicOpaqueRef> m_ref;
cv::detail::OpaqueKind m_kind;
template<typename T> inline void check() const
{
@ -222,13 +233,19 @@ namespace detail
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()
{
@ -238,6 +255,12 @@ namespace detail
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>();
@ -285,10 +308,12 @@ private:
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;

View File

@ -41,98 +41,45 @@ namespace detail
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();}
@ -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<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();}
@ -176,7 +123,6 @@ namespace detail
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;};

View File

@ -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 &)
{

View File

@ -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 &)
{

View File

@ -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)
{
}

View File

@ -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

View File

@ -44,6 +44,8 @@ std::vector<char> 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<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();
}

View File

@ -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
{
GAPI_Assert(false && "Serialization: Unsupported << for cv::detail::VectorRef &");
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<>>
{
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
@ -350,7 +410,6 @@ I::IStream& operator>> (I::IStream& is, cv::gimpl::Data::Storage &s) {
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
@ -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<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;
}
@ -478,6 +576,14 @@ void serialize( I::OStream& os
, 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)
@ -488,7 +594,7 @@ void serialize( I::OStream& os
}
}
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;
}

View File

@ -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<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

View File

@ -194,7 +194,7 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj> &&input_objs,
{
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

View File

@ -614,7 +614,7 @@ struct InferList2: public cv::detail::KernelTag {
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);
@ -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<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)

View File

@ -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;
}

View File

@ -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 <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/gkernel.hpp>
#include <opencv2/gapi/gcommon.hpp>
#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

View File

@ -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);
}

View File

@ -55,7 +55,6 @@ namespace detail
template<> struct GTypeTraits<cv::gimpl::RcDesc>
{
static constexpr const ArgKind kind = ArgKind::GOBJREF;
static constexpr const ArgSpec spec = ArgSpec::OPAQUE_SPEC;
};
}

View File

@ -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<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);
}

View File

@ -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<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

View File

@ -214,4 +214,25 @@ TEST(GOpaque_OpaqueRef, TestMov)
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

View File

@ -76,61 +76,6 @@ TYPED_TEST(GArgKind, RValue)
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)
@ -170,6 +115,4 @@ TEST(GArg, GOpaqueU)
cv::GArg arg2 = cv::GArg(cv::GOpaque<cv::Point>());
EXPECT_NO_THROW(arg2.get<cv::detail::GOpaqueU>());
}
} // namespace opencv_test

View File

@ -10,6 +10,7 @@
#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
@ -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<ade::NodeHandle> collectOperations(const cv::gimpl::GModel::Graph& gr)

View File

@ -23,6 +23,21 @@ private:
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);
@ -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::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);
@ -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)
{

View File

@ -282,4 +282,206 @@ TEST(S11N, Pipeline_CustomRGB2YUV)
}
}
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