Merge pull request #18401 from smirnov-alexey:as/serialization_more_types
authorAlexey Smirnov <alexey.smirnov@intel.com>
Mon, 28 Sep 2020 18:20:04 +0000 (21:20 +0300)
committerGitHub <noreply@github.com>
Mon, 28 Sep 2020 18:20:04 +0000 (18:20 +0000)
[G-API] Add support for more types serialization

* Support more types

* Add std::string support

* Fix GOpaque and gin interaction

* Fix tests on kind

* Make map serialization support templates and add tests on kind

modules/gapi/include/opencv2/gapi/gcommon.hpp
modules/gapi/include/opencv2/gapi/gopaque.hpp
modules/gapi/src/backends/common/serialization.cpp
modules/gapi/src/backends/common/serialization.hpp
modules/gapi/test/gapi_array_tests.cpp
modules/gapi/test/gapi_opaque_tests.cpp
modules/gapi/test/s11n/gapi_s11n_tests.cpp
modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp

index dc2c8b9..e008fe4 100644 (file)
@@ -44,12 +44,15 @@ namespace detail
         CV_BOOL,       // bool user G-API data
         CV_INT,        // int user G-API data
         CV_DOUBLE,     // double user G-API data
+        CV_FLOAT,      // float user G-API data
+        CV_UINT64,     // uint64_t user G-API data
+        CV_STRING,     // std::string user G-API data
         CV_POINT,      // cv::Point user G-API data
         CV_SIZE,       // cv::Size user G-API data
         CV_RECT,       // cv::Rect user G-API data
         CV_SCALAR,     // cv::Scalar user G-API data
         CV_MAT,        // cv::Mat user G-API data
-        CV_PRIM,       // cv::gapi::wip::draw::Prim user G-API data
+        CV_DRAW_PRIM,  // cv::gapi::wip::draw::Prim user G-API data
     };
 
     // Type traits helper which simplifies the extraction of kind from type
@@ -57,19 +60,23 @@ namespace detail
     template<typename T> struct GOpaqueTraits    { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; };
     template<> struct GOpaqueTraits<int>         { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; };
     template<> struct GOpaqueTraits<double>      { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; };
-    template<> struct GOpaqueTraits<cv::Size>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; };
+    template<> struct GOpaqueTraits<float>       { static constexpr const OpaqueKind kind = OpaqueKind::CV_FLOAT; };
+    template<> struct GOpaqueTraits<uint64_t>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_UINT64; };
     template<> struct GOpaqueTraits<bool>        { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; };
+    template<> struct GOpaqueTraits<std::string> { static constexpr const OpaqueKind kind = OpaqueKind::CV_STRING; };
+    template<> struct GOpaqueTraits<cv::Size>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; };
     template<> struct GOpaqueTraits<cv::Scalar>  { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; };
     template<> struct GOpaqueTraits<cv::Point>   { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; };
     template<> struct GOpaqueTraits<cv::Mat>     { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
     template<> struct GOpaqueTraits<cv::Rect>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; };
     template<> struct GOpaqueTraits<cv::GMat>    { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
     template<> struct GOpaqueTraits<cv::gapi::wip::draw::Prim>
-                                                 { static constexpr const OpaqueKind kind = OpaqueKind::CV_PRIM; };
-    // GArray is not supporting bool type for now due to difference in std::vector<bool> implementation
-    using GOpaqueTraitsArrayTypes = std::tuple<int, double, cv::Size, cv::Scalar, cv::Point, cv::Mat, cv::Rect, cv::gapi::wip::draw::Prim>;
+                                                 { static constexpr const OpaqueKind kind = OpaqueKind::CV_DRAW_PRIM; };
+    using GOpaqueTraitsArrayTypes = std::tuple<int, double, float, uint64_t, bool, std::string, cv::Size, cv::Scalar, cv::Point,
+                                               cv::Mat, cv::Rect, cv::gapi::wip::draw::Prim>;
     // GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types
-    using GOpaqueTraitsOpaqueTypes = std::tuple<bool, int, double, cv::Size, cv::Point, cv::Rect, cv::gapi::wip::draw::Prim>;
+    using GOpaqueTraitsOpaqueTypes = std::tuple<int, double, float, uint64_t, bool, std::string, cv::Size, cv::Point, cv::Rect,
+                                                cv::gapi::wip::draw::Prim>;
 } // namespace detail
 
 // This definition is here because it is reused by both public(?) and internal
