Merge pull request #20271 from TolyaTalamanov:at/extend-python-bindings

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
This commit is contained in:
Anatoliy Talamanov 2021-06-30 12:04:09 +03:00 committed by GitHub
parent ee39081b11
commit fb7ef76e74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 240 additions and 144 deletions

View File

@ -44,6 +44,7 @@ namespace detail
CV_UNKNOWN, // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization CV_UNKNOWN, // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization
CV_BOOL, // bool user G-API data CV_BOOL, // bool user G-API data
CV_INT, // int 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_DOUBLE, // double user G-API data
CV_FLOAT, // float user G-API data CV_FLOAT, // float user G-API data
CV_UINT64, // uint64_t 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;
template<typename T> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; }; 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<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<double> { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; };
template<> struct GOpaqueTraits<float> { static constexpr const OpaqueKind kind = OpaqueKind::CV_FLOAT; }; 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<uint64_t> { static constexpr const OpaqueKind kind = OpaqueKind::CV_UINT64; };

View File

@ -196,7 +196,7 @@ public:
* @param s a shared pointer to IStreamSource representing the * @param s a shared pointer to IStreamSource representing the
* input video stream. * 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 * @brief Constructs and specifies an input video stream for a

View File

@ -136,11 +136,12 @@ public:
} }
template <typename U> 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, m_priv->blobs.emplace(std::piecewise_construct,
std::forward_as_tuple(name), std::forward_as_tuple(name),
std::forward_as_tuple(in)); std::forward_as_tuple(in));
return *this;
} }
using StorageT = cv::util::variant<Ts...>; using StorageT = cv::util::variant<Ts...>;
@ -654,7 +655,7 @@ namespace gapi {
// A type-erased form of network parameters. // A type-erased form of network parameters.
// Similar to how a type-erased GKernel is represented and used. // Similar to how a type-erased GKernel is represented and used.
/// @private /// @private
struct GAPI_EXPORTS GNetParam { struct GAPI_EXPORTS_W_SIMPLE GNetParam {
std::string tag; // FIXME: const? std::string tag; // FIXME: const?
GBackend backend; // Specifies the execution model GBackend backend; // Specifies the execution model
util::any params; // Backend-interpreted parameter structure util::any params; // Backend-interpreted parameter structure
@ -671,6 +672,7 @@ struct GAPI_EXPORTS GNetParam {
*/ */
struct GAPI_EXPORTS_W_SIMPLE GNetPackage { struct GAPI_EXPORTS_W_SIMPLE GNetPackage {
GAPI_WRAP GNetPackage() = default; GAPI_WRAP GNetPackage() = default;
GAPI_WRAP explicit GNetPackage(std::vector<GNetParam> nets);
explicit GNetPackage(std::initializer_list<GNetParam> ii); explicit GNetPackage(std::initializer_list<GNetParam> ii);
std::vector<GBackend> backends() const; std::vector<GBackend> backends() const;
std::vector<GNetParam> networks; std::vector<GNetParam> networks;

View File

@ -64,10 +64,10 @@ detection is smaller than confidence threshold, detection is rejected.
given label will get to the output. given label will get to the output.
@return a tuple with a vector of detected boxes and a vector of appropriate labels. @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, GAPI_EXPORTS_W std::tuple<GArray<Rect>, GArray<int>> parseSSD(const GMat& in,
const GOpaque<Size>& inSz, const GOpaque<Size>& inSz,
const float confidenceThreshold = 0.5f, const float confidenceThreshold = 0.5f,
const int filterLabel = -1); const int filterLabel = -1);
/** @brief Parses output of SSD network. /** @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>. <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. @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, GAPI_EXPORTS_W std::tuple<GArray<Rect>, GArray<int>> parseYolo(const GMat& in,
const GOpaque<Size>& inSz, const GOpaque<Size>& inSz,
const float confidenceThreshold = 0.5f, const float confidenceThreshold = 0.5f,
const float nmsThreshold = 0.5f, const float nmsThreshold = 0.5f,
const std::vector<float>& anchors const std::vector<float>& anchors
= nn::parsers::GParseYolo::defaultAnchors()); = nn::parsers::GParseYolo::defaultAnchors());
} // namespace gapi } // namespace gapi
} // namespace cv } // namespace cv

View 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 @param in Input image
@return Copy of the input @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 /** @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, (no actual data copied). Use this function to maintain graph contracts,

View File

@ -11,11 +11,36 @@ def register(mname):
return parameterized return parameterized
@register('cv2.gapi')
def networks(*args):
return cv.gapi_GNetPackage(list(map(cv.detail.strip, args)))
@register('cv2.gapi') @register('cv2.gapi')
def compile_args(*args): def compile_args(*args):
return list(map(cv.GCompileArg, 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') @register('cv2')
class GOpaque(): class GOpaque():
# NB: Inheritance from c++ class cause segfault. # NB: Inheritance from c++ class cause segfault.

View 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 gapi_wip_IStreamSource_Ptr = cv::Ptr<cv::gapi::wip::IStreamSource>;
using detail_ExtractArgsCallback = cv::detail::ExtractArgsCallback; using detail_ExtractArgsCallback = cv::detail::ExtractArgsCallback;
using detail_ExtractMetaCallback = cv::detail::ExtractMetaCallback; using detail_ExtractMetaCallback = cv::detail::ExtractMetaCallback;
using vector_GNetParam = std::vector<cv::gapi::GNetParam>;
// NB: Python wrapper generate T_U for T<U> // NB: Python wrapper generate T_U for T<U>
// This behavior is only observed for inputs // This behavior is only observed for inputs
@ -138,6 +139,7 @@ PyObject* pyopencv_from(const cv::GArg& value)
{ {
HANDLE_CASE(BOOL, bool); HANDLE_CASE(BOOL, bool);
HANDLE_CASE(INT, int); HANDLE_CASE(INT, int);
HANDLE_CASE(INT64, int64_t);
HANDLE_CASE(DOUBLE, double); HANDLE_CASE(DOUBLE, double);
HANDLE_CASE(FLOAT, float); HANDLE_CASE(FLOAT, float);
HANDLE_CASE(STRING, std::string); HANDLE_CASE(STRING, std::string);
@ -163,6 +165,18 @@ bool pyopencv_to(PyObject* obj, cv::GArg& value, const ArgInfo& info)
return true; return true;
} }
template <>
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<cv::gapi::GNetParam>& value)
{
return pyopencv_from_generic_vec(value);
}
template <> template <>
bool pyopencv_to(PyObject* obj, std::vector<GCompileArg>& value, const ArgInfo& info) bool pyopencv_to(PyObject* obj, std::vector<GCompileArg>& value, const ArgInfo& info)
{ {
@ -175,12 +189,6 @@ PyObject* pyopencv_from(const std::vector<GCompileArg>& value)
return pyopencv_from_generic_vec(value); return pyopencv_from_generic_vec(value);
} }
template <>
bool pyopencv_to(PyObject* obj, GRunArgs& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
template<> template<>
PyObject* pyopencv_from(const cv::detail::OpaqueRef& o) 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_BOOL : return pyopencv_from(o.rref<bool>());
case cv::detail::OpaqueKind::CV_INT : return pyopencv_from(o.rref<int>()); 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_DOUBLE : return pyopencv_from(o.rref<double>());
case cv::detail::OpaqueKind::CV_FLOAT : return pyopencv_from(o.rref<float>()); 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>()); 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_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_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_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_FLOAT : return pyopencv_from_generic_vec(v.rref<float>());
case cv::detail::OpaqueKind::CV_STRING : return pyopencv_from_generic_vec(v.rref<std::string>()); 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; 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> template <typename T>
void pyopencv_to_with_check(PyObject* from, T& to, const std::string& msg = "") 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> template <typename T>
static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw) static T extract_proto_args(PyObject* py_args)
{ {
using namespace cv; using namespace cv;
GProtoArgs args; GProtoArgs args;
Py_ssize_t size = PyTuple_Size(py_args); Py_ssize_t size = PyList_Size(py_args);
args.reserve(size); args.reserve(size);
for (int i = 0; i < size; ++i) 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))) if (PyObject_TypeCheck(item, reinterpret_cast<PyTypeObject*>(pyopencv_GScalar_TypePtr)))
{ {
args.emplace_back(reinterpret_cast<pyopencv_GScalar_t*>(item)->v); 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 else
{ {
PyErr_SetString(PyExc_TypeError, "Unsupported type for cv.GIn()/cv.GOut()"); util::throw_error(std::logic_error("Unsupported type for GProtoArgs"));
return NULL;
} }
} }
return pyopencv_from<T>(T{std::move(args)}); return 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);
} }
static cv::detail::OpaqueRef extract_opaque_ref(PyObject* from, cv::detail::OpaqueKind kind) 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(RECT, cv::Rect);
HANDLE_CASE(UNKNOWN, cv::GArg); HANDLE_CASE(UNKNOWN, cv::GArg);
UNSUPPORTED(UINT64); UNSUPPORTED(UINT64);
UNSUPPORTED(INT64);
UNSUPPORTED(SCALAR); UNSUPPORTED(SCALAR);
UNSUPPORTED(MAT); UNSUPPORTED(MAT);
UNSUPPORTED(DRAW_PRIM); 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(MAT, cv::Mat);
HANDLE_CASE(UNKNOWN, cv::GArg); HANDLE_CASE(UNKNOWN, cv::GArg);
UNSUPPORTED(UINT64); UNSUPPORTED(UINT64);
UNSUPPORTED(INT64);
UNSUPPORTED(DRAW_PRIM); UNSUPPORTED(DRAW_PRIM);
#undef HANDLE_CASE #undef HANDLE_CASE
#undef UNSUPPORTED #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) static cv::GRunArgs extract_run_args(const cv::GTypesInfo& info, PyObject* py_args)
{ {
cv::GRunArgs args; GAPI_Assert(PyList_Check(py_args));
Py_ssize_t tuple_size = PyTuple_Size(py_args);
args.reserve(tuple_size);
for (int i = 0; i < tuple_size; ++i) cv::GRunArgs args;
Py_ssize_t list_size = PyList_Size(py_args);
args.reserve(list_size);
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; 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) static cv::GMetaArgs extract_meta_args(const cv::GTypesInfo& info, PyObject* py_args)
{ {
cv::GMetaArgs metas; GAPI_Assert(PyList_Check(py_args));
Py_ssize_t tuple_size = PyTuple_Size(py_args);
metas.reserve(tuple_size);
for (int i = 0; i < tuple_size; ++i) cv::GMetaArgs metas;
Py_ssize_t list_size = PyList_Size(py_args);
metas.reserve(list_size);
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; 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. // NB: In fact it's impossible situation, becase errors were handled above.
GAPI_Assert(result.get() && "Python kernel returned NULL!"); GAPI_Assert(result.get() && "Python kernel returned NULL!");
outs = out_info.size() == 1 ? cv::GRunArgs{extract_run_arg(out_info[0], result.get())} if (out_info.size() == 1)
: extract_run_args(out_info, result.get()); {
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 (...) catch (...)
{ {
@ -756,23 +768,6 @@ static PyObject* pyopencv_cv_gapi_kernels(PyObject* , PyObject* py_args, PyObjec
return pyopencv_from(pkg); 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*) static PyObject* pyopencv_cv_gapi_op(PyObject* , PyObject* py_args, PyObject*)
{ {
using namespace cv; 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))); 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}; cv::detail::PyObjectHolder holder{obj};
auto callback = cv::detail::ExtractArgsCallback{[=](const cv::GTypesInfo& info) 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_STATE gstate;
gstate = PyGILState_Ensure();
cv::GRunArgs args;
try
{
args = extract_run_args(info, holder.get());
}
catch (...)
{
PyGILState_Release(gstate);
throw;
}
PyGILState_Release(gstate); PyGILState_Release(gstate);
return args; throw;
}}; }
PyGILState_Release(gstate);
return pyopencv_from(callback); 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); cv::detail::PyObjectHolder holder{obj};
auto callback = cv::detail::ExtractMetaCallback{[=](const cv::GTypesInfo& info) value = cv::detail::ExtractMetaCallback{[=](const cv::GTypesInfo& info)
{ {
PyGILState_STATE gstate; PyGILState_STATE gstate;
gstate = PyGILState_Ensure(); gstate = PyGILState_Ensure();
cv::GMetaArgs args; cv::GMetaArgs args;
try try
{ {
args = extract_meta_args(info, py_args); args = extract_meta_args(info, holder.get());
} }
catch (...) catch (...)
{ {
PyGILState_Release(gstate);
throw;
}
PyGILState_Release(gstate); PyGILState_Release(gstate);
return args; throw;
}}; }
return pyopencv_from(callback); PyGILState_Release(gstate);
return args;
}};
return true;
} }
template<typename T> 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 // extend cv.gapi methods
#define PYOPENCV_EXTRA_METHODS_GAPI \ #define PYOPENCV_EXTRA_METHODS_GAPI \
{"kernels", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_kernels), "kernels(...) -> GKernelPackage"}, \ {"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"}, {"__op", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_op), "__op(...) -> retval\n"},

View File

@ -27,6 +27,7 @@
#define GARRAY_TYPE_LIST_G(G, G2) \ #define GARRAY_TYPE_LIST_G(G, G2) \
WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \ WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \
WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, 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(double , cv::gapi::ArgType::CV_DOUBLE, G) \
WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \ WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \
WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, 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) \ #define GOPAQUE_TYPE_LIST_G(G, G2) \
WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \ WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \
WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, 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(double , cv::gapi::ArgType::CV_DOUBLE, G) \
WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \ WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \
WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \ WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \
@ -58,6 +60,7 @@ namespace gapi {
enum ArgType { enum ArgType {
CV_BOOL, CV_BOOL,
CV_INT, CV_INT,
CV_INT64,
CV_DOUBLE, CV_DOUBLE,
CV_FLOAT, CV_FLOAT,
CV_STRING, CV_STRING,

View File

@ -8,31 +8,20 @@ namespace cv
GAPI_WRAP GCompileArg(gapi::GNetPackage pkg); 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 class GAPI_EXPORTS_W_SIMPLE GInferInputs
{ {
public: public:
GAPI_WRAP GInferInputs(); GAPI_WRAP GInferInputs();
GAPI_WRAP void setInput(const std::string& name, const cv::GMat& value); GAPI_WRAP GInferInputs& 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::GFrame& value);
}; };
class GAPI_EXPORTS_W_SIMPLE GInferListInputs class GAPI_EXPORTS_W_SIMPLE GInferListInputs
{ {
public: public:
GAPI_WRAP GInferListInputs(); GAPI_WRAP GInferListInputs();
GAPI_WRAP void setInput(const std::string& name, const cv::GArray<cv::GMat>& value); GAPI_WRAP GInferListInputs 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::Rect>& value);
}; };
class GAPI_EXPORTS_W_SIMPLE GInferOutputs class GAPI_EXPORTS_W_SIMPLE GInferOutputs
@ -51,12 +40,18 @@ namespace cv
namespace detail namespace detail
{ {
struct GAPI_EXPORTS_W_SIMPLE ExtractArgsCallback { }; gapi::GNetParam GAPI_EXPORTS_W strip(gapi::ie::PyParams params);
struct GAPI_EXPORTS_W_SIMPLE ExtractMetaCallback { };
} // namespace detail } // namespace detail
namespace gapi 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 namespace wip
{ {
class GAPI_EXPORTS_W IStreamSource { }; class GAPI_EXPORTS_W IStreamSource { };

View File

@ -28,7 +28,7 @@ try:
g_in = cv.GMat() g_in = cv.GMat()
g_out = cv.gapi.medianBlur(g_in, 3) g_out = cv.gapi.medianBlur(g_in, 3)
c = cv.GComputation(g_in, g_out) 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.setSource(cv.gin(in_mat))
ccomp.start() ccomp.start()
@ -52,7 +52,7 @@ try:
ccomp = c.compileStreaming() ccomp = c.compileStreaming()
source = cv.gapi.wip.make_capture_src(path) source = cv.gapi.wip.make_capture_src(path)
ccomp.setSource(source) ccomp.setSource(cv.gin(source))
ccomp.start() ccomp.start()
# Assert # Assert
@ -87,7 +87,7 @@ try:
ccomp = c.compileStreaming() ccomp = c.compileStreaming()
source = cv.gapi.wip.make_capture_src(path) source = cv.gapi.wip.make_capture_src(path)
ccomp.setSource(source) ccomp.setSource(cv.gin(source))
ccomp.start() ccomp.start()
# Assert # Assert
@ -176,7 +176,7 @@ try:
ccomp = c.compileStreaming() ccomp = c.compileStreaming()
source = cv.gapi.wip.make_capture_src(path) source = cv.gapi.wip.make_capture_src(path)
ccomp.setSource(source) ccomp.setSource(cv.gin(source))
ccomp.start() ccomp.start()
# Assert # Assert
@ -209,6 +209,40 @@ try:
break 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: except unittest.SkipTest as e:
message = str(e) message = str(e)

View File

@ -15,6 +15,10 @@ cv::gapi::GNetPackage::GNetPackage(std::initializer_list<GNetParam> ii)
: networks(ii) { : networks(ii) {
} }
cv::gapi::GNetPackage::GNetPackage(std::vector<GNetParam> nets)
: networks(nets) {
}
std::vector<cv::gapi::GBackend> cv::gapi::GNetPackage::backends() const { std::vector<cv::gapi::GBackend> cv::gapi::GNetPackage::backends() const {
std::unordered_set<cv::gapi::GBackend> unique_set; std::unordered_set<cv::gapi::GBackend> unique_set;
for (const auto &nn : networks) unique_set.insert(nn.backend); for (const auto &nn : networks) unique_set.insert(nn.backend);

View File

@ -85,6 +85,19 @@ class GGraphMetaBackendImpl final: public cv::gapi::GBackend::Priv {
const std::vector<cv::gimpl::Data>&) const override { const std::vector<cv::gimpl::Data>&) const override {
return EPtr{new GraphMetaExecutable(graph, nodes)}; 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() { cv::gapi::GBackend graph_meta_backend() {

View File

@ -2219,12 +2219,6 @@ static PyMethodDef special_methods[] = {
#ifdef HAVE_OPENCV_DNN #ifdef HAVE_OPENCV_DNN
{"dnn_registerLayer", CV_PY_FN_WITH_KW(pyopencv_cv_dnn_registerLayer), "registerLayer(type, class) -> None"}, {"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"}, {"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 #endif
{NULL, NULL}, {NULL, NULL},
}; };