Merge pull request #20271 from TolyaTalamanov:at/extend-python-bindings
authorAnatoliy Talamanov <anatoliy.talamanov@intel.com>
Wed, 30 Jun 2021 09:04:09 +0000 (12:04 +0300)
committerGitHub <noreply@github.com>
Wed, 30 Jun 2021 09:04:09 +0000 (09:04 +0000)
G-API: Extend python bindings

* Extend G-API bindings

* Wrap timestamp, seqNo, seq_id
* Wrap copy
* Wrap parseSSD, parseYolo

* Rewrap cv.gapi.networks

* Add test for metabackend in pytnon

* Remove int64 pyopencv_to

13 files changed:
modules/gapi/include/opencv2/gapi/gcommon.hpp
modules/gapi/include/opencv2/gapi/gstreaming.hpp
modules/gapi/include/opencv2/gapi/infer.hpp
modules/gapi/include/opencv2/gapi/infer/parsers.hpp
modules/gapi/include/opencv2/gapi/streaming/format.hpp
modules/gapi/misc/python/package/gapi/__init__.py
modules/gapi/misc/python/pyopencv_gapi.hpp
modules/gapi/misc/python/python_bridge.hpp
modules/gapi/misc/python/shadow_gapi.hpp
modules/gapi/misc/python/test/test_gapi_streaming.py
modules/gapi/src/api/ginfer.cpp
modules/gapi/src/backends/common/gmetabackend.cpp
modules/python/src2/cv2.cpp

index a9cb0159014e18e27244fb6b0a9e20fd6811d800..d3c280816ff94afc6cde5941d8d655558be36698 100644 (file)
@@ -44,6 +44,7 @@ namespace detail
         CV_UNKNOWN,    // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization
         CV_BOOL,       // bool user G-API data
         CV_INT,        // int user G-API data
+        CV_INT64,      // int64_t 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
@@ -61,6 +62,7 @@ namespace detail
     template<typename T> struct GOpaqueTraits;
     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<int64_t>     { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT64; };
     template<> struct GOpaqueTraits<double>      { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; };
     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; };
index 5bbed5e12dda00777b968f86dc49342e04cb4156..47e103fd0ea7ab325128d094e16f91fb74e10d97 100644 (file)
@@ -196,7 +196,7 @@ public:
      * @param s a shared pointer to IStreamSource representing the
      * input video stream.
      */