index 1c45d46..3d13944 100644 (file)
@@ -240,7 +240,7 @@ namespace detail
         // FIXME: probably won't work with const object
         explicit OpaqueRef(T&& obj) :
             m_ref(new OpaqueRefT<util::decay_t<T>>(std::forward<T>(obj))),
-            m_kind(GOpaqueTraits<T>::kind) {}
+            m_kind(GOpaqueTraits<util::decay_t<T>>::kind) {}
 
         cv::detail::OpaqueKind getKind() const
         {
index ab7626d..76618d6 100644 (file)
@@ -478,14 +478,17 @@ I::OStream& operator<< (I::OStream& os, const cv::GArg &arg) {
         GAPI_Assert(arg.kind == cv::detail::ArgKind::OPAQUE_VAL);
         GAPI_Assert(arg.opaque_kind != cv::detail::OpaqueKind::CV_UNKNOWN);
         switch (arg.opaque_kind) {
-        case cv::detail::OpaqueKind::CV_BOOL:   os << arg.get<bool>();       break;
-        case cv::detail::OpaqueKind::CV_INT:    os << arg.get<int>();        break;
-        case cv::detail::OpaqueKind::CV_DOUBLE: os << arg.get<double>();     break;
-        case cv::detail::OpaqueKind::CV_POINT:  os << arg.get<cv::Point>();  break;
-        case cv::detail::OpaqueKind::CV_SIZE:   os << arg.get<cv::Size>();   break;
-        case cv::detail::OpaqueKind::CV_RECT:   os << arg.get<cv::Rect>();   break;
-        case cv::detail::OpaqueKind::CV_SCALAR: os << arg.get<cv::Scalar>(); break;
-        case cv::detail::OpaqueKind::CV_MAT:    os << arg.get<cv::Mat>();    break;
+        case cv::detail::OpaqueKind::CV_BOOL:   os << arg.get<bool>();         break;
+        case cv::detail::OpaqueKind::CV_INT:    os << arg.get<int>();          break;
+        case cv::detail::OpaqueKind::CV_UINT64: os << arg.get<uint64_t>();     break;
+        case cv::detail::OpaqueKind::CV_DOUBLE: os << arg.get<double>();       break;
+        case cv::detail::OpaqueKind::CV_FLOAT:  os << arg.get<float>();        break;
+        case cv::detail::OpaqueKind::CV_STRING: os << arg.get<std::string>();  break;
+        case cv::detail::OpaqueKind::CV_POINT:  os << arg.get<cv::Point>();    break;
+        case cv::detail::OpaqueKind::CV_SIZE:   os << arg.get<cv::Size>();     break;
+        case cv::detail::OpaqueKind::CV_RECT:   os << arg.get<cv::Rect>();     break;
+        case cv::detail::OpaqueKind::CV_SCALAR: os << arg.get<cv::Scalar>();   break;
+        case cv::detail::OpaqueKind::CV_MAT:    os << arg.get<cv::Mat>();      break;
         default: GAPI_Assert(false && "GArg: Unsupported (unknown?) opaque value type");
         }
     }
@@ -511,7 +514,10 @@ I::IStream& operator>> (I::IStream& is, cv::GArg &arg) {
             { T t{}; is >> t; arg = (cv::GArg(t)); } break
             HANDLE_CASE(BOOL   , bool);
             HANDLE_CASE(INT    , int);
+            HANDLE_CASE(UINT64 , uint64_t);
             HANDLE_CASE(DOUBLE , double);
+            HANDLE_CASE(FLOAT  , float);
+            HANDLE_CASE(STRING , std::string);
             HANDLE_CASE(POINT  , cv::Point);
             HANDLE_CASE(SIZE   , cv::Size);
             HANDLE_CASE(RECT   , cv::Rect);
@@ -686,6 +692,12 @@ I::OStream& ByteMemoryOutStream::operator<< (uint32_t atom) {
     m_storage.push_back(0xFF & (atom >> 24));
     return *this;
 }
+I::OStream& ByteMemoryOutStream::operator<< (uint64_t atom) {
+    for (int i = 0; i < 8; ++i) {
+        m_storage.push_back(0xFF & (atom >> (i * 8)));;
+    }
+    return *this;
+}
 I::OStream& ByteMemoryOutStream::operator<< (bool atom) {
     m_storage.push_back(atom ? 1 : 0);
     return *this;
@@ -734,7 +746,6 @@ I::OStream& ByteMemoryOutStream::operator<< (const std::string &str) {
     for (auto c : str) *this << c;
     return *this;
 }
-
 ByteMemoryInStream::ByteMemoryInStream(const std::vector<char> &data)
     : m_storage(data) {
 }
@@ -753,11 +764,26 @@ I::IStream& ByteMemoryInStream::operator>> (bool& atom) {
     atom = (m_storage[m_idx++] == 0) ? false : true;
     return *this;
 }
+I::IStream& ByteMemoryInStream::operator>> (std::vector<bool>::reference atom) {
+    check(sizeof(char));
+    atom = (m_storage[m_idx++] == 0) ? false : true;
+    return *this;
+}
 I::IStream& ByteMemoryInStream::operator>> (char &atom) {
     check(sizeof(char));
     atom = m_storage[m_idx++];
     return *this;
 }
+I::IStream& ByteMemoryInStream::operator>> (uint64_t &atom) {
+    check(sizeof(uint64_t));
+    uint8_t x[8];
+    atom = 0;
+    for (int i = 0; i < 8; ++i) {
+        x[i] = static_cast<uint8_t>(m_storage[m_idx++]);
+        atom |= (static_cast<uint64_t>(x[i]) << (i * 8));
+    }
+    return *this;
+}
 I::IStream& ByteMemoryInStream::operator>> (unsigned char &atom) {
     char c{};
     *this >> c;
index 9286bc4..7a2952a 100644 (file)
@@ -9,7 +9,8 @@
 
 #include <iostream>
 #include <fstream>
-#include <string.h>
+#include <string>
+#include <map>
 
 #include <ade/util/iota_range.hpp> // used in the vector<</>>
 
@@ -46,6 +47,7 @@ namespace I {
         virtual OStream& operator<< (int) = 0;
         //virtual OStream& operator<< (std::size_t) = 0;
         virtual OStream& operator<< (uint32_t) = 0;
+        virtual OStream& operator<< (uint64_t) = 0;
         virtual OStream& operator<< (float) = 0;
         virtual OStream& operator<< (double) = 0;
         virtual OStream& operator<< (const std::string&) = 0;
@@ -55,6 +57,7 @@ namespace I {
         virtual ~IStream() = default;
 
         virtual IStream& operator>> (bool &) = 0;
+        virtual IStream& operator>> (std::vector<bool>::reference) = 0;
         virtual IStream& operator>> (char &) = 0;
         virtual IStream& operator>> (unsigned char &) = 0;
         virtual IStream& operator>> (short &) = 0;
@@ -64,6 +67,7 @@ namespace I {
         virtual IStream& operator>> (double &) = 0;
         //virtual IStream& operator>> (std::size_t &) = 0;
         virtual IStream& operator >> (uint32_t &) = 0;
+        virtual IStream& operator >> (uint64_t &) = 0;
         virtual IStream& operator>> (std::string &) = 0;
     };
 } // namespace I
@@ -217,6 +221,28 @@ GAPI_EXPORTS void serialize( I::OStream& os
 GAPI_EXPORTS GSerialized deserialize(I::IStream& is);
 GAPI_EXPORTS void reconstruct(const GSerialized &s, ade::Graph &g);
 
+// Generic: map serialization ////////////////////////////////////////
+template<typename K, typename V>
+I::OStream& operator<< (I::OStream& os, const std::map<K, V> &m) {
+    const uint32_t sz = static_cast<uint32_t>(m.size()); // explicitly specify type
+    os << sz;
+    for (const auto& it : m) os << it.first << it.second;
+    return os;
+}
+template<typename K, typename V>
+I::IStream& operator>> (I::IStream& is, std::map<K, V> &m) {
+    m.clear();
+    uint32_t sz = 0u;
+    is >> sz;
+    for (std::size_t i = 0; i < sz; ++i) {
+        K k{};
+        V v{};
+        is >> k >> v;
+        m[k] = v;
+    }
+    return is;
+}
+
 // Legacy //////////////////////////////////////////////////////////////////////
 // Generic: unordered_map serialization ////////////////////////////////////////
 template<typename K, typename V>
@@ -334,6 +360,7 @@ public:
     virtual I::OStream& operator<< (double) override;
     virtual I::OStream& operator<< (const std::string&) override;
     virtual I::OStream& operator<< (uint32_t) override;
+    virtual I::OStream& operator<< (uint64_t) override;
 };
 
 class GAPI_EXPORTS ByteMemoryInStream final: public I::IStream {
@@ -349,6 +376,7 @@ public:
     explicit ByteMemoryInStream(const std::vector<char> &data);
 
     virtual I::IStream& operator>> (bool &) override;
+    virtual I::IStream& operator>> (std::vector<bool>::reference) override;
     virtual I::IStream& operator>> (char &) override;
     virtual I::IStream& operator>> (unsigned char &) override;
     virtual I::IStream& operator>> (short &) override;
@@ -358,6 +386,7 @@ public:
     virtual I::IStream& operator>> (double &) override;
     //virtual I::IStream& operator>> (std::size_t &) override;
     virtual I::IStream& operator >> (uint32_t &) override;
+    virtual I::IStream& operator >> (uint64_t &) override;
     virtual I::IStream& operator>> (std::string &) override;
 };
 
index 2faf538..de8b4f2 100644 (file)
@@ -240,6 +240,14 @@ TEST(GArray_VectorRef, TestMov)
     EXPECT_EQ(V{}, vtest);
 }
 
+namespace {
+    struct MyTestStruct {
+        int i;
+        float f;
+        std::string name;
+    };
+}
+
 TEST(GArray_VectorRef, Kind)
 {
     cv::detail::VectorRef v1(std::vector<cv::Rect>{});
@@ -264,7 +272,10 @@ TEST(GArray_VectorRef, Kind)
     EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind());
 
     cv::detail::VectorRef v8(std::vector<std::string>{});
-    EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind());
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_STRING, v8.getKind());
+
+    cv::detail::VectorRef v9(std::vector<MyTestStruct>{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v9.getKind());
 }
 
 TEST(GArray_VectorRef, TestRvalue)
index c76c97a..9bbb431 100644 (file)
@@ -215,6 +215,14 @@ TEST(GOpaque_OpaqueRef, TestMov)
     EXPECT_NE(test, mov.rref<I>());         // ref lost the data
 }
 
+namespace {
+    struct MyTestStruct {
+        int i;
+        float f;
+        std::string name;
+    };
+}
+
 TEST(GOpaque_OpaqueRef, Kind)
 {
     cv::detail::OpaqueRef v1(cv::Rect{});
@@ -233,7 +241,10 @@ TEST(GOpaque_OpaqueRef, Kind)
     EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind());
 
     cv::detail::OpaqueRef v8(std::string{});
-    EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind());
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_STRING, v8.getKind());
+
+    cv::detail::OpaqueRef v9(MyTestStruct{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v9.getKind());
 }
 
 TEST(GOpaque_OpaqueRef, TestReset)
