diff --git a/modules/gapi/include/opencv2/gapi/rmat.hpp b/modules/gapi/include/opencv2/gapi/rmat.hpp index 626e67e9ee..ff834b46b1 100644 --- a/modules/gapi/include/opencv2/gapi/rmat.hpp +++ b/modules/gapi/include/opencv2/gapi/rmat.hpp @@ -10,6 +10,16 @@ #include #include +// Forward declaration +namespace cv { +namespace gapi { +namespace s11n { + struct IOStream; + struct IIStream; +} // namespace s11n +} // namespace gapi +} // namespace cv + namespace cv { // "Remote Mat", a general class which provides an abstraction layer over the data @@ -90,6 +100,12 @@ public: // the view when accessed for writing, to ensure that the data from the view // is transferred to the device when the view is destroyed virtual View access(Access) = 0; + virtual void serialize(cv::gapi::s11n::IOStream&) { + GAPI_Assert(false && "Generic serialize method should never be called for RMat adapter"); + } + virtual void deserialize(cv::gapi::s11n::IIStream&) { + GAPI_Assert(false && "Generic deserialize method should never be called for RMat adapter"); + } }; using AdapterP = std::shared_ptr; @@ -113,6 +129,10 @@ public: return dynamic_cast(m_adapter.get()); } + void serialize(cv::gapi::s11n::IOStream& os) const { + m_adapter->serialize(os); + } + private: AdapterP m_adapter = nullptr; }; diff --git a/modules/gapi/include/opencv2/gapi/s11n.hpp b/modules/gapi/include/opencv2/gapi/s11n.hpp index e8a8dbcab4..2fa4e51176 100644 --- a/modules/gapi/include/opencv2/gapi/s11n.hpp +++ b/modules/gapi/include/opencv2/gapi/s11n.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace cv { namespace gapi { @@ -25,6 +26,9 @@ namespace detail { template cv::GCompileArgs getCompileArgs(const std::vector &p); + + template + cv::GRunArgs getRunArgsWithRMats(const std::vector &p); } // namespace detail GAPI_EXPORTS std::vector serialize(const cv::GComputation &c); @@ -59,6 +63,12 @@ typename std::enable_if::value, GCompileArgs>:: type deserialize(const std::vector &p) { return detail::getCompileArgs(p); } + +template inline +typename std::enable_if::value, GRunArgs>:: +type deserialize(const std::vector &p) { + return detail::getRunArgsWithRMats(p); +} } // namespace gapi } // namespace cv @@ -123,6 +133,27 @@ GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Scalar &s); GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::Mat &m); GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Mat &m); +// FIXME: for GRunArgs serailization +#if !defined(GAPI_STANDALONE) +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::UMat &); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::UMat &); +#endif // !defined(GAPI_STANDALONE) + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::RMat &r); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::RMat &r); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::gapi::wip::IStreamSource::Ptr &); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::gapi::wip::IStreamSource::Ptr &); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::VectorRef &); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::VectorRef &); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::OpaqueRef &); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::OpaqueRef &); + +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::MediaFrame &); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::MediaFrame &); + // Generic STL types //////////////////////////////////////////////////////////////// template IOStream& operator<< (IOStream& os, const std::map &m) { @@ -184,6 +215,52 @@ IIStream& operator>> (IIStream& is, std::vector &ts) { } return is; } + +// Generic: variant serialization +namespace detail { +template +IOStream& put_v(IOStream&, const V&, std::size_t) { + GAPI_Assert(false && "variant>>: requested index is invalid"); +}; +template +IOStream& put_v(IOStream& os, const V& v, std::size_t x) { + return (x == 0u) + ? os << cv::util::get(v) + : put_v(os, v, x-1); +} +template +IIStream& get_v(IIStream&, V&, std::size_t, std::size_t) { + GAPI_Assert(false && "variant<<: requested index is invalid"); +} +template +IIStream& get_v(IIStream& is, V& v, std::size_t i, std::size_t gi) { + if (i == gi) { + X x{}; + is >> x; + v = V{std::move(x)}; + return is; + } else return get_v(is, v, i+1, gi); +} +} // namespace detail + +template +IOStream& operator<< (IOStream& os, const cv::util::variant &v) { + os << static_cast(v.index()); + return detail::put_v, Ts...>(os, v, v.index()); +} +template +IIStream& operator>> (IIStream& is, cv::util::variant &v) { + int idx = -1; + is >> idx; + GAPI_Assert(idx >= 0 && idx < (int)sizeof...(Ts)); + return detail::get_v, Ts...>(is, v, 0u, idx); +} + +// FIXME: consider a better solution +template +void getRunArgByIdx (IIStream& is, cv::util::variant &v, uint32_t idx) { + is = detail::get_v, Ts...>(is, v, 0u, idx); +} } // namespace s11n namespace detail @@ -204,11 +281,27 @@ static GCompileArg exec(cv::gapi::s11n::IIStream& is, const std::string& tag) { cv::gapi::s11n::detail::S11N::deserialize(is) }; } - return deserialize_arg>::exec(is, tag); } }; +template struct deserialize_runarg; + +template +struct deserialize_runarg { +static GRunArg exec(cv::gapi::s11n::IIStream& is, uint32_t idx) { + if (idx == GRunArg::index_of()) { + auto ptr = std::make_shared(); + ptr->deserialize(is); + return GRunArg { RMat(std::move(ptr)) }; + } else { // non-RMat arg - use default deserialization + GRunArg arg; + getRunArgByIdx(is, arg, idx); + return arg; + } +} +}; + template cv::GCompileArgs getCompileArgs(const std::vector &p) { std::unique_ptr pIs = cv::gapi::s11n::detail::getInStream(p); @@ -225,6 +318,23 @@ cv::GCompileArgs getCompileArgs(const std::vector &p) { return args; } + +template +cv::GRunArgs getRunArgsWithRMats(const std::vector &p) { + std::unique_ptr pIs = cv::gapi::s11n::detail::getInStream(p); + cv::gapi::s11n::IIStream& is = *pIs; + cv::GRunArgs args; + + uint32_t sz = 0; + is >> sz; + for (uint32_t i = 0; i < sz; ++i) { + uint32_t idx = 0; + is >> idx; + args.push_back(cv::gapi::detail::deserialize_runarg::exec(is, idx)); + } + + return args; +} } // namespace detail } // namespace gapi } // namespace cv diff --git a/modules/gapi/src/api/s11n.cpp b/modules/gapi/src/api/s11n.cpp index 52c276fd5d..b6acf28ea4 100644 --- a/modules/gapi/src/api/s11n.cpp +++ b/modules/gapi/src/api/s11n.cpp @@ -79,6 +79,9 @@ cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results) case T::index_of() : outputs.emplace_back(cv::util::get(res_obj)); break; + case cv::GRunArg::index_of() : + outputs.emplace_back((cv::RMat*)(&(cv::util::get(res_obj)))); + break; default: GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode. break; @@ -112,6 +115,9 @@ cv::GRunArg cv::gapi::bind(cv::GRunArgP &out) case T::index_of() : return cv::GRunArg(*cv::util::get(out)); + case T::index_of() : + return cv::GRunArg(*cv::util::get(out)); + default: // ...maybe our types were extended GAPI_Assert(false && "This value type is UNKNOWN!"); diff --git a/modules/gapi/src/backends/common/serialization.cpp b/modules/gapi/src/backends/common/serialization.cpp index ca73d29ffb..2b23b33cc8 100644 --- a/modules/gapi/src/backends/common/serialization.cpp +++ b/modules/gapi/src/backends/common/serialization.cpp @@ -165,12 +165,12 @@ IOStream& operator<< (IOStream& os, const cv::Scalar &s) { IIStream& operator>> (IIStream& is, cv::Scalar& s) { return is >> s.val[0] >> s.val[1] >> s.val[2] >> s.val[3]; } -IOStream& operator<< (IOStream& os, const cv::RMat&) { - util::throw_error(std::logic_error("Serialization of RMat is not supported")); +IOStream& operator<< (IOStream& os, const cv::RMat& mat) { + mat.serialize(os); return os; } IIStream& operator>> (IIStream& is, cv::RMat&) { - util::throw_error(std::logic_error("Serialization of RMat is not supported")); + util::throw_error(std::logic_error("operator>> for RMat should never be called")); return is; } diff --git a/modules/gapi/src/backends/common/serialization.hpp b/modules/gapi/src/backends/common/serialization.hpp index e2aa56c45b..a3134d84d2 100644 --- a/modules/gapi/src/backends/common/serialization.hpp +++ b/modules/gapi/src/backends/common/serialization.hpp @@ -88,26 +88,6 @@ GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::GArrayDesc &); GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::GFrameDesc &); GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::GFrameDesc &); -#if !defined(GAPI_STANDALONE) -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::UMat &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::UMat &); -#endif // !defined(GAPI_STANDALONE) - -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::RMat &r); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::RMat &r); - -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::gapi::wip::IStreamSource::Ptr &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::gapi::wip::IStreamSource::Ptr &); - -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::VectorRef &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::VectorRef &); - -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::OpaqueRef &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::OpaqueRef &); - -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::MediaFrame &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::MediaFrame &); - GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::gimpl::RcDesc &rc); GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::gimpl::RcDesc &rc); @@ -178,46 +158,6 @@ GAPI_EXPORTS void serialize( IOStream& os GAPI_EXPORTS GSerialized deserialize(IIStream& is); GAPI_EXPORTS void reconstruct(const GSerialized &s, ade::Graph &g); -// Generic: variant serialization ////////////////////////////////////////////// -namespace detail { // FIXME: breaks old code -template -IOStream& put_v(IOStream&, const V&, std::size_t) { - GAPI_Assert(false && "variant>>: requested index is invalid"); -}; -template -IOStream& put_v(IOStream& os, const V& v, std::size_t x) { - return (x == 0u) - ? os << cv::util::get(v) - : put_v(os, v, x-1); -} -template -IIStream& get_v(IIStream&, V&, std::size_t, std::size_t) { - GAPI_Assert(false && "variant<<: requested index is invalid"); -} -template -IIStream& get_v(IIStream& is, V& v, std::size_t i, std::size_t gi) { - if (i == gi) { - X x{}; - is >> x; - v = std::move(x); - return is; - } else return get_v(is, v, i+1, gi); -} -} // namespace detail FIXME: breaks old code - -template -IOStream& operator<< (IOStream& os, const cv::util::variant &v) { - os << (uint32_t)v.index(); - return detail::put_v, Ts...>(os, v, v.index()); -} -template -IIStream& operator>> (IIStream& is, cv::util::variant &v) { - int idx = -1; - is >> idx; - GAPI_Assert(idx >= 0 && idx < (int)sizeof...(Ts)); - return detail::get_v, Ts...>(is, v, 0u, idx); -} - // FIXME: Basic Stream implementaions ////////////////////////////////////////// // Basic in-memory stream implementations. diff --git a/modules/gapi/test/s11n/gapi_s11n_tests.cpp b/modules/gapi/test/s11n/gapi_s11n_tests.cpp index 1a4faec12c..3fe632e449 100644 --- a/modules/gapi/test/s11n/gapi_s11n_tests.cpp +++ b/modules/gapi/test/s11n/gapi_s11n_tests.cpp @@ -1,6 +1,7 @@ #include "../test_precomp.hpp" #include "backends/common/serialization.hpp" +#include namespace { struct MyCustomType { @@ -45,6 +46,35 @@ template<> struct CompileArgTag { } // namespace detail } // namespace cv +namespace { +class MyRMatAdapter : public cv::RMat::Adapter { + cv::Mat m_mat; + int m_value; + std::string m_str; +public: + MyRMatAdapter() = default; + MyRMatAdapter(cv::Mat m, int value, const std::string& str) + : m_mat(m), m_value(value), m_str(str) + {} + virtual cv::RMat::View access(cv::RMat::Access access) override { + if (access == cv::RMat::Access::W) { + return cv::RMat::View(cv::descr_of(m_mat), m_mat.data, m_mat.step); + } else { + return cv::RMat::View(cv::descr_of(m_mat), m_mat.data, m_mat.step); + } + } + virtual cv::GMatDesc desc() const override { return cv::descr_of(m_mat); } + virtual void serialize(cv::gapi::s11n::IOStream& os) override { + os << m_value << m_str; + } + virtual void deserialize(cv::gapi::s11n::IIStream& is) override { + is >> m_value >> m_str; + } + int getVal() { return m_value; } + std::string getStr() { return m_str; } +}; +} + namespace opencv_test { struct S11N_Basic: public ::testing::Test { @@ -460,6 +490,39 @@ TEST_F(S11N_Basic, Test_Bind_RunArgs_MatScalar) { } } +TEST_F(S11N_Basic, Test_RunArg_RMat) { + cv::Mat mat = cv::Mat::eye(cv::Size(128, 64), CV_8UC3); + cv::RMat rmat = cv::make_rmat(mat, 42, "It actually works"); + auto v = cv::GRunArgs{ cv::GRunArg{ rmat } }; + + const std::vector sargsin = cv::gapi::serialize(v); + cv::GRunArgs out = cv::gapi::deserialize(sargsin); + cv::RMat out_mat = cv::util::get(out[0]); + auto adapter = out_mat.get(); + EXPECT_EQ(42, adapter->getVal()); + EXPECT_EQ("It actually works", adapter->getStr()); +} + +TEST_F(S11N_Basic, Test_RunArg_RMat_Scalar_Mat) { + cv::Mat mat = cv::Mat::eye(cv::Size(128, 64), CV_8UC3); + cv::RMat rmat = cv::make_rmat(mat, 42, "It actually works"); + cv::Scalar sc(111); + auto v = cv::GRunArgs{ cv::GRunArg{ rmat }, cv::GRunArg{ sc }, cv::GRunArg{ mat } }; + + const std::vector sargsin = cv::gapi::serialize(v); + cv::GRunArgs out = cv::gapi::deserialize(sargsin); + cv::RMat out_rmat = cv::util::get(out[0]); + auto adapter = out_rmat.get(); + EXPECT_EQ(42, adapter->getVal()); + EXPECT_EQ("It actually works", adapter->getStr()); + + cv::Scalar out_sc = cv::util::get(out[1]); + EXPECT_EQ(sc, out_sc); + + cv::Mat out_mat = cv::util::get(out[2]); + EXPECT_EQ(0, cv::norm(mat, out_mat)); +} + namespace { template bool verifyOpaqueKind(T&& in) {