diff --git a/modules/gapi/CMakeLists.txt b/modules/gapi/CMakeLists.txt index 0278d9326a..88ddeead16 100644 --- a/modules/gapi/CMakeLists.txt +++ b/modules/gapi/CMakeLists.txt @@ -49,6 +49,7 @@ file(GLOB gapi_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/ocl/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/own/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/render/*.hpp" + "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/s11n/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/plaidml/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/util/*.hpp" diff --git a/modules/gapi/include/opencv2/gapi/gcommon.hpp b/modules/gapi/include/opencv2/gapi/gcommon.hpp index e008fe4bf1..2b260ed07c 100644 --- a/modules/gapi/include/opencv2/gapi/gcommon.hpp +++ b/modules/gapi/include/opencv2/gapi/gcommon.hpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace cv { @@ -94,6 +95,15 @@ enum class GShape: int GFRAME, }; +namespace gapi { +namespace s11n { +namespace detail { +template struct wrap_serialize; +} // namespace detail +} // namespace s11n +} // namespace gapi + + struct GCompileArg; namespace detail { @@ -139,7 +149,7 @@ namespace detail { * passed in (a variadic template parameter pack) into a vector of * cv::GCompileArg objects. */ -struct GAPI_EXPORTS_W_SIMPLE GCompileArg +struct GCompileArg { public: // NB: Required for pythnon bindings @@ -151,6 +161,7 @@ public: template::value, int>::type = 0> explicit GCompileArg(T &&t) : tag(detail::CompileArgTag::type>::tag()) + , serializeF(&cv::gapi::s11n::detail::wrap_serialize::serialize) , arg(t) { } @@ -165,7 +176,13 @@ public: return util::any_cast(arg); } + void serialize(cv::gapi::s11n::IOStream& os) const + { + serializeF(os, *this); + } + private: + std::function serializeF; util::any arg; }; @@ -198,6 +215,19 @@ inline cv::util::optional getCompileArg(const cv::GCompileArgs &args) } return cv::util::optional(); } + +namespace s11n { +namespace detail { +template struct wrap_serialize +{ + static void serialize(IOStream& os, const GCompileArg& arg) + { + using decayed_type = typename std::decay::type; + S11N::serialize(os, arg.get()); + } +}; +} // namespace detail +} // namespace s11n } // namespace gapi /** diff --git a/modules/gapi/include/opencv2/gapi/s11n.hpp b/modules/gapi/include/opencv2/gapi/s11n.hpp index 0b61304c5c..e8a8dbcab4 100644 --- a/modules/gapi/include/opencv2/gapi/s11n.hpp +++ b/modules/gapi/include/opencv2/gapi/s11n.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace cv { @@ -17,14 +18,13 @@ namespace gapi { 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); + + template + cv::GCompileArgs getCompileArgs(const std::vector &p); } // namespace detail GAPI_EXPORTS std::vector serialize(const cv::GComputation &c); @@ -35,6 +35,7 @@ T deserialize(const std::vector &p); //} //ananymous namespace +GAPI_EXPORTS std::vector serialize(const cv::GCompileArgs&); GAPI_EXPORTS std::vector serialize(const cv::GMetaArgs&); GAPI_EXPORTS std::vector serialize(const cv::GRunArgs&); @@ -53,6 +54,11 @@ cv::GRunArgs deserialize(const std::vector &p) { return detail::getRunArgs(p); } +template inline +typename std::enable_if::value, GCompileArgs>:: +type deserialize(const std::vector &p) { + return detail::getCompileArgs(p); +} } // namespace gapi } // namespace cv @@ -91,6 +97,10 @@ struct GAPI_EXPORTS IIStream { virtual IIStream& operator>> (std::string &) = 0; }; +namespace detail { +GAPI_EXPORTS std::unique_ptr getInStream(const std::vector &p); +} // namespace detail + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // S11N operators @@ -174,17 +184,48 @@ IIStream& operator>> (IIStream& is, std::vector &ts) { } return is; } - -namespace detail { - // Will be used along with default types if possible in specific cases (compile args, etc) - // Note: actual implementation is defined by user - template - struct GAPI_EXPORTS S11N { - static void serialize(IOStream &, const T &) {} - static T deserialize(IIStream &) { T t; return t; } - }; -} // namespace detail } // namespace s11n + +namespace detail +{ +template struct deserialize_arg; + +template<> struct deserialize_arg> { +static GCompileArg exec(cv::gapi::s11n::IIStream&, const std::string&) { + throw std::logic_error("Passed arg can't be deserialized!"); + } +}; + +template +struct deserialize_arg> { +static GCompileArg exec(cv::gapi::s11n::IIStream& is, const std::string& tag) { + if (tag == cv::detail::CompileArgTag::tag()) { + return GCompileArg { + cv::gapi::s11n::detail::S11N::deserialize(is) + }; + } + + return deserialize_arg>::exec(is, tag); +} +}; + +template +cv::GCompileArgs getCompileArgs(const std::vector &p) { + std::unique_ptr pIs = cv::gapi::s11n::detail::getInStream(p); + cv::gapi::s11n::IIStream& is = *pIs; + cv::GCompileArgs args; + + uint32_t sz = 0; + is >> sz; + for (uint32_t i = 0; i < sz; ++i) { + std::string tag; + is >> tag; + args.push_back(cv::gapi::detail::deserialize_arg>::exec(is, tag)); + } + + return args; +} +} // namespace detail } // namespace gapi } // namespace cv diff --git a/modules/gapi/include/opencv2/gapi/s11n/base.hpp b/modules/gapi/include/opencv2/gapi/s11n/base.hpp new file mode 100644 index 0000000000..6bf5d5fb0f --- /dev/null +++ b/modules/gapi/include/opencv2/gapi/s11n/base.hpp @@ -0,0 +1,36 @@ +// This file is part of OpenCV project. +// 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) 2020 Intel Corporation + +#ifndef OPENCV_GAPI_S11N_BASE_HPP +#define OPENCV_GAPI_S11N_BASE_HPP + +#include + +namespace cv { +namespace gapi { +namespace s11n { +struct IOStream; +struct IIStream; + +namespace detail { +// Will be used along with default types if possible in specific cases (compile args, etc) +// Note: actual implementation is defined by user +template +struct S11N { + static void serialize(IOStream &, const T &) { + GAPI_Assert(false && "No serialization routine is provided!"); + } + static T deserialize(IIStream &) { + GAPI_Assert(false && "No deserialization routine is provided!"); + } +}; + +} // namespace detail +} // namespace s11n +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_S11N_BASE_HPP diff --git a/modules/gapi/misc/python/shadow_gapi.hpp b/modules/gapi/misc/python/shadow_gapi.hpp index dab083def7..4f988440e8 100644 --- a/modules/gapi/misc/python/shadow_gapi.hpp +++ b/modules/gapi/misc/python/shadow_gapi.hpp @@ -3,6 +3,8 @@ namespace cv { + struct GAPI_EXPORTS_W_SIMPLE GCompileArg { }; + GAPI_EXPORTS_W GCompileArgs compile_args(gapi::GKernelPackage pkg); class GAPI_EXPORTS_W_SIMPLE GProtoArg { }; diff --git a/modules/gapi/src/api/s11n.cpp b/modules/gapi/src/api/s11n.cpp index 54a0850394..52c276fd5d 100644 --- a/modules/gapi/src/api/s11n.cpp +++ b/modules/gapi/src/api/s11n.cpp @@ -44,6 +44,13 @@ std::vector cv::gapi::serialize(const cv::GRunArgs& ra) return os.data(); } +std::vector cv::gapi::serialize(const cv::GCompileArgs& ca) +{ + cv::gapi::s11n::ByteMemoryOutStream os; + serialize(os, ca); + return os.data(); +} + // FIXME: This function should move from S11N to GRunArg-related entities. // it has nothing to do with the S11N as it is cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results) diff --git a/modules/gapi/src/backends/common/serialization.cpp b/modules/gapi/src/backends/common/serialization.cpp index c0b3281449..ca73d29ffb 100644 --- a/modules/gapi/src/backends/common/serialization.cpp +++ b/modules/gapi/src/backends/common/serialization.cpp @@ -329,6 +329,13 @@ IIStream& operator>> (IIStream& is, cv::gapi::wip::draw::Line &l) { // G-API types ///////////////////////////////////////////////////////////////// +IOStream& operator<< (IOStream& os, const cv::GCompileArg& arg) +{ + os << arg.tag; + arg.serialize(os); + return os; +} + // Stubs (empty types) IOStream& operator<< (IOStream& os, cv::util::monostate ) {return os;} @@ -865,6 +872,14 @@ IIStream& ByteMemoryInStream::operator>> (std::string& str) { return *this; } +GAPI_EXPORTS std::unique_ptr detail::getInStream(const std::vector &p) { + return std::unique_ptr(new ByteMemoryInStream(p)); +} + +GAPI_EXPORTS void serialize(IOStream& os, const cv::GCompileArgs &ca) { + os << ca; +} + GAPI_EXPORTS void serialize(IOStream& os, const cv::GMetaArgs &ma) { os << ma; } @@ -882,7 +897,6 @@ GAPI_EXPORTS GRunArgs run_args_deserialize(IIStream& is) { return s; } - } // namespace s11n } // namespace gapi } // namespace cv diff --git a/modules/gapi/src/backends/common/serialization.hpp b/modules/gapi/src/backends/common/serialization.hpp index 4c60e71d87..e2aa56c45b 100644 --- a/modules/gapi/src/backends/common/serialization.hpp +++ b/modules/gapi/src/backends/common/serialization.hpp @@ -40,6 +40,8 @@ struct GSerialized { // G-API types ///////////////////////////////////////////////////////////////// +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::GCompileArg& arg); + GAPI_EXPORTS IOStream& operator<< (IOStream& os, cv::util::monostate ); GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::util::monostate &); @@ -268,6 +270,11 @@ public: virtual IIStream& operator>> (std::string &) override; }; +namespace detail { +GAPI_EXPORTS std::unique_ptr getInStream(const std::vector &p); +} // namespace detail + +GAPI_EXPORTS void serialize(IOStream& os, const cv::GCompileArgs &ca); GAPI_EXPORTS void serialize(IOStream& os, const cv::GMetaArgs &ma); GAPI_EXPORTS void serialize(IOStream& os, const cv::GRunArgs &ra); GAPI_EXPORTS GMetaArgs meta_args_deserialize(IIStream& is); diff --git a/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp b/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp index 75ca7989e0..fe6a1f94af 100644 --- a/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp +++ b/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp @@ -21,7 +21,7 @@ namespace opencv_test { std::string method; }; -} +} // namespace opencv_test namespace cv { @@ -31,11 +31,11 @@ namespace cv { static const char* tag() { - return "org.opencv.test..background_substractor_state_params"; + return "org.opencv.test.background_substractor_state_params"; } }; - } -} + } // namespace detail +} // namespace cv namespace opencv_test { diff --git a/modules/gapi/test/s11n/gapi_s11n_tests.cpp b/modules/gapi/test/s11n/gapi_s11n_tests.cpp index 10fe586188..1a4faec12c 100644 --- a/modules/gapi/test/s11n/gapi_s11n_tests.cpp +++ b/modules/gapi/test/s11n/gapi_s11n_tests.cpp @@ -34,6 +34,17 @@ namespace detail { } // namespace gapi } // namespace cv + +namespace cv { +namespace detail { +template<> struct CompileArgTag { + static const char* tag() { + return "org.opencv.test.mycustomtype"; + } +}; +} // namespace detail +} // namespace cv + namespace opencv_test { struct S11N_Basic: public ::testing::Test { @@ -511,4 +522,15 @@ TEST_F(S11N_Basic, Test_Custom_Type) { MyCustomType new_var = cv::gapi::s11n::detail::S11N::deserialize(is); EXPECT_EQ(var, new_var); } + +TEST_F(S11N_Basic, Test_Custom_CompileArg) { + MyCustomType customVar{1248, "World", {1280, 720, 640, 480}, {{5, 32434142342}, {7, 34242432}}}; + + std::vector sArgs = cv::gapi::serialize(cv::compile_args(customVar)); + + GCompileArgs dArgs = cv::gapi::deserialize(sArgs); + + MyCustomType dCustomVar = cv::gapi::getCompileArg(dArgs).value(); + EXPECT_EQ(customVar, dCustomVar); +} } // namespace opencv_test