index 5b5be99..5042a34 100644 (file)
@@ -62,10 +62,78 @@ TEST_F(S11N_Basic, Test_fp64) {
     EXPECT_EQ(x, get<double>());
 }
 
+TEST_F(S11N_Basic, Test_uint64) {
+    uint64_t x = 2147483647374;
+    put(x);
+    EXPECT_EQ(x, get<uint64_t>());
+}
+
+TEST_F(S11N_Basic, Test_int32_pos) {
+    int32_t x = 2147483647;
+    put(x);
+    EXPECT_EQ(x, get<int32_t>());
+}
+
+TEST_F(S11N_Basic, Test_int32_neg) {
+    int32_t x = -2147483646;
+    put(x);
+    EXPECT_EQ(x, get<int32_t>());
+}
+
+TEST_F(S11N_Basic, Test_vector_bool) {
+    std::vector<bool> v = {false, true, false};
+    put(v);
+    EXPECT_EQ(v, get<std::vector<bool>>());
+}
+
+TEST_F(S11N_Basic, Test_map_string2string) {
+    using T = std::map<std::string, std::string>;
+    T v;
+    v["gapi"] = "cool";
+    v["42"] = "answer";
+    v["hi"] = "hello there";
+    put(v);
+    EXPECT_EQ(v, get<T>());
+}
+
+TEST_F(S11N_Basic, Test_map_int2int) {
+    using T = std::map<int, int32_t>;
+    T v;
+    v[1] = 23;
+    v[-100] = 0;
+    v[435346] = -12346;
+    put(v);
+    EXPECT_EQ(v, get<T>());
+}
+
+TEST_F(S11N_Basic, Test_map_float2cvsize) {
+    using T = std::map<float, cv::Size>;
+    T v;
+    v[0.4f] = cv::Size(4, 5);
+    v[234.43f] = cv::Size(3421, 321);
+    v[2223.f] = cv::Size(1920, 1080);
+    put(v);
+    EXPECT_EQ(v, get<T>());
+}
+
+TEST_F(S11N_Basic, Test_map_uint642cvmat) {
+    using T = std::map<uint64_t, cv::Mat>;
+    T v;
+    v[21304805324] = cv::Mat(3, 3, CV_8UC1, cv::Scalar::all(3));
+    v[4353245222] = cv::Mat(5, 5, CV_8UC3, cv::Scalar::all(7));
+    v[0] = cv::Mat(10, 10, CV_32FC2, cv::Scalar::all(-128.f));
+    put(v);
+    auto out_v = get<T>();
+    for (const auto& el : out_v) {
+        EXPECT_NE(v.end(), v.find(el.first));
+        EXPECT_EQ(0, cv::norm(el.second, v[el.first]));
+    }
+}
+
 TEST_F(S11N_Basic, Test_vector_int) {
     std::vector<int> v = {1,2,3};
     put(v);
-    EXPECT_EQ(v, get<std::vector<int> >());
+    EXPECT_EQ(v, get<std::vector<int>>());
 }
 
 TEST_F(S11N_Basic, Test_vector_cvSize) {
@@ -74,7 +142,7 @@ TEST_F(S11N_Basic, Test_vector_cvSize) {
         cv::Size(1280, 1024),
     };
     put(v);
-    EXPECT_EQ(v, get<std::vector<cv::Size> >());
+    EXPECT_EQ(v, get<std::vector<cv::Size>>());
 }
 
 TEST_F(S11N_Basic, Test_vector_string) {
@@ -84,13 +152,13 @@ TEST_F(S11N_Basic, Test_vector_string) {
         "ok!"
     };
     put(v);
-    EXPECT_EQ(v, get<std::vector<std::string> >());
+    EXPECT_EQ(v, get<std::vector<std::string>>());
 }
 
 TEST_F(S11N_Basic, Test_vector_empty) {
     std::vector<char> v;
     put(v);
-    EXPECT_EQ(v, get<std::vector<char> >());
+    EXPECT_EQ(v, get<std::vector<char>>());
 }
 
 TEST_F(S11N_Basic, Test_variant) {
@@ -348,4 +416,58 @@ TEST_F(S11N_Basic, Test_Bind_RunArgs_MatScalar) {
         i++;
     }
 }
