Merge pull request #17694 from dbudniko:dbudniko/serialization_args2

G-API args serialization

* args serialization

* GRunArgP draft

* UMat added

* bind added

* DmitryM's review addressed. Code clean up required.

* fix android build

* bind test added

* more comments addressed

* try to fix Mac build

* clean up

* header-based generic implementation (GRunArg)

* clang again

* one more attempt for clang

* more clean up

* More Dmitry's comments addressed.

* monostate removed

* Top level functions and some other comments addressed.

* fix warnings

* disable warning
pull/17831/head
Dmitry Budnikov 5 years ago committed by GitHub
parent 3d50bde46e
commit 521aac9665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      modules/gapi/include/opencv2/gapi/garg.hpp
  2. 20
      modules/gapi/include/opencv2/gapi/s11n.hpp
  3. 59
      modules/gapi/src/api/s11n.cpp
  4. 64
      modules/gapi/src/backends/common/serialization.cpp
  5. 80
      modules/gapi/src/backends/common/serialization.hpp
  6. 156
      modules/gapi/test/s11n/gapi_s11n_tests.cpp

@ -133,6 +133,11 @@ using GRunArgP = util::variant<
>; >;
using GRunArgsP = std::vector<GRunArgP>; using GRunArgsP = std::vector<GRunArgP>;
namespace gapi
{
GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &results);
}
template<typename... Ts> inline GRunArgs gin(const Ts&... args) template<typename... Ts> inline GRunArgs gin(const Ts&... args)
{ {
return GRunArgs{ GRunArg(detail::wrap_host_helper<Ts>::wrap_in(args))... }; return GRunArgs{ GRunArg(detail::wrap_host_helper<Ts>::wrap_in(args))... };

@ -17,6 +17,14 @@ namespace detail {
GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &p); GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &p);
} // namespace detail } // namespace detail
namespace detail {
GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector<char> &p);
} // namespace detail
namespace detail {
GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector<char> &p);
} // namespace detail
GAPI_EXPORTS std::vector<char> serialize(const cv::GComputation &c); GAPI_EXPORTS std::vector<char> serialize(const cv::GComputation &c);
//namespace{ //namespace{
@ -25,11 +33,23 @@ T deserialize(const std::vector<char> &p);
//} //ananymous namespace //} //ananymous namespace
GAPI_EXPORTS std::vector<char> serialize(const cv::GMetaArgs&);
GAPI_EXPORTS std::vector<char> serialize(const cv::GRunArgs&);
template<> inline template<> inline
cv::GComputation deserialize(const std::vector<char> &p) { cv::GComputation deserialize(const std::vector<char> &p) {
return detail::getGraph(p); return detail::getGraph(p);
} }
template<> inline
cv::GMetaArgs deserialize(const std::vector<char> &p) {
return detail::getMetaArgs(p);
}
template<> inline
cv::GRunArgs deserialize(const std::vector<char> &p) {
return detail::getRunArgs(p);
}
} // namespace gapi } // namespace gapi