-    GAPI_WRAP void setSource(const gapi::wip::IStreamSource::Ptr& s);
+    void setSource(const gapi::wip::IStreamSource::Ptr& s);
 
     /**
      * @brief Constructs and specifies an input video stream for a
index 93701856bbdb92a8cc9378e70336517e31478dd9..807c82d31f8992733defcd22c997402da802e883 100644 (file)
@@ -136,11 +136,12 @@ public:
     }
 
     template <typename U>
-    void setInput(const std::string& name, U in)
+    GInferInputsTyped<Ts...>& setInput(const std::string& name, U in)
     {
         m_priv->blobs.emplace(std::piecewise_construct,
                               std::forward_as_tuple(name),
                               std::forward_as_tuple(in));
+        return *this;
     }
 
     using StorageT = cv::util::variant<Ts...>;
@@ -654,7 +655,7 @@ namespace gapi {
 // A type-erased form of network parameters.
 // Similar to how a type-erased GKernel is represented and used.
 /// @private
-struct GAPI_EXPORTS GNetParam {
+struct GAPI_EXPORTS_W_SIMPLE GNetParam {
     std::string tag;     // FIXME: const?
     GBackend backend;    // Specifies the execution model
     util::any params;    // Backend-interpreted parameter structure
@@ -671,6 +672,7 @@ struct GAPI_EXPORTS GNetParam {
  */
 struct GAPI_EXPORTS_W_SIMPLE GNetPackage {
     GAPI_WRAP GNetPackage() = default;
+    GAPI_WRAP explicit GNetPackage(std::vector<GNetParam> nets);
     explicit GNetPackage(std::initializer_list<GNetParam> ii);
     std::vector<GBackend> backends() const;
     std::vector<GNetParam> networks;
index 22c8701a6c2e1accc2f95d7d3d7f533040cb5f16..c7308dd39f4792ebf781e9caf927882e7cede39f 100644 (file)
@@ -64,10 +64,10 @@ detection is smaller than confidence threshold, detection is rejected.
 given label will get to the output.
 @return a tuple with a vector of detected boxes and a vector of appropriate labels.
 */
-GAPI_EXPORTS std::tuple<GArray<Rect>, GArray<int>> parseSSD(const GMat& in,
-                                                            const GOpaque<Size>& inSz,
-                                                            const float confidenceThreshold = 0.5f,
-                                                            const int   filterLabel = -1);
+GAPI_EXPORTS_W std::tuple<GArray<Rect>, GArray<int>> parseSSD(const GMat& in,
+                                                              const GOpaque<Size>& inSz,
+                                                              const float confidenceThreshold = 0.5f,
+                                                              const int   filterLabel = -1);
 
 /** @brief Parses output of SSD network.
 
@@ -113,12 +113,12 @@ If 1.f, nms is not performed and no boxes are rejected.
 <a href="https://github.com/openvinotoolkit/open_model_zoo/blob/master/models/public/yolo-v2-tiny-tf/yolo-v2-tiny-tf.md">documentation</a>.
 @return a tuple with a vector of detected boxes and a vector of appropriate labels.
 */
-GAPI_EXPORTS std::tuple<GArray<Rect>, GArray<int>> parseYolo(const GMat& in,
-                                                             const GOpaque<Size>& inSz,
-                                                             const float confidenceThreshold = 0.5f,
-                                                             const float nmsThreshold = 0.5f,
-                                                             const std::vector<float>& anchors
-                                                                 = nn::parsers::GParseYolo::defaultAnchors());
+GAPI_EXPORTS_W std::tuple<GArray<Rect>, GArray<int>> parseYolo(const GMat& in,
+                                                               const GOpaque<Size>& inSz,
+                                                               const float confidenceThreshold = 0.5f,
+                                                               const float nmsThreshold = 0.5f,
+                                                               const std::vector<float>& anchors
+                                                                   = nn::parsers::GParseYolo::defaultAnchors());
 
 } // namespace gapi
 } // namespace cv
index c9d2fa3e0a296fb9baa7246c215abeaa985c79ba..f7c3bd457dfbad8e336f23efd85bb56a84640364 100644 (file)
@@ -74,7 +74,7 @@ e.g when graph's input needs to be passed directly to output, like in Streaming
 @param in Input image
 @return Copy of the input
 */