+
+namespace {
+    template <cv::detail::OpaqueKind K, typename T>
+    bool verifyOpaqueKind(T&& in) {
+        auto inObjs = cv::gin(in);
+        auto in_o_ref = cv::util::get<cv::detail::OpaqueRef>(inObjs[0]);
+        return K == in_o_ref.getKind();
+    }
+
+    template <cv::detail::OpaqueKind K, typename T>
+    bool verifyArrayKind(T&& in) {
+        auto inObjs = cv::gin(in);
+        auto in_o_ref = cv::util::get<cv::detail::VectorRef>(inObjs[0]);
+        return K == in_o_ref.getKind();
+    }
+}
+
+TEST_F(S11N_Basic, Test_Gin_GOpaque) {
+    int i; float f; double d;
+    std::uint64_t ui; bool b;
+    std::string s;
+    cv::Rect r; cv::Size sz;
+    cv::Point p;
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_INT>(i));
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_FLOAT>(f));
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_DOUBLE>(d));
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_UINT64>(ui));
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_BOOL>(b));
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_STRING>(s));
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_RECT>(r));
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_SIZE>(sz));
+    EXPECT_TRUE(verifyOpaqueKind<cv::detail::OpaqueKind::CV_POINT>(p));
+}
+
+TEST_F(S11N_Basic, Test_Gin_GArray) {
+    std::vector<int> i; std::vector<float> f; std::vector<double> d;
+    std::vector<std::uint64_t> ui; std::vector<bool> b;
+    std::vector<std::string> s;
+    std::vector<cv::Rect> r; std::vector<cv::Size> sz;
+    std::vector<cv::Point> p;
+    std::vector<cv::Mat> mat;
+    std::vector<cv::Scalar> sc;
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_INT>(i));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_FLOAT>(f));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_DOUBLE>(d));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_UINT64>(ui));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_BOOL>(b));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_STRING>(s));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_RECT>(r));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_SIZE>(sz));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_POINT>(p));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_MAT>(mat));
+    EXPECT_TRUE(verifyArrayKind<cv::detail::OpaqueKind::CV_SCALAR>(sc));
+}
 } // namespace opencv_test