@ -5,6 +5,7 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020 Intel Corporation
#include <opencv2/gapi/s11n.hpp> #include <opencv2/gapi/s11n.hpp>
#include <opencv2/gapi/garg.hpp>
#include "backends/common/serialization.hpp" #include "backends/common/serialization.hpp"
@ -18,3 +19,61 @@ cv::GComputation cv::gapi::detail::getGraph(const std::vector<char> &p) {
cv::gimpl::s11n::ByteMemoryInStream is(p); cv::gimpl::s11n::ByteMemoryInStream is(p);
return cv::GComputation(is); return cv::GComputation(is);
} }
cv::GMetaArgs cv::gapi::detail::getMetaArgs(const std::vector<char> &p) {
cv::gimpl::s11n::ByteMemoryInStream is(p);
return meta_args_deserialize(is);
}
cv::GRunArgs cv::gapi::detail::getRunArgs(const std::vector<char> &p) {
cv::gimpl::s11n::ByteMemoryInStream is(p);
return run_args_deserialize(is);
}
std::vector<char> cv::gapi::serialize(const cv::GMetaArgs& ma)
{
cv::gimpl::s11n::ByteMemoryOutStream os;
serialize(os, ma);
return os.data();
}
std::vector<char> cv::gapi::serialize(const cv::GRunArgs& ra)
{
cv::gimpl::s11n::ByteMemoryOutStream os;
serialize(os, ra);
return os.data();
}
cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results)
{
cv::GRunArgsP outputs;
outputs.reserve(results.size());
for (cv::GRunArg &res_obj : results)
{
using T = cv::GRunArg;
switch (res_obj.index())
{
#if !defined(GAPI_STANDALONE)
case T::index_of<cv::UMat>() :
outputs.emplace_back((cv::UMat*)(&(cv::util::get<cv::UMat>(res_obj))));
break;
#endif
case cv::GRunArg::index_of<cv::Mat>() :
outputs.emplace_back((cv::Mat*)(&(cv::util::get<cv::Mat>(res_obj))));
break;
case cv::GRunArg::index_of<cv::Scalar>() :
outputs.emplace_back((cv::Scalar*)(&(cv::util::get<cv::Scalar>(res_obj))));
break;
case T::index_of<cv::detail::VectorRef>() :
outputs.emplace_back(cv::util::get<cv::detail::VectorRef>(res_obj));
break;
case T::index_of<cv::detail::OpaqueRef>() :
outputs.emplace_back(cv::util::get<cv::detail::OpaqueRef>(res_obj));
break;
default:
GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode.
break;
}
}
return outputs;
}

@ -268,6 +268,51 @@ I::IStream& operator>> (I::IStream& is, cv::GOpaqueDesc &) {return is;}
I::OStream& operator<< (I::OStream& os, const cv::GArrayDesc &) {return os;} I::OStream& operator<< (I::OStream& os, const cv::GArrayDesc &) {return os;}
I::IStream& operator>> (I::IStream& is, cv::GArrayDesc &) {return is;} I::IStream& operator>> (I::IStream& is, cv::GArrayDesc &) {return is;}
#if !defined(GAPI_STANDALONE)
I::OStream& operator<< (I::OStream& os, const cv::UMat &)
{
GAPI_Assert(false && "Serialization: Unsupported << for UMat");
return os;
}
I::IStream& operator >> (I::IStream& is, cv::UMat &)
{
GAPI_Assert(false && "Serialization: Unsupported >> for UMat");
return is;
}
#endif // !defined(GAPI_STANDALONE)
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::IStreamSource::Ptr &)
{
GAPI_Assert(false && "Serialization: Unsupported << for IStreamSource::Ptr");
return os;
}
I::IStream& operator >> (I::IStream& is, cv::gapi::wip::IStreamSource::Ptr &)
{
GAPI_Assert("Serialization: Unsupported >> for IStreamSource::Ptr");
return is;
}
I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef &)
{
GAPI_Assert(false && "Serialization: Unsupported << for cv::detail::VectorRef &");
return os;
}
I::IStream& operator >> (I::IStream& is, cv::detail::VectorRef &)
{
GAPI_Assert(false && "Serialization: Unsupported >> for cv::detail::VectorRef &");
return is;
}
I::OStream& operator<< (I::OStream& os, const cv::detail::OpaqueRef &)
{
GAPI_Assert(false && "Serialization: Unsupported << for cv::detail::OpaqueRef &");
return os;
}
I::IStream& operator >> (I::IStream& is, cv::detail::OpaqueRef &)
{
GAPI_Assert(false && "Serialization: Unsupported >> for cv::detail::OpaqueRef &");
return is;
}
// Enums and structures // Enums and structures
namespace { namespace {
@ -363,7 +408,6 @@ I::IStream& operator>> (I::IStream& is, cv::GArg &arg) {
return is; return is;
} }
I::OStream& operator<< (I::OStream& os, const cv::GKernel &k) { I::OStream& operator<< (I::OStream& os, const cv::GKernel &k) {
return os << k.name << k.tag << k.outShapes; return os << k.name << k.tag << k.outShapes;
} }
@ -608,6 +652,24 @@ I::IStream& ByteMemoryInStream::operator>> (std::string& str) {
return *this; return *this;
} }
GAPI_EXPORTS void serialize(I::OStream& os, const cv::GMetaArgs &ma) {
os << ma;
}
GAPI_EXPORTS void serialize(I::OStream& os, const cv::GRunArgs &ra) {
os << ra;
}
GAPI_EXPORTS GMetaArgs meta_args_deserialize(I::IStream& is) {
GMetaArgs s;
is >> s;
return s;
}
GAPI_EXPORTS GRunArgs run_args_deserialize(I::IStream& is) {
GRunArgs s;
is >> s;
return s;
}
} // namespace s11n } // namespace s11n
} // namespace gimpl } // namespace gimpl
} // namespace cv } // namespace cv

