Merge pull request #17694 from dbudniko:dbudniko/serialization_args2
authorDmitry Budnikov <Dmitry.Budnikov@intel.com>
Mon, 13 Jul 2020 19:24:46 +0000 (22:24 +0300)
committerGitHub <noreply@github.com>
Mon, 13 Jul 2020 19:24:46 +0000 (19:24 +0000)
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

modules/gapi/include/opencv2/gapi/garg.hpp
modules/gapi/include/opencv2/gapi/s11n.hpp
modules/gapi/src/api/s11n.cpp
modules/gapi/src/backends/common/serialization.cpp
modules/gapi/src/backends/common/serialization.hpp
modules/gapi/test/s11n/gapi_s11n_tests.cpp

index 980806f..2f4b90f 100644 (file)
@@ -133,6 +133,11 @@ using GRunArgP = util::variant<
     >;
 using GRunArgsP = std::vector<GRunArgP>;
 
+namespace gapi
+{
+    GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &results);
+}
+
 template<typename... Ts> inline GRunArgs gin(const Ts&... args)
 {
     return GRunArgs{ GRunArg(detail::wrap_host_helper<Ts>::wrap_in(args))... };
index 689eda5..c669b73 100644 (file)
@@ -17,6 +17,14 @@ namespace detail {
     GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &p);
 } // 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);
 //namespace{
 
@@ -25,11 +33,23 @@ T deserialize(const std::vector<char> &p);
 
 //} //ananymous namespace
 
+GAPI_EXPORTS std::vector<char> serialize(const cv::GMetaArgs&);
+GAPI_EXPORTS std::vector<char> serialize(const cv::GRunArgs&);
+
 template<> inline
 cv::GComputation deserialize(const std::vector<char> &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
index c17b78c..f3893dd 100644 (file)
@@ -5,6 +5,7 @@
 // Copyright (C) 2020 Intel Corporation
 
 #include <opencv2/gapi/s11n.hpp>
+#include <opencv2/gapi/garg.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);
     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;
+}
index 3a60cbf..7b275a7 100644 (file)
@@ -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::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
 
 namespace {
@@ -363,7 +408,6 @@ I::IStream& operator>> (I::IStream& is, cv::GArg &arg) {
     return is;
 }
 
-
 I::OStream& operator<< (I::OStream& os, const cv::GKernel &k) {
     return os << k.name << k.tag << k.outShapes;
 }
@@ -608,6 +652,24 @@ I::IStream& ByteMemoryInStream::operator>> (std::string& str) {
     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 gimpl
 } // namespace cv
index a88c8c2..a7b8537 100644 (file)
 
 #include "compiler/gmodel.hpp"
 
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+#pragma warning(disable: 4702)
+#endif
+
 namespace cv {
 namespace gimpl {
 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::IStream& operator>> (I::IStream& is,       cv::Mat &m);
 
+
+
 // G-API types /////////////////////////////////////////////////////////////////
 
 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::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::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::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::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);
 
 // 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 ////////////////////////////////////////
 template<typename K, typename V>
 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);
 }
 
+// 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 //////////////////////////////////////////
 
 // Basic in-memory stream implementations.
@@ -305,6 +331,10 @@ public:
     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 gimpl
index 5c4fd2a..00ee10f 100644 (file)
@@ -125,4 +125,160 @@ TEST_F(S11N_Basic, Test_Mat_view) {
     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