-GAPI_EXPORTS GMat copy(const GMat& in);
+GAPI_EXPORTS_W GMat copy(const GMat& in);
 
 /** @brief Makes a copy of the input frame. Note that this copy may be not real
 (no actual data copied). Use this function to maintain graph contracts,
index 23f5f41846f373a56871006b9415fab5e5306896..587f641fd33a9f5bdcf9f7dcc84859e5d5a82c2f 100644 (file)
@@ -11,11 +11,36 @@ def register(mname):
     return parameterized
 
 
+@register('cv2.gapi')
+def networks(*args):
+    return cv.gapi_GNetPackage(list(map(cv.detail.strip, args)))
+
+
 @register('cv2.gapi')
 def compile_args(*args):
     return list(map(cv.GCompileArg, args))
 
 
+@register('cv2')
+def GIn(*args):
+    return [*args]
+
+
+@register('cv2')
+def GOut(*args):
+    return [*args]
+
+
+@register('cv2')
+def gin(*args):
+    return [*args]
+
+
+@register('cv2.gapi')
+def descr_of(*args):
+    return [*args]
+
+
 @register('cv2')
 class GOpaque():
     # NB: Inheritance from c++ class cause segfault.
index 6b782cfc8dd8a868003536f7a1fb7af4e0b12e7f..6cd79e4a731875e8a407c848136292bce0d1e95b 100644 (file)
@@ -17,6 +17,7 @@ using gapi_ie_PyParams           = cv::gapi::ie::PyParams;
 using gapi_wip_IStreamSource_Ptr = cv::Ptr<cv::gapi::wip::IStreamSource>;
 using detail_ExtractArgsCallback = cv::detail::ExtractArgsCallback;
 using detail_ExtractMetaCallback = cv::detail::ExtractMetaCallback;
+using vector_GNetParam           = std::vector<cv::gapi::GNetParam>;
 
 // NB: Python wrapper generate T_U for T<U>
 // This behavior is only observed for inputs
@@ -138,6 +139,7 @@ PyObject* pyopencv_from(const cv::GArg& value)
     {
         HANDLE_CASE(BOOL,    bool);
         HANDLE_CASE(INT,     int);
+        HANDLE_CASE(INT64,   int64_t);
         HANDLE_CASE(DOUBLE,  double);
         HANDLE_CASE(FLOAT,   float);
         HANDLE_CASE(STRING,  std::string);
@@ -164,23 +166,29 @@ bool pyopencv_to(PyObject* obj, cv::GArg& value, const ArgInfo& info)
 }
 
 template <>
-bool pyopencv_to(PyObject* obj, std::vector<GCompileArg>& value, const ArgInfo& info)
+bool pyopencv_to(PyObject* obj, std::vector<cv::gapi::GNetParam>& value, const ArgInfo& info)
 {
     return pyopencv_to_generic_vec(obj, value, info);
 }
 
 template <>
-PyObject* pyopencv_from(const std::vector<GCompileArg>& value)
+PyObject* pyopencv_from(const std::vector<cv::gapi::GNetParam>& value)
 {
     return pyopencv_from_generic_vec(value);
 }
 
 template <>
-bool pyopencv_to(PyObject* obj, GRunArgs& value, const ArgInfo& info)
+bool pyopencv_to(PyObject* obj, std::vector<GCompileArg>& value, const ArgInfo& info)
 {
     return pyopencv_to_generic_vec(obj, value, info);
 }
 
+template <>
+PyObject* pyopencv_from(const std::vector<GCompileArg>& value)
+{
+    return pyopencv_from_generic_vec(value);
+}
+
 template<>
 PyObject* pyopencv_from(const cv::detail::OpaqueRef& o)
 {
@@ -188,6 +196,7 @@ PyObject* pyopencv_from(const cv::detail::OpaqueRef& o)
     {
         case cv::detail::OpaqueKind::CV_BOOL      : return pyopencv_from(o.rref<bool>());
         case cv::detail::OpaqueKind::CV_INT       : return pyopencv_from(o.rref<int>());
+        case cv::detail::OpaqueKind::CV_INT64     : return pyopencv_from(o.rref<int64_t>());
         case cv::detail::OpaqueKind::CV_DOUBLE    : return pyopencv_from(o.rref<double>());
         case cv::detail::OpaqueKind::CV_FLOAT     : return pyopencv_from(o.rref<float>());
         case cv::detail::OpaqueKind::CV_STRING    : return pyopencv_from(o.rref<std::string>());
@@ -213,6 +222,7 @@ PyObject* pyopencv_from(const cv::detail::VectorRef& v)
     {
         case cv::detail::OpaqueKind::CV_BOOL      : return pyopencv_from_generic_vec(v.rref<bool>());
         case cv::detail::OpaqueKind::CV_INT       : return pyopencv_from_generic_vec(v.rref<int>());
+        case cv::detail::OpaqueKind::CV_INT64     : return pyopencv_from_generic_vec(v.rref<int64_t>());
         case cv::detail::OpaqueKind::CV_DOUBLE    : return pyopencv_from_generic_vec(v.rref<double>());
         case cv::detail::OpaqueKind::CV_FLOAT     : return pyopencv_from_generic_vec(v.rref<float>());
         case cv::detail::OpaqueKind::CV_STRING    : return pyopencv_from_generic_vec(v.rref<std::string>());
@@ -285,18 +295,6 @@ PyObject* pyopencv_from(const GRunArgs& value)
     return list;
 }
 
-template<>
-bool pyopencv_to(PyObject* obj, GMetaArgs& value, const ArgInfo& info)
-{
-    return pyopencv_to_generic_vec(obj, value, info);
-}
-
-template<>
-PyObject* pyopencv_from(const GMetaArgs& value)
-{
-    return pyopencv_from_generic_vec(value);
-}
-
 template <typename T>
 void pyopencv_to_with_check(PyObject* from, T& to, const std::string& msg = "")
 {
@@ -318,16 +316,16 @@ void pyopencv_to_generic_vec_with_check(PyObject* from,
 }
 
 template <typename T>
-static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw)
+static T extract_proto_args(PyObject* py_args)
 {
     using namespace cv;
 
     GProtoArgs args;
-    Py_ssize_t size = PyTuple_Size(py_args);
+    Py_ssize_t size = PyList_Size(py_args);
     args.reserve(size);
     for (int i = 0; i < size; ++i)
     {
-        PyObject* item = PyTuple_GetItem(py_args, i);
+        PyObject* item = PyList_GetItem(py_args, i);
         if (PyObject_TypeCheck(item, reinterpret_cast<PyTypeObject*>(pyopencv_GScalar_TypePtr)))
         {
             args.emplace_back(reinterpret_cast<pyopencv_GScalar_t*>(item)->v);
@@ -346,22 +344,11 @@ static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw)
         }
         else
         {
-            PyErr_SetString(PyExc_TypeError, "Unsupported type for cv.GIn()/cv.GOut()");
-            return NULL;
+            util::throw_error(std::logic_error("Unsupported type for GProtoArgs"));
         }
     }
 
-    return pyopencv_from<T>(T{std::move(args)});
-}
-
-static PyObject* pyopencv_cv_GIn(PyObject* , PyObject* py_args, PyObject* kw)
-{
-    return extract_proto_args<GProtoInputArgs>(py_args, kw);
-}
-
-static PyObject* pyopencv_cv_GOut(PyObject* , PyObject* py_args, PyObject* kw)
-{
-    return extract_proto_args<GProtoOutputArgs>(py_args, kw);
+    return T(std::move(args));
 }
 
 static cv::detail::OpaqueRef extract_opaque_ref(PyObject* from, cv::detail::OpaqueKind kind)
@@ -386,6 +373,7 @@ static cv::detail::OpaqueRef extract_opaque_ref(PyObject* from, cv::detail::Opaq
         HANDLE_CASE(RECT,    cv::Rect);
         HANDLE_CASE(UNKNOWN, cv::GArg);
         UNSUPPORTED(UINT64);
+        UNSUPPORTED(INT64);
         UNSUPPORTED(SCALAR);
         UNSUPPORTED(MAT);
         UNSUPPORTED(DRAW_PRIM);
@@ -419,6 +407,7 @@ static cv::detail::VectorRef extract_vector_ref(PyObject* from, cv::detail::Opaq
         HANDLE_CASE(MAT,     cv::Mat);
         HANDLE_CASE(UNKNOWN, cv::GArg);
         UNSUPPORTED(UINT64);
+        UNSUPPORTED(INT64);
         UNSUPPORTED(DRAW_PRIM);
 #undef HANDLE_CASE
 #undef UNSUPPORTED
@@ -470,13 +459,15 @@ static cv::GRunArg extract_run_arg(const cv::GTypeInfo& info, PyObject* item)
 
 static cv::GRunArgs extract_run_args(const cv::GTypesInfo& info, PyObject* py_args)
 {
+    GAPI_Assert(PyList_Check(py_args));
+
     cv::GRunArgs args;
-    Py_ssize_t tuple_size = PyTuple_Size(py_args);
-    args.reserve(tuple_size);
+    Py_ssize_t list_size = PyList_Size(py_args);
+    args.reserve(list_size);
 
-    for (int i = 0; i < tuple_size; ++i)
+    for (int i = 0; i < list_size; ++i)
     {
-        args.push_back(extract_run_arg(info[i], PyTuple_GetItem(py_args, i)));
+        args.push_back(extract_run_arg(info[i], PyList_GetItem(py_args, i)));
     }
 
     return args;
@@ -517,13 +508,15 @@ static cv::GMetaArg extract_meta_arg(const cv::GTypeInfo& info, PyObject* item)
 
 static cv::GMetaArgs extract_meta_args(const cv::GTypesInfo& info, PyObject* py_args)
 {
+    GAPI_Assert(PyList_Check(py_args));
+
     cv::GMetaArgs metas;
-    Py_ssize_t tuple_size = PyTuple_Size(py_args);
-    metas.reserve(tuple_size);
+    Py_ssize_t list_size = PyList_Size(py_args);
+    metas.reserve(list_size);
 
-    for (int i = 0; i < tuple_size; ++i)
+    for (int i = 0; i < list_size; ++i)
     {
-        metas.push_back(extract_meta_arg(info[i], PyTuple_GetItem(py_args, i)));
+        metas.push_back(extract_meta_arg(info[i], PyList_GetItem(py_args, i)));
     }
 
     return metas;
@@ -589,8 +582,27 @@ static cv::GRunArgs run_py_kernel(cv::detail::PyObjectHolder kernel,
         // NB: In fact it's impossible situation, becase errors were handled above.
         GAPI_Assert(result.get() && "Python kernel returned NULL!");
 
-        outs = out_info.size() == 1 ? cv::GRunArgs{extract_run_arg(out_info[0], result.get())}
-                                    : extract_run_args(out_info, result.get());
+        if (out_info.size() == 1)
+        {
+            outs = cv::GRunArgs{extract_run_arg(out_info[0], result.get())};
+        }
+        else if (out_info.size() > 1)
+        {
+            GAPI_Assert(PyTuple_Check(result.get()));
+
+            Py_ssize_t tuple_size = PyTuple_Size(result.get());
+            outs.reserve(tuple_size);
+
+            for (int i = 0; i < tuple_size; ++i)
+            {
+                outs.push_back(extract_run_arg(out_info[i], PyTuple_GetItem(result.get(), i)));
+            }
+        }
+        else
+        {
+            // Seems to be impossible case.
+            GAPI_Assert(false);
+        }
     }
     catch (...)
     {
@@ -756,23 +768,6 @@ static PyObject* pyopencv_cv_gapi_kernels(PyObject* , PyObject* py_args, PyObjec
     return pyopencv_from(pkg);
 }
 
-static PyObject* pyopencv_cv_gapi_networks(PyObject*, PyObject* py_args, PyObject*)
-{
-    using namespace cv;
-    gapi::GNetPackage pkg;
-    Py_ssize_t size = PyTuple_Size(py_args);
-    for (int i = 0; i < size; ++i)
-    {
-        gapi_ie_PyParams params;
-        PyObject* item = PyTuple_GetItem(py_args, i);
-        if (pyopencv_to(item, params, ArgInfo("PyParams", false)))
-        {
-            pkg += gapi::networks(params);
-        }
-    }
-    return pyopencv_from(pkg);
-}
-
 static PyObject* pyopencv_cv_gapi_op(PyObject* , PyObject* py_args, PyObject*)
 {
     using namespace cv;
@@ -834,53 +829,54 @@ static PyObject* pyopencv_cv_gapi_op(PyObject* , PyObject* py_args, PyObject*)
     return pyopencv_from(cv::gapi::wip::op(id, outMetaWrapper, std::move(args)));
 }
 
-static PyObject* pyopencv_cv_gin(PyObject*, PyObject* py_args, PyObject*)
+template<>
+bool pyopencv_to(PyObject* obj, cv::detail::ExtractArgsCallback& value, const ArgInfo&)
 {
-    cv::detail::PyObjectHolder holder{py_args};
-    auto callback = cv::detail::ExtractArgsCallback{[=](const cv::GTypesInfo& info)
-        {
-            PyGILState_STATE gstate;
-            gstate = PyGILState_Ensure();
+    cv::detail::PyObjectHolder holder{obj};
+    value = cv::detail::ExtractArgsCallback{[=](const cv::GTypesInfo& info)
+    {
+        PyGILState_STATE gstate;
+        gstate = PyGILState_Ensure();
 
-            cv::GRunArgs args;
-            try
-            {
-                args = extract_run_args(info, holder.get());
-            }
-            catch (...)
-            {
-                PyGILState_Release(gstate);
-                throw;
-            }
+        cv::GRunArgs args;
+        try
+        {
+            args = extract_run_args(info, holder.get());
+        }
+        catch (...)
+        {
             PyGILState_Release(gstate);
-            return args;
-        }};
-
-    return pyopencv_from(callback);
+            throw;
+        }
+        PyGILState_Release(gstate);
+        return args;
+    }};
+    return true;
 }
 
-static PyObject* pyopencv_cv_descr_of(PyObject*, PyObject* py_args, PyObject*)
+template<>
+bool pyopencv_to(PyObject* obj, cv::detail::ExtractMetaCallback& value, const ArgInfo&)
 {
-    Py_INCREF(py_args);
-    auto callback = cv::detail::ExtractMetaCallback{[=](const cv::GTypesInfo& info)
-        {
-            PyGILState_STATE gstate;
-            gstate = PyGILState_Ensure();
+    cv::detail::PyObjectHolder holder{obj};
+    value = cv::detail::ExtractMetaCallback{[=](const cv::GTypesInfo& info)
+    {
+        PyGILState_STATE gstate;
+        gstate = PyGILState_Ensure();
 
-            cv::GMetaArgs args;
-            try
-            {
-                args = extract_meta_args(info, py_args);
-            }
-            catch (...)
-            {
-                PyGILState_Release(gstate);
-                throw;
-            }
+        cv::GMetaArgs args;
+        try
+        {
+            args = extract_meta_args(info, holder.get());
+        }
+        catch (...)
+        {
             PyGILState_Release(gstate);
-            return args;
-        }};
-    return pyopencv_from(callback);
+            throw;
+        }
+        PyGILState_Release(gstate);
+        return args;
+    }};
+    return true;
 }
 
 template<typename T>
@@ -929,11 +925,39 @@ struct PyOpenCV_Converter<cv::GOpaque<T>>
     }
 };
 
+template<>
+bool pyopencv_to(PyObject* obj, cv::GProtoInputArgs& value, const ArgInfo& info)
+{
+    try
+    {
+        value = extract_proto_args<cv::GProtoInputArgs>(obj);
+        return true;
+    }
+    catch (...)
+    {
+        failmsg("Can't parse cv::GProtoInputArgs");
+        return false;
+    }
+}
+
+template<>
+bool pyopencv_to(PyObject* obj, cv::GProtoOutputArgs& value, const ArgInfo& info)
+{
+    try
+    {
+        value = extract_proto_args<cv::GProtoOutputArgs>(obj);
+        return true;
+    }
+    catch (...)
+    {
+        failmsg("Can't parse cv::GProtoOutputArgs");
+        return false;
+    }
+}
 
 // extend cv.gapi methods
 #define PYOPENCV_EXTRA_METHODS_GAPI \
   {"kernels", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_kernels), "kernels(...) -> GKernelPackage"}, \
-  {"networks", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_networks), "networks(...) -> GNetPackage"}, \
   {"__op", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_op), "__op(...) -> retval\n"},
 
 
index 0d1c6d51c5748a9ee0a4d6be00f0ce060f6e4d51..b212babe4599df9ade094a47b2d72afb3571a507 100644 (file)
@@ -27,6 +27,7 @@
 #define GARRAY_TYPE_LIST_G(G, G2) \
 WRAP_ARGS(bool        , cv::gapi::ArgType::CV_BOOL,    G)  \
 WRAP_ARGS(int         , cv::gapi::ArgType::CV_INT,     G)  \
+WRAP_ARGS(int64_t     , cv::gapi::ArgType::CV_INT64,   G)  \
 WRAP_ARGS(double      , cv::gapi::ArgType::CV_DOUBLE,  G)  \
 WRAP_ARGS(float       , cv::gapi::ArgType::CV_FLOAT,   G)  \
 WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING,  G)  \
@@ -42,6 +43,7 @@ WRAP_ARGS(cv::GMat    , cv::gapi::ArgType::CV_GMAT,    G2) \
 #define GOPAQUE_TYPE_LIST_G(G, G2) \
 WRAP_ARGS(bool        , cv::gapi::ArgType::CV_BOOL,    G)  \
 WRAP_ARGS(int         , cv::gapi::ArgType::CV_INT,     G)  \
+WRAP_ARGS(int64_t     , cv::gapi::ArgType::CV_INT64,   G)  \
 WRAP_ARGS(double      , cv::gapi::ArgType::CV_DOUBLE,  G)  \
 WRAP_ARGS(float       , cv::gapi::ArgType::CV_FLOAT,   G)  \
 WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING,  G)  \
@@ -58,6 +60,7 @@ namespace gapi {
 enum ArgType {
     CV_BOOL,
     CV_INT,
+    CV_INT64,
     CV_DOUBLE,
     CV_FLOAT,
     CV_STRING,
index 941250c2fb45fe83204a96e0834255930b24b56a..e777aa5d934b5c900462f60bf792b0f6c8252bd0 100644 (file)
@@ -8,31 +8,20 @@ namespace cv
        GAPI_WRAP GCompileArg(gapi::GNetPackage pkg);
    };
 
-   // NB: This classes doesn't exist in *.so
-   // HACK: Mark them as a class to force python wrapper generate code for this entities
-   class GAPI_EXPORTS_W_SIMPLE GProtoArg { };
-   class GAPI_EXPORTS_W_SIMPLE GProtoInputArgs { };
-   class GAPI_EXPORTS_W_SIMPLE GProtoOutputArgs { };
-   class GAPI_EXPORTS_W_SIMPLE GRunArg { };
-   class GAPI_EXPORTS_W_SIMPLE GMetaArg { GAPI_WRAP GMetaArg(); };
-
-   using GProtoInputArgs  = GIOProtoArgs<In_Tag>;
-   using GProtoOutputArgs = GIOProtoArgs<Out_Tag>;
-
    class GAPI_EXPORTS_W_SIMPLE GInferInputs
    {
    public:
        GAPI_WRAP GInferInputs();
-       GAPI_WRAP void setInput(const std::string& name, const cv::GMat&   value);
-       GAPI_WRAP void setInput(const std::string& name, const cv::GFrame& value);
+       GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GMat&   value);
+       GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GFrame& value);
    };
 
    class GAPI_EXPORTS_W_SIMPLE GInferListInputs
    {
    public:
        GAPI_WRAP GInferListInputs();
-       GAPI_WRAP void setInput(const std::string& name, const cv::GArray<cv::GMat>& value);
-       GAPI_WRAP void setInput(const std::string& name, const cv::GArray<cv::Rect>& value);
+       GAPI_WRAP GInferListInputs setInput(const std::string& name, const cv::GArray<cv::GMat>& value);
+       GAPI_WRAP GInferListInputs setInput(const std::string& name, const cv::GArray<cv::Rect>& value);
    };
 
    class GAPI_EXPORTS_W_SIMPLE GInferOutputs
@@ -51,12 +40,18 @@ namespace cv
 
    namespace detail
    {
-       struct GAPI_EXPORTS_W_SIMPLE ExtractArgsCallback { };
-       struct GAPI_EXPORTS_W_SIMPLE ExtractMetaCallback { };
+       gapi::GNetParam GAPI_EXPORTS_W strip(gapi::ie::PyParams params);
    } // namespace detail
 
    namespace gapi
    {
+       namespace streaming
+       {
+           // FIXME: Extend to work with an arbitrary G-type.
+           cv::GOpaque<int64_t> GAPI_EXPORTS_W timestamp(cv::GMat);
+           cv::GOpaque<int64_t> GAPI_EXPORTS_W seqNo(cv::GMat);
+           cv::GOpaque<int64_t> GAPI_EXPORTS_W seq_id(cv::GMat);
+       } // namespace streaming
        namespace wip
        {
            class GAPI_EXPORTS_W IStreamSource { };
index f1cce4fb72fc453229fe55a340b908109b96d5e8..4ea88878eeabd6d5ee2663399aebcc5b493b66cd 100644 (file)
@@ -28,7 +28,7 @@ try:
             g_in = cv.GMat()
             g_out = cv.gapi.medianBlur(g_in, 3)
             c = cv.GComputation(g_in, g_out)
-            ccomp = c.compileStreaming(cv.descr_of(in_mat))
+            ccomp = c.compileStreaming(cv.gapi.descr_of(in_mat))
             ccomp.setSource(cv.gin(in_mat))
             ccomp.start()
 
@@ -52,7 +52,7 @@ try:
 
             ccomp = c.compileStreaming()
             source = cv.gapi.wip.make_capture_src(path)
-            ccomp.setSource(source)
+            ccomp.setSource(cv.gin(source))
             ccomp.start()
 
             # Assert
@@ -87,7 +87,7 @@ try:
 
             ccomp = c.compileStreaming()
             source = cv.gapi.wip.make_capture_src(path)
-            ccomp.setSource(source)
+            ccomp.setSource(cv.gin(source))
             ccomp.start()
 
             # Assert
@@ -176,7 +176,7 @@ try:
 
             ccomp = c.compileStreaming()
             source = cv.gapi.wip.make_capture_src(path)
-            ccomp.setSource(source)
+            ccomp.setSource(cv.gin(source))
             ccomp.start()
 
             # Assert
@@ -209,6 +209,40 @@ try:
                     break
 
 
+        def test_gapi_streaming_meta(self):
+            ksize = 3
+            path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
+
+            # G-API
+            g_in = cv.GMat()
+            g_ts = cv.gapi.streaming.timestamp(g_in)
+            g_seqno = cv.gapi.streaming.seqNo(g_in)
+            g_seqid = cv.gapi.streaming.seq_id(g_in)
+
+            c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_ts, g_seqno, g_seqid))
+
+            ccomp = c.compileStreaming()
+            source = cv.gapi.wip.make_capture_src(path)
+            ccomp.setSource(cv.gin(source))
+            ccomp.start()
+
+            # Assert
+            max_num_frames  = 10
+            curr_frame_number = 0
+            while True:
+                has_frame, (ts, seqno, seqid) = ccomp.pull()
+
+                if not has_frame:
+                    break
+
+                self.assertEqual(curr_frame_number, seqno)
+                self.assertEqual(curr_frame_number, seqid)
+
+                curr_frame_number += 1
+                if curr_frame_number == max_num_frames:
+                    break
+
+
 except unittest.SkipTest as e:
 
     message = str(e)
index e3cc94041c32d3a93fd19959cb66af90dc10b5bd..9db05a43c36954d35bc2062f2c17345f9ffbbcbc 100644 (file)
@@ -15,6 +15,10 @@ cv::gapi::GNetPackage::GNetPackage(std::initializer_list<GNetParam> ii)
     : networks(ii) {
 }
 
+cv::gapi::GNetPackage::GNetPackage(std::vector<GNetParam> nets)
+    : networks(nets) {
+}
+
 std::vector<cv::gapi::GBackend> cv::gapi::GNetPackage::backends() const {
     std::unordered_set<cv::gapi::GBackend> unique_set;
     for (const auto &nn : networks) unique_set.insert(nn.backend);
index c535569b0cef814987cc11eac3844a5530e54e9e..40e87c3ea0aa1fd0d163cddd61028221d36b2ce4 100644 (file)
@@ -85,6 +85,19 @@ class GGraphMetaBackendImpl final: public cv::gapi::GBackend::Priv {
                          const std::vector<cv::gimpl::Data>&) const override {
         return EPtr{new GraphMetaExecutable(graph, nodes)};
     }
+
+    virtual bool controlsMerge() const override
+    {
+        return true;
+    }
+
+    virtual bool allowsMerge(const cv::gimpl::GIslandModel::Graph &,
+                             const ade::NodeHandle &,
+                             const ade::NodeHandle &,
+                             const ade::NodeHandle &) const override
+    {
+        return false;
+    }
 };
 
 cv::gapi::GBackend graph_meta_backend() {
index 9e8a6ee13bd97e5649ae0bc43f2382c97609b3c5..795afb13f276a3aaa48acb652f8f424e60b22a01 100644 (file)
@@ -2219,12 +2219,6 @@ static PyMethodDef special_methods[] = {
 #ifdef HAVE_OPENCV_DNN
   {"dnn_registerLayer", CV_PY_FN_WITH_KW(pyopencv_cv_dnn_registerLayer), "registerLayer(type, class) -> None"},
   {"dnn_unregisterLayer", CV_PY_FN_WITH_KW(pyopencv_cv_dnn_unregisterLayer), "unregisterLayer(type) -> None"},
-#endif
-#ifdef HAVE_OPENCV_GAPI
-  {"GIn", CV_PY_FN_WITH_KW(pyopencv_cv_GIn), "GIn(...) -> GInputProtoArgs"},
-  {"GOut", CV_PY_FN_WITH_KW(pyopencv_cv_GOut), "GOut(...) -> GOutputProtoArgs"},
-  {"gin", CV_PY_FN_WITH_KW(pyopencv_cv_gin), "gin(...) -> ExtractArgsCallback"},
-  {"descr_of", CV_PY_FN_WITH_KW(pyopencv_cv_descr_of), "descr_of(...) -> ExtractMetaCallback"},
 #endif
   {NULL, NULL},
 };