@ -15,6 +15,10 @@
#include "compiler/gmodel.hpp" #include "compiler/gmodel.hpp"
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
#pragma warning(disable: 4702)
#endif
namespace cv { namespace cv {
namespace gimpl { namespace gimpl {
namespace s11n { namespace s11n {
@ -85,6 +89,8 @@ GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Scalar &s);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Mat &m); GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Mat &m);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Mat &m); GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Mat &m);
// G-API types ///////////////////////////////////////////////////////////////// // G-API types /////////////////////////////////////////////////////////////////
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::util::monostate ); GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::util::monostate );
@ -111,6 +117,11 @@ GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::Protocol &
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GArg &arg); GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GArg &arg);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GArg &arg); GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GArg &arg);
//Forward declaration
//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::OStream& operator<< (I::OStream& os, const cv::GKernel &k);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GKernel &k); GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GKernel &k);
@ -126,6 +137,20 @@ GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GOpaqueDesc &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GArrayDesc &); GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GArrayDesc &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GArrayDesc &); GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GArrayDesc &);
#if !defined(GAPI_STANDALONE)
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::UMat &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::UMat &);
#endif // !defined(GAPI_STANDALONE)
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::IStreamSource::Ptr &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::IStreamSource::Ptr &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::detail::VectorRef &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::detail::OpaqueRef &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::detail::OpaqueRef &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::RcDesc &rc); GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::RcDesc &rc);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::RcDesc &rc); GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::RcDesc &rc);
@ -163,31 +188,6 @@ GAPI_EXPORTS GSerialized deserialize(I::IStream& is);
GAPI_EXPORTS void reconstruct(const GSerialized &s, ade::Graph &g); GAPI_EXPORTS void reconstruct(const GSerialized &s, ade::Graph &g);
// Legacy ////////////////////////////////////////////////////////////////////// // Legacy //////////////////////////////////////////////////////////////////////
// Generic: vector serialization ///////////////////////////////////////////////
template<typename T>
I::OStream& operator<< (I::OStream& os, const std::vector<T> &ts) {
//const std::size_t sz = ts.size(); // explicitly specify type
const uint32_t sz = (uint32_t)ts.size(); // explicitly specify type
os << sz;
for (auto &&v : ts) os << v;
return os;
}
template<typename T>
I::IStream& operator>> (I::IStream& is, std::vector<T> &ts) {
//std::size_t sz = 0u;
uint32_t sz = 0u;
is >> sz;
if (sz == 0u) {
ts.clear();
} else {
ts.resize(sz);
for (auto &&i : ade::util::iota(sz)) is >> ts[i];
}
return is;
}
// Generic: unordered_map serialization //////////////////////////////////////// // Generic: unordered_map serialization ////////////////////////////////////////
template<typename K, typename V> template<typename K, typename V>
I::OStream& operator<< (I::OStream& os, const std::unordered_map<K, V> &m) { I::OStream& operator<< (I::OStream& os, const std::unordered_map<K, V> &m) {
@ -256,6 +256,32 @@ I::IStream& operator>> (I::IStream& is, cv::util::variant<Ts...> &v) {
return detail::get_v<cv::util::variant<Ts...>, Ts...>(is, v, 0u, idx); return detail::get_v<cv::util::variant<Ts...>, Ts...>(is, v, 0u, idx);
} }
// Generic: vector serialization ///////////////////////////////////////////////
// Moved here to fix CLang issues https://clang.llvm.org/compatibility.html
// Unqualified lookup in templates
template<typename T>
I::OStream& operator<< (I::OStream& os, const std::vector<T> &ts) {
//const std::size_t sz = ts.size(); // explicitly specify type
const uint32_t sz = (uint32_t)ts.size(); // explicitly specify type
os << sz;
for (auto &&v : ts) os << v;
return os;
}
template<typename T>
I::IStream& operator >> (I::IStream& is, std::vector<T> &ts) {
//std::size_t sz = 0u;
uint32_t sz = 0u;
is >> sz;
if (sz == 0u) {
ts.clear();
}
else {
ts.resize(sz);
for (auto &&i : ade::util::iota(sz)) is >> ts[i];
}
return is;
}
// FIXME: Basic Stream implementaions ////////////////////////////////////////// // FIXME: Basic Stream implementaions //////////////////////////////////////////
// Basic in-memory stream implementations. // Basic in-memory stream implementations.
@ -305,6 +331,10 @@ public:
virtual I::IStream& operator>> (std::string &) override; virtual I::IStream& operator>> (std::string &) override;
}; };
GAPI_EXPORTS void serialize(I::OStream& os, const cv::GMetaArgs &ma);
GAPI_EXPORTS void serialize(I::OStream& os, const cv::GRunArgs &ra);
GAPI_EXPORTS GMetaArgs meta_args_deserialize(I::IStream& is);
GAPI_EXPORTS GRunArgs run_args_deserialize(I::IStream& is);
} // namespace s11n } // namespace s11n
} // namespace gimpl } // namespace gimpl

