From 5ad6ff239bed8d9bfbd4e176a49ea1213989d5a6 Mon Sep 17 00:00:00 2001 From: Anatoliy Talamanov Date: Tue, 24 Aug 2021 12:37:50 +0300 Subject: [PATCH] Merge pull request #20555 from TolyaTalamanov:at/fix-compileStreaming-bug [G-API] Extend compileStreaming to support different overloads * Make different overloads * Order python compileStreaming overloads * Fix compileStreaming bug * Replace gin -> descr_of * Set error message * Fix review comments * Use macros for pyopencv_to GMetaArgs * Use GAPI_PROP_RW * Not split Prims python stuff --- .../include/opencv2/gapi/gcomputation.hpp | 10 +-- .../gapi/include/opencv2/gapi/gstreaming.hpp | 4 +- .../gapi/misc/python/package/gapi/__init__.py | 2 + modules/gapi/misc/python/pyopencv_gapi.hpp | 70 +++++++++++-------- modules/gapi/misc/python/shadow_gapi.hpp | 5 +- .../misc/python/test/test_gapi_streaming.py | 44 ++++++++++++ 6 files changed, 98 insertions(+), 37 deletions(-) diff --git a/modules/gapi/include/opencv2/gapi/gcomputation.hpp b/modules/gapi/include/opencv2/gapi/gcomputation.hpp index a3566fb495..7e07a587e1 100644 --- a/modules/gapi/include/opencv2/gapi/gcomputation.hpp +++ b/modules/gapi/include/opencv2/gapi/gcomputation.hpp @@ -437,11 +437,7 @@ public: * * @sa @ref gapi_compile_args */ - GStreamingCompiled compileStreaming(GMetaArgs &&in_metas, GCompileArgs &&args = {}); - - /// @private -- Exclude this function from OpenCV documentation - GAPI_WRAP GStreamingCompiled compileStreaming(const cv::detail::ExtractMetaCallback &callback, - GCompileArgs &&args = {}); + GAPI_WRAP GStreamingCompiled compileStreaming(GMetaArgs &&in_metas, GCompileArgs &&args = {}); /** * @brief Compile the computation for streaming mode. @@ -464,6 +460,10 @@ public: */ GAPI_WRAP GStreamingCompiled compileStreaming(GCompileArgs &&args = {}); + /// @private -- Exclude this function from OpenCV documentation + GAPI_WRAP GStreamingCompiled compileStreaming(const cv::detail::ExtractMetaCallback &callback, + GCompileArgs &&args = {}); + // 2. Direct metadata version /** * @overload diff --git a/modules/gapi/include/opencv2/gapi/gstreaming.hpp b/modules/gapi/include/opencv2/gapi/gstreaming.hpp index 50abe69f87..0e7d2a847f 100644 --- a/modules/gapi/include/opencv2/gapi/gstreaming.hpp +++ b/modules/gapi/include/opencv2/gapi/gstreaming.hpp @@ -396,9 +396,11 @@ namespace streaming { * In the streaming mode the pipeline steps are connected with queues * and this compile argument controls every queue's size. */ -struct GAPI_EXPORTS queue_capacity +struct GAPI_EXPORTS_W_SIMPLE queue_capacity { + GAPI_WRAP explicit queue_capacity(size_t cap = 1) : capacity(cap) { }; + GAPI_PROP_RW size_t capacity; }; /** @} */ diff --git a/modules/gapi/misc/python/package/gapi/__init__.py b/modules/gapi/misc/python/package/gapi/__init__.py index dc874f0b0c..b1326712fc 100644 --- a/modules/gapi/misc/python/package/gapi/__init__.py +++ b/modules/gapi/misc/python/package/gapi/__init__.py @@ -295,3 +295,5 @@ cv.gapi.wip.draw.Line = cv.gapi_wip_draw_Line cv.gapi.wip.draw.Mosaic = cv.gapi_wip_draw_Mosaic cv.gapi.wip.draw.Image = cv.gapi_wip_draw_Image cv.gapi.wip.draw.Poly = cv.gapi_wip_draw_Poly + +cv.gapi.streaming.queue_capacity = cv.gapi_streaming_queue_capacity diff --git a/modules/gapi/misc/python/pyopencv_gapi.hpp b/modules/gapi/misc/python/pyopencv_gapi.hpp index d378a91b5f..64f8277740 100644 --- a/modules/gapi/misc/python/pyopencv_gapi.hpp +++ b/modules/gapi/misc/python/pyopencv_gapi.hpp @@ -11,13 +11,14 @@ #include // NB: Python wrapper replaces :: with _ for classes -using gapi_GKernelPackage = cv::gapi::GKernelPackage; -using gapi_GNetPackage = cv::gapi::GNetPackage; -using gapi_ie_PyParams = cv::gapi::ie::PyParams; -using gapi_wip_IStreamSource_Ptr = cv::Ptr; -using detail_ExtractArgsCallback = cv::detail::ExtractArgsCallback; -using detail_ExtractMetaCallback = cv::detail::ExtractMetaCallback; -using vector_GNetParam = std::vector; +using gapi_GKernelPackage = cv::gapi::GKernelPackage; +using gapi_GNetPackage = cv::gapi::GNetPackage; +using gapi_ie_PyParams = cv::gapi::ie::PyParams; +using gapi_wip_IStreamSource_Ptr = cv::Ptr; +using detail_ExtractArgsCallback = cv::detail::ExtractArgsCallback; +using detail_ExtractMetaCallback = cv::detail::ExtractMetaCallback; +using vector_GNetParam = std::vector; +using gapi_streaming_queue_capacity = cv::gapi::streaming::queue_capacity; // NB: Python wrapper generate T_U for T // This behavior is only observed for inputs @@ -159,7 +160,7 @@ PyObject* pyopencv_from(const cv::gapi::wip::draw::Prims& value) } template<> -bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prim& value, const ArgInfo& info) +bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prim& value, const ArgInfo&) { #define TRY_EXTRACT(Prim) \ if (PyObject_TypeCheck(obj, reinterpret_cast(pyopencv_gapi_wip_draw_##Prim##_TypePtr))) \ @@ -175,6 +176,7 @@ bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prim& value, const ArgInfo& TRY_EXTRACT(Mosaic) TRY_EXTRACT(Image) TRY_EXTRACT(Poly) +#undef TRY_EXTRACT failmsg("Unsupported primitive type"); return false; @@ -186,6 +188,34 @@ bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prims& value, const ArgInfo return pyopencv_to_generic_vec(obj, value, info); } +template <> +bool pyopencv_to(PyObject* obj, cv::GMetaArg& value, const ArgInfo&) +{ +#define TRY_EXTRACT(Meta) \ + if (PyObject_TypeCheck(obj, \ + reinterpret_cast(pyopencv_##Meta##_TypePtr))) \ + { \ + value = reinterpret_cast(obj)->v; \ + return true; \ + } \ + + TRY_EXTRACT(GMatDesc) + TRY_EXTRACT(GScalarDesc) + TRY_EXTRACT(GArrayDesc) + TRY_EXTRACT(GOpaqueDesc) +#undef TRY_EXTRACT + + failmsg("Unsupported cv::GMetaArg type"); + return false; +} + +template <> +bool pyopencv_to(PyObject* obj, cv::GMetaArgs& value, const ArgInfo& info) +{ + return pyopencv_to_generic_vec(obj, value, info); +} + + template<> PyObject* pyopencv_from(const cv::GArg& value) { @@ -707,30 +737,12 @@ static cv::GRunArgs run_py_kernel(cv::detail::PyObjectHolder kernel, static GMetaArg get_meta_arg(PyObject* obj) { - if (PyObject_TypeCheck(obj, - reinterpret_cast(pyopencv_GMatDesc_TypePtr))) - { - return cv::GMetaArg{reinterpret_cast(obj)->v}; - } - else if (PyObject_TypeCheck(obj, - reinterpret_cast(pyopencv_GScalarDesc_TypePtr))) - { - return cv::GMetaArg{reinterpret_cast(obj)->v}; - } - else if (PyObject_TypeCheck(obj, - reinterpret_cast(pyopencv_GArrayDesc_TypePtr))) - { - return cv::GMetaArg{reinterpret_cast(obj)->v}; - } - else if (PyObject_TypeCheck(obj, - reinterpret_cast(pyopencv_GOpaqueDesc_TypePtr))) - { - return cv::GMetaArg{reinterpret_cast(obj)->v}; - } - else + cv::GMetaArg arg; + if (!pyopencv_to(obj, arg, ArgInfo("arg", false))) { util::throw_error(std::logic_error("Unsupported output meta type")); } + return arg; } static cv::GMetaArgs get_meta_args(PyObject* tuple) diff --git a/modules/gapi/misc/python/shadow_gapi.hpp b/modules/gapi/misc/python/shadow_gapi.hpp index 0b489dde0f..33a0e0fde1 100644 --- a/modules/gapi/misc/python/shadow_gapi.hpp +++ b/modules/gapi/misc/python/shadow_gapi.hpp @@ -5,8 +5,9 @@ namespace cv { struct GAPI_EXPORTS_W_SIMPLE GCompileArg { - GAPI_WRAP GCompileArg(gapi::GKernelPackage pkg); - GAPI_WRAP GCompileArg(gapi::GNetPackage pkg); + GAPI_WRAP GCompileArg(gapi::GKernelPackage arg); + GAPI_WRAP GCompileArg(gapi::GNetPackage arg); + GAPI_WRAP GCompileArg(gapi::streaming::queue_capacity arg); }; class GAPI_EXPORTS_W_SIMPLE GInferInputs diff --git a/modules/gapi/misc/python/test/test_gapi_streaming.py b/modules/gapi/misc/python/test/test_gapi_streaming.py index 7ede1b5cf3..d7914c5157 100644 --- a/modules/gapi/misc/python/test/test_gapi_streaming.py +++ b/modules/gapi/misc/python/test/test_gapi_streaming.py @@ -261,6 +261,7 @@ 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']]) @@ -307,6 +308,49 @@ try: self.assertLess(0, none_counter) + def test_compile_streaming_empty(self): + g_in = cv.GMat() + comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3)) + comp.compileStreaming() + + + def test_compile_streaming_args(self): + g_in = cv.GMat() + comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3)) + comp.compileStreaming(cv.gapi.compile_args(cv.gapi.streaming.queue_capacity(1))) + + + def test_compile_streaming_descr_of(self): + g_in = cv.GMat() + comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3)) + img = np.zeros((3,300,300), dtype=np.float32) + comp.compileStreaming(cv.gapi.descr_of(img)) + + + def test_compile_streaming_descr_of_and_args(self): + g_in = cv.GMat() + comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3)) + img = np.zeros((3,300,300), dtype=np.float32) + comp.compileStreaming(cv.gapi.descr_of(img), + cv.gapi.compile_args(cv.gapi.streaming.queue_capacity(1))) + + + def test_compile_streaming_meta(self): + g_in = cv.GMat() + comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3)) + img = np.zeros((3,300,300), dtype=np.float32) + comp.compileStreaming([cv.GMatDesc(cv.CV_8U, 3, (300, 300))]) + + + def test_compile_streaming_meta_and_args(self): + g_in = cv.GMat() + comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3)) + img = np.zeros((3,300,300), dtype=np.float32) + comp.compileStreaming([cv.GMatDesc(cv.CV_8U, 3, (300, 300))], + cv.gapi.compile_args(cv.gapi.streaming.queue_capacity(1))) + + + except unittest.SkipTest as e: message = str(e)