Merge pull request #20298 from mpashchenkov:mp/python-desync
G-API: Python. Desync. * Desync. GMat. * Alignment
This commit is contained in:
committed by
GitHub
parent
050ea9762f
commit
05f1939b02
@@ -131,7 +131,8 @@ PyObject* pyopencv_from(const cv::detail::PyObjectHolder& v)
|
||||
template <>
|
||||
PyObject* pyopencv_from(const cv::gapi::wip::draw::Prim& prim)
|
||||
{
|
||||
switch (prim.index()) {
|
||||
switch (prim.index())
|
||||
{
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Rect>():
|
||||
return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Rect>(prim));
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Text>():
|
||||
@@ -319,40 +320,69 @@ PyObject* pyopencv_from(const GRunArg& v)
|
||||
return pyopencv_from(util::get<cv::detail::OpaqueRef>(v));
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs");
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs. Index of variant is unknown");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PyObject* pyopencv_from(const cv::optional<T>& opt)
|
||||
{
|
||||
if (!opt.has_value())
|
||||
{
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return pyopencv_from(*opt);
|
||||
}
|
||||
|
||||
template <>
|
||||
PyObject* pyopencv_from(const GOptRunArg& v)
|
||||
{
|
||||
switch (v.index())
|
||||
{
|
||||
case GOptRunArg::index_of<cv::optional<cv::Mat>>():
|
||||
return pyopencv_from(util::get<cv::optional<cv::Mat>>(v));
|
||||
|
||||
case GOptRunArg::index_of<cv::optional<cv::Scalar>>():
|
||||
return pyopencv_from(util::get<cv::optional<cv::Scalar>>(v));
|
||||
|
||||
case GOptRunArg::index_of<optional<cv::detail::VectorRef>>():
|
||||
return pyopencv_from(util::get<optional<cv::detail::VectorRef>>(v));
|
||||
|
||||
case GOptRunArg::index_of<optional<cv::detail::OpaqueRef>>():
|
||||
return pyopencv_from(util::get<optional<cv::detail::OpaqueRef>>(v));
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to unpack GOptRunArg. Index of variant is unknown");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const GRunArgs& value)
|
||||
{
|
||||
size_t i, n = value.size();
|
||||
return value.size() == 1 ? pyopencv_from(value[0]) : pyopencv_from_generic_vec(value);
|
||||
}
|
||||
|
||||
// NB: It doesn't make sense to return list with a single element
|
||||
if (n == 1)
|
||||
template<>
|
||||
PyObject* pyopencv_from(const GOptRunArgs& value)
|
||||
{
|
||||
return value.size() == 1 ? pyopencv_from(value[0]) : pyopencv_from_generic_vec(value);
|
||||
}
|
||||
|
||||
// FIXME: cv::variant should be wrapped once for all types.
|
||||
template <>
|
||||
PyObject* pyopencv_from(const cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>& v)
|
||||
{
|
||||
using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
|
||||
switch (v.index())
|
||||
{
|
||||
PyObject* item = pyopencv_from(value[0]);
|
||||
if(!item)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return item;
|
||||
case RunArgs::index_of<cv::GRunArgs>():
|
||||
return pyopencv_from(util::get<cv::GRunArgs>(v));
|
||||
case RunArgs::index_of<cv::GOptRunArgs>():
|
||||
return pyopencv_from(util::get<cv::GOptRunArgs>(v));
|
||||
}
|
||||
|
||||
PyObject* list = PyList_New(n);
|
||||
for(i = 0; i < n; ++i)
|
||||
{
|
||||
PyObject* item = pyopencv_from(value[i]);
|
||||
if(!item)
|
||||
{
|
||||
Py_DECREF(list);
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs");
|
||||
return NULL;
|
||||
}
|
||||
PyList_SetItem(list, i, item);
|
||||
}
|
||||
|
||||
return list;
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to recognize kind of RunArgs. Index of variant is unknown");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -634,7 +664,8 @@ static cv::GRunArgs run_py_kernel(cv::detail::PyObjectHolder kernel,
|
||||
cv::detail::PyObjectHolder result(
|
||||
PyObject_CallObject(kernel.get(), args.get()), false);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_PrintEx(0);
|
||||
PyErr_Clear();
|
||||
throw std::logic_error("Python kernel failed with error!");
|
||||
@@ -717,8 +748,9 @@ static cv::GMetaArgs get_meta_args(PyObject* tuple)
|
||||
}
|
||||
|
||||
static GMetaArgs run_py_meta(cv::detail::PyObjectHolder out_meta,
|
||||
const cv::GMetaArgs &meta,
|
||||
const cv::GArgs &gargs) {
|
||||
const cv::GMetaArgs &meta,
|
||||
const cv::GArgs &gargs)
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
@@ -760,7 +792,8 @@ static GMetaArgs run_py_meta(cv::detail::PyObjectHolder out_meta,
|
||||
cv::detail::PyObjectHolder result(
|
||||
PyObject_CallObject(out_meta.get(), args.get()), false);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_PrintEx(0);
|
||||
PyErr_Clear();
|
||||
throw std::logic_error("Python outMeta failed with error!");
|
||||
@@ -792,21 +825,24 @@ static PyObject* pyopencv_cv_gapi_kernels(PyObject* , PyObject* py_args, PyObjec
|
||||
PyObject* user_kernel = PyTuple_GetItem(py_args, i);
|
||||
|
||||
PyObject* id_obj = PyObject_GetAttrString(user_kernel, "id");
|
||||
if (!id_obj) {
|
||||
if (!id_obj)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Python kernel should contain id, please use cv.gapi.kernel to define kernel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* out_meta = PyObject_GetAttrString(user_kernel, "outMeta");
|
||||
if (!out_meta) {
|
||||
if (!out_meta)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Python kernel should contain outMeta, please use cv.gapi.kernel to define kernel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* run = PyObject_GetAttrString(user_kernel, "run");
|
||||
if (!run) {
|
||||
if (!run)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Python kernel should contain run, please use cv.gapi.kernel to define kernel");
|
||||
return NULL;
|
||||
@@ -951,9 +987,12 @@ struct PyOpenCV_Converter<cv::GArray<T>>
|
||||
if (PyObject_TypeCheck(obj, reinterpret_cast<PyTypeObject*>(pyopencv_GArrayT_TypePtr)))
|
||||
{
|
||||
auto& array = reinterpret_cast<pyopencv_GArrayT_t*>(obj)->v;
|
||||
try {
|
||||
try
|
||||
{
|
||||
value = cv::util::get<cv::GArray<T>>(array.arg());
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -974,9 +1013,12 @@ struct PyOpenCV_Converter<cv::GOpaque<T>>
|
||||
if (PyObject_TypeCheck(obj, reinterpret_cast<PyTypeObject*>(pyopencv_GOpaqueT_TypePtr)))
|
||||
{
|
||||
auto& opaque = reinterpret_cast<pyopencv_GOpaqueT_t*>(obj)->v;
|
||||
try {
|
||||
try
|
||||
{
|
||||
value = cv::util::get<cv::GOpaque<T>>(opaque.arg());
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -3,39 +3,40 @@
|
||||
|
||||
namespace cv
|
||||
{
|
||||
struct GAPI_EXPORTS_W_SIMPLE GCompileArg {
|
||||
GAPI_WRAP GCompileArg(gapi::GKernelPackage pkg);
|
||||
GAPI_WRAP GCompileArg(gapi::GNetPackage pkg);
|
||||
struct GAPI_EXPORTS_W_SIMPLE GCompileArg
|
||||
{
|
||||
GAPI_WRAP GCompileArg(gapi::GKernelPackage pkg);
|
||||
GAPI_WRAP GCompileArg(gapi::GNetPackage pkg);
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferInputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferInputs();
|
||||
GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GMat& value);
|
||||
GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GFrame& value);
|
||||
GAPI_WRAP GInferInputs();
|
||||
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 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);
|
||||
GAPI_WRAP GInferListInputs();
|
||||
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
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferOutputs();
|
||||
GAPI_WRAP cv::GMat at(const std::string& name);
|
||||
GAPI_WRAP GInferOutputs();
|
||||
GAPI_WRAP cv::GMat at(const std::string& name);
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferListOutputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferListOutputs();
|
||||
GAPI_WRAP cv::GArray<cv::GMat> at(const std::string& name);
|
||||
GAPI_WRAP GInferListOutputs();
|
||||
GAPI_WRAP cv::GArray<cv::GMat> at(const std::string& name);
|
||||
};
|
||||
|
||||
namespace gapi
|
||||
@@ -69,11 +70,13 @@ namespace streaming
|
||||
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);
|
||||
|
||||
GAPI_EXPORTS_W cv::GMat desync(const cv::GMat &g);
|
||||
} // namespace streaming
|
||||
} // namespace gapi
|
||||
|
||||
namespace detail
|
||||
{
|
||||
gapi::GNetParam GAPI_EXPORTS_W strip(gapi::ie::PyParams params);
|
||||
gapi::GNetParam GAPI_EXPORTS_W strip(gapi::ie::PyParams params);
|
||||
} // namespace detail
|
||||
} // namespace cv
|
||||
|
||||
@@ -5,16 +5,35 @@ import cv2 as cv
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import time
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
|
||||
try:
|
||||
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
|
||||
@cv.gapi.op('custom.delay', in_types=[cv.GMat], out_types=[cv.GMat])
|
||||
class GDelay:
|
||||
"""Delay for 10 ms."""
|
||||
|
||||
@staticmethod
|
||||
def outMeta(desc):
|
||||
return desc
|
||||
|
||||
|
||||
@cv.gapi.kernel(GDelay)
|
||||
class GDelayImpl:
|
||||
"""Implementation for GDelay operation."""
|
||||
|
||||
@staticmethod
|
||||
def run(img):
|
||||
time.sleep(0.01)
|
||||
return img
|
||||
|
||||
|
||||
class test_gapi_streaming(NewOpenCVTests):
|
||||
|
||||
def test_image_input(self):
|
||||
@@ -148,7 +167,7 @@ try:
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break;
|
||||
break
|
||||
|
||||
|
||||
def test_video_good_features_to_track(self):
|
||||
@@ -242,6 +261,51 @@ try:
|
||||
if curr_frame_number == max_num_frames:
|
||||
break
|
||||
|
||||
def test_desync(self):
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out1 = cv.gapi.copy(g_in)
|
||||
des = cv.gapi.streaming.desync(g_in)
|
||||
g_out2 = GDelay.on(des)
|
||||
|
||||
c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out1, g_out2))
|
||||
|
||||
kernels = cv.gapi.kernels(GDelayImpl)
|
||||
ccomp = c.compileStreaming(args=cv.gapi.compile_args(kernels))
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(cv.gin(source))
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
|
||||
out_counter = 0
|
||||
desync_out_counter = 0
|
||||
none_counter = 0
|
||||
while True:
|
||||
has_frame, (out1, out2) = ccomp.pull()
|
||||
if not has_frame:
|
||||
break
|
||||
|
||||
if not out1 is None:
|
||||
out_counter += 1
|
||||
if not out2 is None:
|
||||
desync_out_counter += 1
|
||||
else:
|
||||
none_counter += 1
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
ccomp.stop()
|
||||
break
|
||||
|
||||
self.assertLess(0, proc_num_frames)
|
||||
self.assertLess(desync_out_counter, out_counter)
|
||||
self.assertLess(0, none_counter)
|
||||
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user