@ -125,4 +125,160 @@ TEST_F(S11N_Basic, Test_Mat_view) {
EXPECT_EQ(0, cv::norm(view, get<cv::Mat>(), cv::NORM_INF)); EXPECT_EQ(0, cv::norm(view, get<cv::Mat>(), cv::NORM_INF));
} }
TEST_F(S11N_Basic, Test_MatDesc) {
cv::GMatDesc v = { CV_8U, 1, {320,240} };
put(v);
EXPECT_EQ(v, get<cv::GMatDesc>());
}
TEST_F(S11N_Basic, Test_MetaArg_MatDesc) {
cv::GMatDesc desc = { CV_8U, 1,{ 320,240 } };
auto v = cv::GMetaArg{ desc };
put(v);
cv::GMetaArg out_v = get<cv::GMetaArg>();
cv::GMatDesc out_desc = cv::util::get<cv::GMatDesc>(out_v);
EXPECT_EQ(desc, out_desc);
}
TEST_F(S11N_Basic, Test_MetaArgs_MatDesc) {
cv::GMatDesc desc1 = { CV_8U, 1,{ 320,240 } };
cv::GMatDesc desc2 = { CV_8U, 1,{ 640,480 } };
GMetaArgs v;
v.resize(2);
v[0] = cv::GMetaArg{ desc1 };
v[1] = cv::GMetaArg{ desc2 };
put(v);
cv::GMetaArgs out_v = get<cv::GMetaArgs>();
cv::GMatDesc out_desc1 = cv::util::get<cv::GMatDesc>(out_v[0]);
cv::GMatDesc out_desc2 = cv::util::get<cv::GMatDesc>(out_v[1]);
EXPECT_EQ(desc1, out_desc1);
EXPECT_EQ(desc2, out_desc2);
}
TEST_F(S11N_Basic, Test_MetaArg_Monostate) {
GMetaArg v;
put(v);
cv::GMetaArg out_v = get<cv::GMetaArg>();
if (!util::holds_alternative<util::monostate>(out_v))
{
GTEST_FAIL();
}
}
TEST_F(S11N_Basic, Test_RunArg_Mat) {
cv::Mat mat = cv::Mat::eye(cv::Size(64, 64), CV_8UC3);
auto v = cv::GRunArg{ mat };
put(v);
cv::GRunArg out_v = get<cv::GRunArg>();
cv::Mat out_mat = cv::util::get<cv::Mat>(out_v);
EXPECT_EQ(0, cv::norm(mat, out_mat, cv::NORM_INF));
}
TEST_F(S11N_Basic, Test_RunArgs_Mat) {
cv::Mat mat1 = cv::Mat::eye(cv::Size(64, 64), CV_8UC3);
cv::Mat mat2 = cv::Mat::eye(cv::Size(128, 128), CV_8UC3);
GRunArgs v;
v.resize(2);
v[0] = cv::GRunArg{ mat1 };
v[1] = cv::GRunArg{ mat2 };
put(v);
cv::GRunArgs out_v = get<cv::GRunArgs>();
cv::Mat out_mat1 = cv::util::get<cv::Mat>(out_v[0]);
cv::Mat out_mat2 = cv::util::get<cv::Mat>(out_v[1]);
EXPECT_EQ(0, cv::norm(mat1, out_mat1, cv::NORM_INF));
EXPECT_EQ(0, cv::norm(mat2, out_mat2, cv::NORM_INF));
}
TEST_F(S11N_Basic, Test_RunArg_Scalar) {
cv::Scalar scalar = cv::Scalar(128, 33, 53);
auto v = cv::GRunArg{ scalar };
put(v);
cv::GRunArg out_v = get<cv::GRunArg>();
cv::Scalar out_scalar = cv::util::get<cv::Scalar>(out_v);
EXPECT_EQ(scalar, out_scalar);
}
TEST_F(S11N_Basic, Test_RunArgs_Scalar) {
cv::Scalar scalar1 = cv::Scalar(128, 33, 53);
cv::Scalar scalar2 = cv::Scalar(64, 15, 23);
GRunArgs v;
v.resize(2);
v[0] = cv::GRunArg{ scalar1 };
v[1] = cv::GRunArg{ scalar2 };
put(v);
cv::GRunArgs out_v = get<cv::GRunArgs>();
cv::Scalar out_scalar1 = cv::util::get<cv::Scalar>(out_v[0]);
cv::Scalar out_scalar2 = cv::util::get<cv::Scalar>(out_v[1]);
EXPECT_EQ(scalar1, out_scalar1);
EXPECT_EQ(scalar2, out_scalar2);
}
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);
GRunArgs v;
v.resize(2);
v[0] = cv::GRunArg{ mat };
v[1] = cv::GRunArg{ scalar };
put(v);
cv::GRunArgs out_v = get<cv::GRunArgs>();
unsigned int i = 0;
for (auto it : out_v)
{
using T = cv::GRunArg;
switch (it.index())
{
case T::index_of<cv::Mat>() :
{
cv::Mat out_mat = cv::util::get<cv::Mat>(out_v[i]);
EXPECT_EQ(0, cv::norm(mat, out_mat, cv::NORM_INF));
} break;
case T::index_of<cv::Scalar>() :
{
cv::Scalar out_scalar = cv::util::get<cv::Scalar>(out_v[i]);
EXPECT_EQ(scalar, out_scalar);
} break;
default:
GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode.
break;
}
i++;
}
}
TEST_F(S11N_Basic, Test_Bind_RunArgs_MatScalar) {
cv::Mat mat = cv::Mat::eye(cv::Size(128, 64), CV_8UC3);
cv::Scalar scalar = cv::Scalar(128, 33, 53);
GRunArgs v;
v.resize(2);
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)
{
using T = cv::GRunArgP;
switch (it.index())
{
case T::index_of<cv::Mat*>() :
{
cv::Mat* out_mat = cv::util::get<cv::Mat*>(it);
EXPECT_EQ(mat.size(), out_mat->size());
} break;
case T::index_of<cv::Scalar*>() :
{
cv::Scalar* out_scalar = cv::util::get<cv::Scalar*>(it);
EXPECT_EQ(out_scalar->val[0], scalar.val[0]);
EXPECT_EQ(out_scalar->val[1], scalar.val[1]);
EXPECT_EQ(out_scalar->val[2], scalar.val[2]);
} break;
default:
GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode.
break;
}
i++;
}
}
} // namespace opencv_test } // namespace opencv_test

Loading…
Cancel
Save