1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

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
26 changed files with 648 additions and 228 deletions
+3 -2
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)
{
+32 -38
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;
@@ -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
@@ -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);
}
+30 -5
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;
@@ -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;};