From: Dmitry Budnikov Date: Mon, 13 Jul 2020 19:24:46 +0000 (+0300) Subject: Merge pull request #17694 from dbudniko:dbudniko/serialization_args2 X-Git-Tag: submit/tizen/20210224.033012~2^2~126 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=521aac9665625b3583522a9c2e89109a81ae886f;p=platform%2Fupstream%2Fopencv.git 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 --- diff --git a/modules/gapi/include/opencv2/gapi/garg.hpp b/modules/gapi/include/opencv2/gapi/garg.hpp index 980806f..2f4b90f 100644 --- a/modules/gapi/include/opencv2/gapi/garg.hpp +++ b/modules/gapi/include/opencv2/gapi/garg.hpp @@ -133,6 +133,11 @@ using GRunArgP = util::variant< >; using GRunArgsP = std::vector; +namespace gapi +{ + GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &results); +} + template inline GRunArgs gin(const Ts&... args) { return GRunArgs{ GRunArg(detail::wrap_host_helper::wrap_in(args))... }; diff --git a/modules/gapi/include/opencv2/gapi/s11n.hpp b/modules/gapi/include/opencv2/gapi/s11n.hpp index 689eda5..c669b73 100644 --- a/modules/gapi/include/opencv2/gapi/s11n.hpp +++ b/modules/gapi/include/opencv2/gapi/s11n.hpp @@ -17,6 +17,14 @@ namespace detail { GAPI_EXPORTS cv::GComputation getGraph(const std::vector &p); } // namespace detail +namespace detail { + GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector &p); +} // namespace detail + +namespace detail { + GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector &p); +} // namespace detail + GAPI_EXPORTS std::vector serialize(const cv::GComputation &c); //namespace{ @@ -25,11 +33,23 @@ T deserialize(const std::vector &p); //} //ananymous namespace +GAPI_EXPORTS std::vector serialize(const cv::GMetaArgs&); +GAPI_EXPORTS std::vector serialize(const cv::GRunArgs&); + template<> inline cv::GComputation deserialize(const std::vector &p) { return detail::getGraph(p); } +template<> inline +cv::GMetaArgs deserialize(const std::vector &p) { + return detail::getMetaArgs(p); +} + +template<> inline +cv::GRunArgs deserialize(const std::vector &p) { + return detail::getRunArgs(p); +} } // namespace gapi diff --git a/modules/gapi/src/api/s11n.cpp b/modules/gapi/src/api/s11n.cpp index c17b78c..f3893dd 100644 --- a/modules/gapi/src/api/s11n.cpp +++ b/modules/gapi/src/api/s11n.cpp @@ -5,6 +5,7 @@ // Copyright (C) 2020 Intel Corporation #include +#include #include "backends/common/serialization.hpp" @@ -18,3 +19,61 @@ cv::GComputation cv::gapi::detail::getGraph(const std::vector &p) { cv::gimpl::s11n::ByteMemoryInStream is(p); return cv::GComputation(is); } + +cv::GMetaArgs cv::gapi::detail::getMetaArgs(const std::vector &p) { + cv::gimpl::s11n::ByteMemoryInStream is(p); + return meta_args_deserialize(is); +} + +cv::GRunArgs cv::gapi::detail::getRunArgs(const std::vector &p) { + cv::gimpl::s11n::ByteMemoryInStream is(p); + return run_args_deserialize(is); +} + +std::vector cv::gapi::serialize(const cv::GMetaArgs& ma) +{ + cv::gimpl::s11n::ByteMemoryOutStream os; + serialize(os, ma); + return os.data(); +} + +std::vector 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() : + outputs.emplace_back((cv::UMat*)(&(cv::util::get(res_obj)))); + break; +#endif + case cv::GRunArg::index_of() : + outputs.emplace_back((cv::Mat*)(&(cv::util::get(res_obj)))); + break; + case cv::GRunArg::index_of() : + outputs.emplace_back((cv::Scalar*)(&(cv::util::get(res_obj)))); + break; + case T::index_of() : + outputs.emplace_back(cv::util::get(res_obj)); + break; + case T::index_of() : + outputs.emplace_back(cv::util::get(res_obj)); + break; + default: + GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode. + break; + } + } + return outputs; +} diff --git a/modules/gapi/src/backends/common/serialization.cpp b/modules/gapi/src/backends/common/serialization.cpp index 3a60cbf..7b275a7 100644 --- a/modules/gapi/src/backends/common/serialization.cpp +++ b/modules/gapi/src/backends/common/serialization.cpp @@ -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 diff --git a/modules/gapi/src/backends/common/serialization.hpp b/modules/gapi/src/backends/common/serialization.hpp index a88c8c2..a7b8537 100644 --- a/modules/gapi/src/backends/common/serialization.hpp +++ b/modules/gapi/src/backends/common/serialization.hpp @@ -15,6 +15,10 @@ #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 -I::OStream& operator<< (I::OStream& os, const std::vector &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 -I::IStream& operator>> (I::IStream& is, std::vector &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 I::OStream& operator<< (I::OStream& os, const std::unordered_map &m) { @@ -256,6 +256,32 @@ I::IStream& operator>> (I::IStream& is, cv::util::variant &v) { return detail::get_v, 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 +I::OStream& operator<< (I::OStream& os, const std::vector &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 +I::IStream& operator >> (I::IStream& is, std::vector &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 diff --git a/modules/gapi/test/s11n/gapi_s11n_tests.cpp b/modules/gapi/test/s11n/gapi_s11n_tests.cpp index 5c4fd2a..00ee10f 100644 --- a/modules/gapi/test/s11n/gapi_s11n_tests.cpp +++ b/modules/gapi/test/s11n/gapi_s11n_tests.cpp @@ -125,4 +125,160 @@ TEST_F(S11N_Basic, Test_Mat_view) { EXPECT_EQ(0, cv::norm(view, get(), cv::NORM_INF)); } +TEST_F(S11N_Basic, Test_MatDesc) { + cv::GMatDesc v = { CV_8U, 1, {320,240} }; + put(v); + EXPECT_EQ(v, get()); +} + +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::GMatDesc out_desc = cv::util::get(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::GMatDesc out_desc1 = cv::util::get(out_v[0]); + cv::GMatDesc out_desc2 = cv::util::get(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(); + if (!util::holds_alternative(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::Mat out_mat = cv::util::get(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::Mat out_mat1 = cv::util::get(out_v[0]); + cv::Mat out_mat2 = cv::util::get(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::Scalar out_scalar = cv::util::get(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::Scalar out_scalar1 = cv::util::get(out_v[0]); + cv::Scalar out_scalar2 = cv::util::get(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(); + unsigned int i = 0; + for (auto it : out_v) + { + using T = cv::GRunArg; + switch (it.index()) + { + case T::index_of() : + { + cv::Mat out_mat = cv::util::get(out_v[i]); + EXPECT_EQ(0, cv::norm(mat, out_mat, cv::NORM_INF)); + } break; + case T::index_of() : + { + cv::Scalar out_scalar = cv::util::get(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* out_mat = cv::util::get(it); + EXPECT_EQ(mat.size(), out_mat->size()); + } break; + case T::index_of() : + { + cv::Scalar* out_scalar = cv::util::get(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