index 1d8f751..885457c 100644 (file)
@@ -391,6 +391,52 @@ namespace ThisTest
                 vp[idx] = cv::Point(vi[idx], vi[idx]);
         }
     };
+
+    using GK3Out = std::tuple<cv::GArray<uint64_t>, cv::GArray<int32_t>>;
+    G_TYPED_KERNEL_M(OpArrK3, <GK3Out(cv::GArray<bool>, cv::GArray<int32_t>, cv::GOpaque<float>)>, "test.s11n.oparrk3")
+    {
+        static std::tuple<GArrayDesc, GArrayDesc> outMeta(const GArrayDesc&, const GArrayDesc&, const GOpaqueDesc&) {
+            return std::make_tuple(empty_array_desc(), empty_array_desc());
+        }
+    };
+
+    GAPI_OCV_KERNEL(OCVOpArrK3, OpArrK3)
+    {
+        static void run(const std::vector<bool>& vb, const std::vector<int32_t>& vi_in, const float& f,
+                        std::vector<uint64_t>& vui, std::vector<int32_t>& vi)
+        {
+            vui.clear(); vui.resize(vi_in.size());
+            vi.clear();  vi.resize(vi_in.size());
+
+            for (std::size_t idx = 0; idx < vi_in.size(); ++ idx)
+            {
+                vi[idx] = vb[idx] ? vi_in[idx] : -vi_in[idx];
+                vui[idx] = vb[idx] ? static_cast<uint64_t>(vi_in[idx] * f) :
+                                     static_cast<uint64_t>(vi_in[idx] / f);
+            }
+        }
+    };
+
+    using GK4Out = std::tuple<cv::GOpaque<int>, cv::GArray<std::string>>;
+    G_TYPED_KERNEL_M(OpArrK4, <GK4Out(cv::GOpaque<bool>, cv::GOpaque<std::string>)>, "test.s11n.oparrk4")
+    {
+        static std::tuple<GOpaqueDesc, GArrayDesc> outMeta(const GOpaqueDesc&, const GOpaqueDesc&) {
+            return std::make_tuple(empty_gopaque_desc(), empty_array_desc());
+        }
+    };
+
+    GAPI_OCV_KERNEL(OCVOpArrK4, OpArrK4)
+    {
+        static void run(const bool& b, const std::string& s,
+                        int& i, std::vector<std::string>& vs)
+        {
+            vs.clear();
+            vs.resize(2);
+            i = b ? 42 : 24;
+            auto s_copy = s + " world";
+            vs = std::vector<std::string>{s_copy, s_copy};
+        }
+    };
 } // namespace ThisTest
 
 TEST(S11N, Pipeline_GOpaque)
@@ -485,6 +531,59 @@ TEST(S11N, Pipeline_GArray_GOpaque_Multinode)
     }
 }
 
+TEST(S11N, Pipeline_GArray_GOpaque_2)
+{
+    using namespace ThisTest;
+
+    cv::GArray<bool> in1;
+    cv::GArray<int32_t> in2;
+    cv::GOpaque<float> in3;
+    auto out = OpArrK3::on(in1, in2, in3);
+    cv::GComputation c(cv::GIn(in1, in2, in3),
+                       cv::GOut(std::get<0>(out), std::get<1>(out)));
+
+    auto p = cv::gapi::serialize(c);
+    auto dc = cv::gapi::deserialize<cv::GComputation>(p);
+
+    std::vector<bool> b {true, false, false};
+    std::vector<int32_t> i {234324, -234252, 999};
+    float f = 0.85f;
+    std::vector<int32_t> out_i;
+    std::vector<uint64_t> out_ui;
+    dc.apply(cv::gin(b, i, f), cv::gout(out_ui, out_i), cv::compile_args(cv::gapi::kernels<OCVOpArrK3>()));
+
+    for (std::size_t idx = 0; idx < b.size(); ++idx)
+    {
+        EXPECT_EQ(out_i[idx], b[idx] ? i[idx] : -i[idx]);
+        EXPECT_EQ(out_ui[idx], b[idx] ? static_cast<uint64_t>(i[idx] * f) :
+                                        static_cast<uint64_t>(i[idx] / f));
+    }
+}
+
+TEST(S11N, Pipeline_GArray_GOpaque_3)
+{
+    using namespace ThisTest;
+
+    cv::GOpaque<bool> in1;
+    cv::GOpaque<std::string> in2;
+    auto out = OpArrK4::on(in1, in2);
+    cv::GComputation c(cv::GIn(in1, in2),
+                       cv::GOut(std::get<0>(out), std::get<1>(out)));
+
+    auto p = cv::gapi::serialize(c);
+    auto dc = cv::gapi::deserialize<cv::GComputation>(p);
+
+    bool b = false;
+    std::string s("hello");
+    int i = 0;
+    std::vector<std::string> vs{};
+    dc.apply(cv::gin(b, s), cv::gout(i, vs), cv::compile_args(cv::gapi::kernels<OCVOpArrK4>()));
+
+    EXPECT_EQ(24, i);
+    std::vector<std::string> vs_ref{"hello world", "hello world"};
+    EXPECT_EQ(vs_ref, vs);
+}
+
 TEST(S11N, Pipeline_Render_NV12)
 {
     cv::Size sz (100, 200);